import assert from 'node:assert/strict';
import test from 'node:test';
import { buildRiskInsightSignature } from './xiaobao-risk-ai';
import type { XiaobaoRiskInsightCacheItem } from './xiaobao-risk-cache';
import type { XiaobaoVersionRisk } from './xiaobao-risk';
import { attachXiaobaoRiskSuggestion, buildXiaobaoRiskInsightPendingKey } from './xiaobao-risk-suggestion';

function risk(patch: Partial<XiaobaoVersionRisk> = {}): XiaobaoVersionRisk {
  return {
    versionId: 'ver-1',
    versionName: 'V1.0',
    productId: 'prod-1',
    productName: 'Product A',
    projectId: 'proj-1',
    projectName: 'Project A',
    riskScore: 68,
    riskLevel: 'attention',
    expectedReleaseDate: '2026-07-05',
    confidence: 80,
    confidenceLevel: 'high',
    forecastReleaseDate: '2026-07-05T10:00:00.000Z',
    delayDays: 0,
    remainingWorkHours: 8,
    reasons: [
      {
        key: 'remaining_work',
        title: '剩余工作量',
        detail: '预计还剩 8h 工作量。',
        severity: 'warning',
      },
    ],
    silentRisks: [],
    signals: {
      unfinishedCount: 1,
      openBugCount: 0,
      criticalBugCount: 0,
      failedTestCount: 0,
      blockedCount: 0,
      silentRiskCount: 0,
      daysToExpectedRelease: 2,
    },
    currentSnapshot: {
      versionId: 'ver-1',
      date: '2026-06-30',
      riskScore: 68,
      riskLevel: 'attention',
      forecastReleaseDate: '2026-07-05T10:00:00.000Z',
      openBugCount: 0,
      criticalBugCount: 0,
      failedTestCount: 0,
      blockedCount: 0,
      silentRiskCount: 0,
      confidence: 80,
      createdAt: '2026-06-30T10:00:00.000Z',
    },
    trend: { direction: 'flat', delta: 0, summary: '风险保持稳定。', pattern: 'stable' },
    ...patch,
  };
}

function insight(itemRisk: XiaobaoVersionRisk, patch: Partial<XiaobaoRiskInsightCacheItem> = {}): XiaobaoRiskInsightCacheItem {
  return {
    versionId: itemRisk.versionId,
    riskSignature: buildRiskInsightSignature(itemRisk),
    insight: {
      summary: '旧的小宝建议',
      why: ['仍有工作未完成'],
      forecast: '当前建议继续观察。',
      suggestedActions: ['确认剩余任务负责人和完成时间。'],
      ownerHints: [],
      generatedAt: '2026-06-30T09:00:00.000Z',
    },
    generatedAt: '2026-06-30T09:00:00.000Z',
    ...patch,
  };
}

test('attachXiaobaoRiskSuggestion provides a rule suggestion when AI cache is empty', () => {
  const result = attachXiaobaoRiskSuggestion(risk(), {
    insights: [],
    pendingInsightKeys: [],
  });

  assert.equal(result.aiInsightSource, 'rule');
  assert.equal(result.aiInsightUpdating, false);
  assert.ok(result.aiInsight?.summary);
  assert.ok(result.aiInsight?.forecast);
  assert.ok((result.aiInsight?.suggestedActions.length ?? 0) > 0);
});

test('attachXiaobaoRiskSuggestion keeps previous AI suggestion while a new one is updating', () => {
  const previous = risk({ riskScore: 52, riskLevel: 'attention' });
  const current = risk({ riskScore: 82, riskLevel: 'at_risk', delayDays: 1 });
  const pendingKey = buildXiaobaoRiskInsightPendingKey(current);

  const result = attachXiaobaoRiskSuggestion(current, {
    insights: [insight(previous)],
    pendingInsightKeys: [pendingKey],
  });

  assert.equal(result.aiInsightSource, 'previous_ai');
  assert.equal(result.aiInsightUpdating, true);
  assert.equal(result.aiInsight?.summary, '旧的小宝建议');
});

test('attachXiaobaoRiskSuggestion hides stale pending update notices', () => {
  const previous = risk({ riskScore: 52, riskLevel: 'attention' });
  const current = risk({ riskScore: 82, riskLevel: 'at_risk', delayDays: 1 });
  const pendingKey = buildXiaobaoRiskInsightPendingKey(current);

  const result = attachXiaobaoRiskSuggestion(current, {
    insights: [insight(previous)],
    pendingInsightKeys: [pendingKey],
    pendingInsightAttempts: { [pendingKey]: '2026-06-30T10:00:00.000Z' },
    now: new Date('2026-06-30T10:04:00.000Z'),
  });

  assert.equal(result.aiInsightSource, 'previous_ai');
  assert.equal(result.aiInsightUpdating, false);
  assert.equal(result.aiInsight?.summary, insight(previous).insight.summary);
});

