import test from 'node:test';
import assert from 'node:assert/strict';
import { randomUUID } from 'node:crypto';

process.env.NODE_ENV = 'test';
process.env.DB_PATH = ':memory:';

const jsonFetch = async (
  baseUrl: string,
  path: string,
  options?: { method?: string; body?: unknown },
) => {
  const res = await fetch(`${baseUrl}${path}`, {
    method: options?.method ?? 'GET',
    headers: options?.body ? { 'Content-Type': 'application/json' } : undefined,
    body: options?.body ? JSON.stringify(options.body) : undefined,
  });

  const text = await res.text();
  let json: any = null;
  try {
    json = text ? JSON.parse(text) : null;
  } catch {
    json = null;
  }
  return { status: res.status, json, text };
};

test('用户任务接口返回未开始/进行中/已结束任务（由前端分组）', async () => {
  const { initDatabase, run } = await import('../api/database');
  await initDatabase();

  const { app } = await import('../api/server');
  const server = app.listen(0);

  try {
    const addr = server.address();
    assert.ok(addr && typeof addr === 'object');
    const baseUrl = `http://127.0.0.1:${addr.port}`;

    const now = Date.now();
    const userId = randomUUID();
    const subjectId = randomUUID();

    const historyTaskId = randomUUID();
    const upcomingTaskId = randomUUID();
    const activeTaskId = randomUUID();

    await run(`INSERT INTO users (id, name, phone, password) VALUES (?, ?, ?, ?)`, [
      userId,
      '测试用户',
      '13800138099',
      '',
    ]);

    await run(
      `INSERT INTO exam_subjects (id, name, type_ratios, category_ratios, total_score, duration_minutes)
       VALUES (?, ?, ?, ?, ?, ?)`,
      [
        subjectId,
        '测试科目',
        JSON.stringify({ single: 100 }),
        JSON.stringify({ 通用: 100 }),
        100,
        60,
      ],
    );

    const historyStartAt = new Date(now - 3 * 24 * 60 * 60 * 1000).toISOString();
    const historyEndAt = new Date(now - 2 * 24 * 60 * 60 * 1000).toISOString();
    const upcomingStartAt = new Date(now + 2 * 24 * 60 * 60 * 1000).toISOString();
    const upcomingEndAt = new Date(now + 3 * 24 * 60 * 60 * 1000).toISOString();
    const activeStartAt = new Date(now - 1 * 24 * 60 * 60 * 1000).toISOString();
    const activeEndAt = new Date(now + 1 * 24 * 60 * 60 * 1000).toISOString();

    await run(
      `INSERT INTO exam_tasks (id, name, subject_id, start_at, end_at, selection_config)
       VALUES (?, ?, ?, ?, ?, ?)`,
      [historyTaskId, '历史任务', subjectId, historyStartAt, historyEndAt, null],
    );
    await run(
      `INSERT INTO exam_tasks (id, name, subject_id, start_at, end_at, selection_config)
       VALUES (?, ?, ?, ?, ?, ?)`,
      [upcomingTaskId, '未开始任务', subjectId, upcomingStartAt, upcomingEndAt, null],
    );
    await run(
      `INSERT INTO exam_tasks (id, name, subject_id, start_at, end_at, selection_config)
       VALUES (?, ?, ?, ?, ?, ?)`,
      [activeTaskId, '进行中任务', subjectId, activeStartAt, activeEndAt, null],
    );

    const linkUserToTask = async (taskId: string) => {
      await run(`INSERT INTO exam_task_users (id, task_id, user_id) VALUES (?, ?, ?)`, [
        randomUUID(),
        taskId,
        userId,
      ]);
    };

    await linkUserToTask(historyTaskId);
    await linkUserToTask(upcomingTaskId);
    await linkUserToTask(activeTaskId);

    const res = await jsonFetch(baseUrl, `/api/exam-tasks/user/${userId}`);
    assert.equal(res.status, 200);
    assert.equal(res.json?.success, true);
    assert.ok(Array.isArray(res.json?.data));

    const names = (res.json?.data as any[]).map((t) => t.name).sort();
    assert.deepEqual(names, ['历史任务', '未开始任务', '进行中任务'].sort());

    const upcoming = (res.json?.data as any[]).find((t) => t.name === '未开始任务');
    assert.ok(upcoming);
    assert.equal(typeof upcoming.startAt, 'string');
    assert.equal(typeof upcoming.endAt, 'string');
  } finally {
    server.close();
  }
});
