import assert from 'node:assert/strict';
import test from 'node:test';
import { calcXiaobaoVersionRisk } from './xiaobao-risk';
import type { DevTask } from './dev-task';
import type { TestCase } from './test-case';
import type { Bug } from './bug';
import type { VersionDailyEvidence } from './xiaobao-risk-evidence';

function version(patch: any = {}) {
  return {
    id: 'ver-1',
    name: 'V1.0',
    status: 'developing',
    productName: 'FTB',
    projectName: '项目管理',
    expectedReleaseDate: '2026-07-03T10:00:00.000Z',
    members: [{ name: '张三', role: 'frontend' }],
    ...patch,
  };
}

function devTask(patch: Partial<DevTask> = {}): DevTask {
  return {
    id: 'dev-1',
    taskNo: 'DEV-001',
    requirementId: 'req-1',
    title: '实现版本风险页',
    categoryId: 'frontend',
    assigneeId: 'm-1',
    priority: 'P1',
    expectedStartAt: '2026-07-01T09:00:00.000Z',
    expectedEndAt: '2026-07-03T18:00:00.000Z',
    estimateHours: 40,
    status: 'todo',
    isBlocked: false,
    createdBy: 'm-1',
    createdAt: '2026-07-01T09:00:00.000Z',
    updatedAt: '2026-07-01T09:00:00.000Z',
    ...patch,
  };
}

function testCase(patch: Partial<TestCase> = {}): TestCase {
  return {
    id: 'tc-1',
    caseNo: 'TC-001',
    versionId: 'ver-1',
    title: '验收版本风险页',
    categoryId: 'ui-interaction',
    priority: 'P1',
    assigneeId: 'm-2',
    status: 'pending',
    estimateHours: 16,
    createdBy: 'm-2',
    createdAt: '2026-07-01T09:00:00.000Z',
    updatedAt: '2026-07-01T09:00:00.000Z',
    ...patch,
  };
}

function bug(patch: Partial<Bug> = {}): Bug {
  return {
    id: 'bug-1',
    bugNo: 'BUG-001',
    versionId: 'ver-1',
    testCaseId: 'tc-1',
    title: '发布阻断缺陷',
    description: '关键流程无法通过',
    severity: 'critical',
    priority: 'P1',
    reportedBy: 'm-2',
    assigneeId: 'm-1',
    status: 'open',
    createdAt: '2026-07-01T09:00:00.000Z',
    updatedAt: '2026-07-01T09:00:00.000Z',
    ...patch,
  };
}

test('calcXiaobaoVersionRisk predicts delay when remaining work exceeds release date', () => {
  const risk = calcXiaobaoVersionRisk({
    version: version(),
    devTasks: [devTask()],
    testCases: [testCase()],
    bugs: [],
    now: new Date('2026-07-02T01:00:00.000Z'),
  });

  assert.equal(risk.riskLevel, 'likely_delayed');
  assert.ok(risk.riskScore >= 70);
  assert.ok(risk.delayDays > 0);
  assert.ok(risk.reasons.some((reason: { key: string }) => reason.key === 'remaining_work'));
});

test('calcXiaobaoVersionRisk marks blocked when critical Bug / blocked dev task / failed test exist', () => {
  const risk = calcXiaobaoVersionRisk({
    version: version(),
    devTasks: [devTask({ isBlocked: true, blockReason: '依赖接口未完成' })],
    testCases: [testCase({ status: 'failed', failReason: '核心流程失败' })],
    bugs: [bug()],
    now: new Date('2026-07-02T01:00:00.000Z'),
  });

  assert.equal(risk.riskLevel, 'blocked');
  assert.ok(risk.reasons.some((reason: { key: string }) => reason.key === 'critical_bug'));
  assert.ok(risk.reasons.some((reason: { key: string }) => reason.key === 'blocked_work'));
});

test('calcXiaobaoVersionRisk preserves daily evidence on the returned risk object', () => {
  const dailyEvidence: VersionDailyEvidence = {
    todayDeliveries: [{ id: 'ev-1', title: '提交提测', summary: '完成核心流程', occurredAt: '2026-07-02T02:00:00.000Z' }],
    todayProgress: [],
    todayCreations: [],
    todayRisks: [],
    progressNotes: [],
    needsProgressItems: [],
    recentActivityCount: 1,
    totalActivityCount: 1,
    todayActualHours: 2,
    lastActivityAt: '2026-07-02T02:00:00.000Z',
  };

  const risk = calcXiaobaoVersionRisk({
    version: version(),
    devTasks: [],
    testCases: [],
    bugs: [],
    dailyEvidence,
    now: new Date('2026-07-02T01:00:00.000Z'),
  });

  assert.equal(risk.dailyEvidence, dailyEvidence);
});

test('calcXiaobaoVersionRisk uses silent risks from daily evidence', () => {
  const silentRisk = {
    key: 'no_progress_today',
    title: '今日无进展',
    detail: '进行中的任务今天没有动态。',
    itemId: 'dev-1',
    itemType: 'dev_task' as const,
  };
  const dailyEvidence: VersionDailyEvidence = {
    todayDeliveries: [],
    todayProgress: [],
    todayCreations: [],
    todayRisks: [],
    progressNotes: [],
    needsProgressItems: [],
    recentActivityCount: 0,
    totalActivityCount: 0,
    todayActualHours: 0,
    silentRisks: [silentRisk],
  };

  const risk = calcXiaobaoVersionRisk({
    version: version(),
    devTasks: [],
    testCases: [],
    bugs: [],
    dailyEvidence,
    now: new Date('2026-07-02T01:00:00.000Z'),
  });

  assert.deepEqual(risk.silentRisks, [silentRisk]);
  assert.equal(risk.signals.silentRiskCount, 1);
  assert.ok(risk.riskScore > 0);
  assert.ok(risk.reasons.some((reason: { key: string }) => reason.key === 'silent_risk'));
});

test('calcXiaobaoVersionRisk preserves null expected release date as a compatible output value', () => {
  const versionWithNullRelease = {
    id: 'ver-null-release',
    name: 'V1.1',
    expectedReleaseDate: null,
    members: [],
  };

  const risk = calcXiaobaoVersionRisk({
    version: versionWithNullRelease,
    devTasks: [],
    testCases: [],
    bugs: [],
    now: new Date('2026-07-02T01:00:00.000Z'),
  });

  assert.equal(risk.expectedReleaseDate, null);
});

test('calcXiaobaoVersionRisk preserves version display context for AI interpretation', () => {
  const risk = calcXiaobaoVersionRisk({
    version: version({ name: 'V2.0', productName: 'FTB', projectName: 'Project PM' }),
    devTasks: [],
    testCases: [],
    bugs: [],
    now: new Date('2026-07-02T01:00:00.000Z'),
  });

  assert.equal(risk.versionName, 'V2.0');
  assert.equal(risk.productName, 'FTB');
  assert.equal(risk.projectName, 'Project PM');
});