test('attachXiaobaoRiskSuggestion uses the current AI suggestion when the signature matches', () => {
  const current = risk({ riskScore: 82, riskLevel: 'at_risk', delayDays: 1 });

  const result = attachXiaobaoRiskSuggestion(current, {
    insights: [insight(current, {
      insight: {
        summary: '新的小宝建议',
        why: ['风险已升高'],
        forecast: '预计延期 1 天。',
        suggestedActions: ['先处理阻塞和失败用例。'],
        ownerHints: [],
        generatedAt: '2026-06-30T10:00:00.000Z',
      },
      generatedAt: '2026-06-30T10:00:00.000Z',
    })],
    pendingInsightKeys: [],
  });

  assert.equal(result.aiInsightSource, 'current_ai');
  assert.equal(result.aiInsightUpdating, false);
  assert.equal(result.aiInsight?.summary, '新的小宝建议');
});

test('buildXiaobaoRiskInsightPendingKey stays stable for refresh-only risk drift', () => {
  const before = risk({
    riskLevel: 'likely_delayed',
    riskScore: 100,
    confidence: 65,
    forecastReleaseDate: '2026-07-14T03:37:15.903Z',
    signals: { ...risk().signals, failedTestCount: 14, silentRiskCount: 58, daysToExpectedRelease: 1 },
    dailyEvidence: {
      todayDeliveries: [],
      todayProgress: [
        { id: 'ev-2', title: 'Progress', summary: 'Fixed login issue.', occurredAt: '2026-06-29T03:37:15.903Z' },
      ],
      todayCreations: [],
      todayRisks: [],
      progressNotes: [],
      needsProgressItems: [],
      recentActivityCount: 12,
      totalActivityCount: 6,
      todayActualHours: 1.5,
      lastActivityAt: '2026-06-29T03:37:15.903Z',
    },
  });
  const after = risk({
    riskLevel: 'likely_delayed',
    riskScore: 100,
    confidence: 65,
    forecastReleaseDate: '2026-07-15T06:21:38.597Z',
    signals: { ...risk().signals, failedTestCount: 14, silentRiskCount: 58, daysToExpectedRelease: 0 },
    dailyEvidence: {
      todayDeliveries: [],
      todayProgress: [
        { id: 'ev-2', title: 'Progress', summary: 'Fixed login issue.', occurredAt: '2026-06-29T06:21:38.597Z' },
      ],
      todayCreations: [],
      todayRisks: [],
      progressNotes: [],
      needsProgressItems: [],
      recentActivityCount: 13,
      totalActivityCount: 6,
      todayActualHours: 3,
      lastActivityAt: '2026-06-29T06:21:38.597Z',
    },
  });

  assert.equal(buildXiaobaoRiskInsightPendingKey(before), buildXiaobaoRiskInsightPendingKey(after));
});

test('buildXiaobaoRiskInsightPendingKey stays stable when only daily report evidence details change', () => {
  const before = risk({
    riskLevel: 'at_risk',
    riskScore: 82,
    confidence: 70,
    dailyEvidence: {
      todayDeliveries: [],
      todayProgress: [
        { id: 'ev-old', title: 'Progress', summary: 'Worked on checkout flow.', occurredAt: '2026-06-30T03:00:00.000Z' },
      ],
      todayCreations: [],
      todayRisks: [],
      progressNotes: [],
      needsProgressItems: [],
      recentActivityCount: 2,
      totalActivityCount: 1,
      todayActualHours: 1,
      lastActivityAt: '2026-06-30T03:00:00.000Z',
    },
  });
  const after = risk({
    riskLevel: 'at_risk',
    riskScore: 82,
    confidence: 70,
    dailyEvidence: {
      todayDeliveries: [],
      todayProgress: [
        { id: 'ev-new', title: 'Progress', summary: 'Updated checkout flow and added handoff notes.', occurredAt: '2026-07-01T04:00:00.000Z' },
        { id: 'ev-new-2', title: 'Progress', summary: 'Confirmed QA scope.', occurredAt: '2026-07-01T05:00:00.000Z' },
      ],
      todayCreations: [],
      todayRisks: [],
      progressNotes: [
        { id: 'note-new', title: 'Note', summary: 'Next work starts tomorrow morning.', occurredAt: '2026-07-01T06:00:00.000Z' },
      ],
      needsProgressItems: [],
      recentActivityCount: 6,
      totalActivityCount: 3,
      todayActualHours: 4,
      lastActivityAt: '2026-07-01T06:00:00.000Z',
    },
  });

  assert.equal(buildXiaobaoRiskInsightPendingKey(before), buildXiaobaoRiskInsightPendingKey(after));
});
