import { ERROR_CODES } from '@insforge/shared-schemas';
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';

// These tests run the real `deno check` (deno binary present in CI/dev). They
// prove the pre-deploy static check rejects the exact class of error that
// wedged project 2mn4wunc (issue #1594): a duplicate top-level declaration that
// builds fine but throws `Identifier '...' has already been declared` at
// isolate warm-up, surfacing only as the opaque "Event iterator validation
// failed".
describe('DenoSubhostingProvider.checkCode (pre-deploy static check)', () => {
  beforeEach(() => {
    vi.resetModules();
    process.env.DENO_DEPLOY_TOKEN = 't';
    process.env.DENO_DEPLOY_ORG_ID = 'o';
  });

  afterEach(() => {
    delete process.env.DENO_DEPLOY_TOKEN;
    delete process.env.DENO_DEPLOY_ORG_ID;
  });

  it('rejects a duplicate top-level declaration with a 400 + the offending identifier', async () => {
    const mod = await import('@/providers/functions/deno-subhosting.provider.js');
    const provider = mod.DenoSubhostingProvider.getInstance();

    // Reproduces dpo_agent.ts:122 from #1594: KILL_SWITCH_DOC_ID declared twice.
    const code = [
      'const KILL_SWITCH_DOC_ID = "global";',
      'export default function (_req: Request): Response {',
      '  return new Response(KILL_SWITCH_DOC_ID);',
      '}',
      'var KILL_SWITCH_DOC_ID = "global";',
    ].join('\n');

    await expect(provider.checkCode(code, 'dpo_agent')).rejects.toMatchObject({
      statusCode: 400,
      code: ERROR_CODES.INVALID_INPUT,
    });

    // The message must name the identifier AND tell the user how to fix it
    // (rename to another name) — not just surface an opaque compiler error.
    await expect(provider.checkCode(code, 'dpo_agent')).rejects.toThrow(/KILL_SWITCH_DOC_ID/);
    await expect(provider.checkCode(code, 'dpo_agent')).rejects.toThrow(
      /declared more than once.*change one of them to another name/s
    );
  }, 60_000);

  it('accepts a valid, import-free function', async () => {
    const mod = await import('@/providers/functions/deno-subhosting.provider.js');
    const provider = mod.DenoSubhostingProvider.getInstance();

    const code = [
      'export default function (_req: Request): Response {',
      '  return new Response("ok");',
      '}',
    ].join('\n');

    await expect(provider.checkCode(code, 'ok_fn')).resolves.toBeUndefined();
  }, 60_000);

  it('is a no-op when Subhosting is not configured (local mode)', async () => {
    delete process.env.DENO_DEPLOY_TOKEN;
    delete process.env.DENO_DEPLOY_ORG_ID;
    const mod = await import('@/providers/functions/deno-subhosting.provider.js');
    const provider = mod.DenoSubhostingProvider.getInstance();

    // Even syntactically broken code resolves when unconfigured — the check only
    // runs in cloud mode; local dev defers to the runtime.
    await expect(
      provider.checkCode('const x = 1; const x = 2;', 'broken')
    ).resolves.toBeUndefined();
  }, 60_000);
});
