import assert from 'node:assert/strict';
import test from 'node:test';

import { __resetApiAvailabilityForTests, resolveApiBase } from './api';
import {
  loadV22RequirementsPage,
  loadV22VersionDetailData,
  loadV22WorkspaceData,
  loadV22XiaobaoWarnings,
} from './v22-api';

test('V2.2 version detail API maps relation rows to existing frontend scope types', async () => {
  const originalFetch = globalThis.fetch;
  const apiBase = resolveApiBase();
  const calls: Array<{ url: string; method: string }> = [];

  globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
    const url = String(input);
    calls.push({ url, method: init?.method ?? 'GET' });
    if (url === `${apiBase}/config/ai`) {
      return jsonResponse({});
    }
    if (url === `${apiBase}/v2.2/versions/version-1/detail-data`) {
      return jsonResponse({
        version: {
          id: 'version-1',
          productId: 'product-1',
          projectId: 'project-1',
          name: 'Project A V1.0',
          releaseDate: '2026-01-20T00:00:00.000Z',
          createdAt: '2026-01-01T00:00:00.000Z',
        },
        requirements: [{
          id: 'req-1',
          productId: 'product-1',
          projectId: 'project-1',
          versionId: 'version-1',
          code: 'REQ-001',
          title: 'Login',
          description: 'Password login',
          status: 'adopted',
          priority: 1,
          type: 'feature',
          sourceType: 'customer',
          sourceTarget: 'ACME',
          platform: 'web, ios',
          creatorId: 'member-1',
          createdAt: '2026-01-01T00:00:00.000Z',
        }],
        versionPlans: [{
          id: 'plan-1',
          versionId: 'version-1',
          type: 'research',
          title: 'Research login',
          status: 'pending',
          ownerId: 'member-1',
          expectedStartAt: '2026-01-01',
          expectedEndAt: '2026-01-05T18:00:00.000Z',
          requirementCoverage: [{ requirementId: 'req-1', status: 'completed', updatedAt: '2026-01-02T00:00:00.000Z', updatedBy: 'member-1' }],
          logs: [],
          createdAt: '2026-01-01T00:00:00.000Z',
        }],
        devTasks: [{
          id: 'dev-1',
          versionId: 'version-1',
          requirementId: 'req-1',
          categoryId: 'cat-dev',
          code: 'DEV-001',
          title: 'Build login',
          description: 'Implement login',
          status: 'in_progress',
          priority: 2,
          assigneeId: 'member-2',
          creatorId: 'member-1',
          isBlocked: false,
          expectedStartAt: '2026-01-02T09:00:00.000Z',
          expectedEndAt: '2026-01-03T18:00:00.000Z',
          startDate: '2026-01-02T09:00:00.000Z',
          completedAt: null,
          estimateHours: 8,
          references: [{ type: 'requirement', id: 'req-1', label: 'REQ-001' }],
          aiDraft: false,
          createdAt: '2026-01-02T08:00:00.000Z',
          updatedAt: '2026-01-02T09:00:00.000Z',
        }],
        testCases: [{
          id: 'tc-1',
          versionId: 'version-1',
          requirementId: 'req-1',
          categoryId: 'cat-test',
          code: 'TC-001',
          title: 'Verify login',
          description: 'Check password login',
          status: 'pending',
          roundNo: 1,
          priority: 3,
          assigneeId: 'member-3',
          creatorId: 'member-1',
          references: [],
          aiDraft: false,
          createdAt: '2026-01-03T08:00:00.000Z',
          updatedAt: '2026-01-03T08:00:00.000Z',
        }],
        bugs: [{
          id: 'bug-1',
          versionId: 'version-1',
          testCaseId: 'tc-1',
          code: 'BUG-001',
          title: 'Login error',
          description: 'Wrong prompt',
          status: 'open',
          severity: 'major',
          priority: 0,
          assigneeId: 'member-2',
          reporterId: 'member-3',
          createdAt: '2026-01-04T08:00:00.000Z',
          updatedAt: '2026-01-04T08:00:00.000Z',
        }],
      });
    }
    throw new Error(`Unexpected fetch ${url}`);
  }) as typeof fetch;

  try {
    __resetApiAvailabilityForTests();
    const result = await loadV22VersionDetailData('version-1');

    assert.equal(calls[1].url, `${apiBase}/v2.2/versions/version-1/detail-data`);
    assert.equal(result.scope.requirements[0].typeId, 'feature');
    assert.deepEqual(result.scope.requirements[0].platforms, ['web', 'ios']);
    assert.equal(result.scope.requirements[0].priority, 'P1');
    assert.equal(result.scope.requirements[0].creator, 'member-1');
    assert.equal(result.scope.devTasks[0].taskNo, 'DEV-001');
    assert.equal(result.scope.devTasks[0].actualStartAt, '2026-01-02T09:00:00.000Z');
    assert.equal(result.scope.devTasks[0].actualEndAt, undefined);
    assert.equal(result.scope.devTasks[0].createdBy, 'member-1');
    assert.equal(result.scope.testCases[0].caseNo, 'TC-001');
    assert.equal(result.scope.testCases[0].createdBy, 'member-1');
    assert.equal(result.scope.bugs[0].bugNo, 'BUG-001');
    assert.equal(result.scope.bugs[0].reportedBy, 'member-3');
    assert.equal(result.scope.plans[0].owner, 'member-1');
    assert.equal(result.scope.plans[0].startTime, '2026-01-01T00:00:00.000Z');
    assert.equal(result.scope.plansByType.research[0].id, 'plan-1');
    assert.equal(result.scope.requirementIdSet.has('req-1'), true);
  } finally {
    globalThis.fetch = originalFetch;
  }
});

test('V2.2 list APIs build scoped query strings without full-table reads', async () => {
  const originalFetch = globalThis.fetch;
  const apiBase = resolveApiBase();
  const urls: string[] = [];

  globalThis.fetch = (async (input: RequestInfo | URL) => {
    const url = String(input);
    urls.push(url);
    if (url === `${apiBase}/config/ai`) return jsonResponse({});
    if (url.startsWith(`${apiBase}/v2.2/requirements?`)) return jsonResponse({ items: [], nextCursor: 'req-2' });
    if (url.startsWith(`${apiBase}/v2.2/workspace?`)) return jsonResponse({ versionPlans: [], devTasks: [], testCases: [], bugs: [] });
    if (url.startsWith(`${apiBase}/v2.2/xiaobao-warning?`)) return jsonResponse([]);
    throw new Error(`Unexpected fetch ${url}`);
  }) as typeof fetch;

  try {
    __resetApiAvailabilityForTests();
    await loadV22RequirementsPage({
      productId: 'product-1',
      projectId: 'project-1',
      status: 'adopted',
      priority: 'P1',
      type: 'feature',
      q: '登录',
      sort: 'created_at_asc',
      cursor: 'req-1',
      limit: 50,
    });
    await loadV22WorkspaceData('member-1');
    await loadV22XiaobaoWarnings({ userId: 'member-1' });

    const requirementUrl = new URL(urls[1]);
    assert.equal(requirementUrl.pathname.endsWith('/v2.2/requirements'), true);
    assert.equal(requirementUrl.searchParams.get('productId'), 'product-1');
    assert.equal(requirementUrl.searchParams.get('projectId'), 'project-1');
    assert.equal(requirementUrl.searchParams.get('status'), 'adopted');
    assert.equal(requirementUrl.searchParams.get('priority'), 'P1');
    assert.equal(requirementUrl.searchParams.get('type'), 'feature');
    assert.equal(requirementUrl.searchParams.get('q'), '登录');
    assert.equal(requirementUrl.searchParams.get('sort'), 'created_at_asc');
    assert.equal(requirementUrl.searchParams.get('cursor'), 'req-1');
    assert.equal(requirementUrl.searchParams.get('limit'), '50');
    assert.equal(new URL(urls[2]).searchParams.get('userId'), 'member-1');
    assert.equal(new URL(urls[3]).searchParams.get('userId'), 'member-1');
  } finally {
    globalThis.fetch = originalFetch;
  }
});

function jsonResponse(body: unknown): Response {
  return new Response(JSON.stringify(body), {
    status: 200,
    headers: { 'Content-Type': 'application/json' },
  });
}
