import { getRequirementCoverageSummary } from './version-plan';
import type { VersionPlan } from './version-plan';
import type { Requirement } from './requirement';
import type { DevTask } from './dev-task';
import type { TestCase } from './test-case';
import type { VersionWithContext } from './derive';
import { STATUS_PROGRESS, getEstimateHours } from './dev-task';

/**
 * 计算单个版本的整体进度（0-100）
 * 算法：调研/产品/UI 计划进度 + 开发任务加权进度 + 测试执行率，求平均
 */
export function calcVersionProgress(
  versionId: string,
  plans: VersionPlan[],
  requirements: Requirement[],
  devTasks: DevTask[],
  testCases: TestCase[],
): number {
  const vPlans = plans.filter((p) => p.versionId === versionId);
  const vReqs = requirements.filter((r) => r.versionId === versionId);
  const vReqIds = new Set(vReqs.map((r) => r.id));
  const vDevTasks = devTasks.filter((t) => isDevTaskInVersion(t, versionId, vReqIds));
  const vTestCases = testCases.filter((c) => c.versionId === versionId);

  return calcScopedVersionProgress(vPlans, vDevTasks, vTestCases);
}

export function calcScopedVersionProgress(
  vPlans: VersionPlan[],
  vDevTasks: DevTask[],
  vTestCases: TestCase[],
): number {
  const segments: number[] = [];

  const researchPlans = vPlans.filter((p) => p.type === 'research');
  if (researchPlans.length > 0) {
    const totals = researchPlans.reduce((acc, p) => {
      const tasks = p.tasks || [];
      acc.total += tasks.length;
      acc.done += tasks.filter((t) => t.status === 'completed').length;
      return acc;
    }, { total: 0, done: 0 });
    segments.push(totals.total > 0 ? (totals.done / totals.total) * 100 : 0);
  }

  const productPlans = vPlans.filter((p) => p.type === 'product');
  if (productPlans.length > 0) {
    const totals = productPlans.reduce((acc, p) => {
      const summary = getRequirementCoverageSummary(p);
      acc.total += summary.total;
      acc.done += summary.completed;
      return acc;
    }, { total: 0, done: 0 });
    segments.push(totals.total > 0 ? (totals.done / totals.total) * 100 : 0);
  }

  const uiPlans = vPlans.filter((p) => p.type === 'ui');
  if (uiPlans.length > 0) {
    const totals = uiPlans.reduce((acc, p) => {
      const summary = getRequirementCoverageSummary(p);
      acc.total += summary.total;
      acc.done += summary.completed;
      return acc;
    }, { total: 0, done: 0 });
    segments.push(totals.total > 0 ? (totals.done / totals.total) * 100 : 0);
  }

  if (vDevTasks.length > 0) {
    const totalEstimate = vDevTasks.reduce((sum, t) => sum + getEstimateHours(t), 0);
    let devProgress: number;
    if (totalEstimate === 0) {
      devProgress = vDevTasks.reduce((sum, t) => sum + STATUS_PROGRESS[t.status], 0) / vDevTasks.length;
    } else {
      const weighted = vDevTasks.reduce((sum, t) => sum + getEstimateHours(t) * STATUS_PROGRESS[t.status], 0);
      devProgress = weighted / totalEstimate;
    }
    segments.push(devProgress);
  }

  if (vTestCases.length > 0) {
    const executed = vTestCases.filter((c) => c.status === 'passed' || c.status === 'failed' || c.status === 'blocked').length;
    segments.push((executed / vTestCases.length) * 100);
  }

  return segments.length > 0 ? Math.round(segments.reduce((s, x) => s + x, 0) / segments.length) : 0;
}

function isDevTaskInVersion(task: DevTask, versionId: string, requirementIds: Set<string>): boolean {
  if (task.versionId) return task.versionId === versionId;
  return requirementIds.has(task.requirementId);
}

/**
 * 批量为多个版本算进度，返回 versionId → 进度 (0-100) 的 Map
 */
export function buildVersionProgressMap(
  versions: VersionWithContext[],
  plans: VersionPlan[],
  requirements: Requirement[],
  devTasks: DevTask[],
  testCases: TestCase[],
): Record<string, number> {
  const plansByVersion = groupByVersionId(plans);
  const requirementVersionMap = new Map<string, string>();
  for (const requirement of requirements) {
    if (!requirement.versionId) continue;
    requirementVersionMap.set(requirement.id, requirement.versionId);
  }

  const devTasksByVersion = new Map<string, DevTask[]>();
  for (const task of devTasks) {
    const versionId = task.versionId || requirementVersionMap.get(task.requirementId);
    if (!versionId) continue;
    const items = devTasksByVersion.get(versionId) ?? [];
    items.push(task);
    devTasksByVersion.set(versionId, items);
  }

  const testCasesByVersion = groupByVersionId(testCases);
  const map: Record<string, number> = {};
  for (const v of versions) {
    map[v.id] = calcScopedVersionProgress(
      plansByVersion.get(v.id) ?? [],
      devTasksByVersion.get(v.id) ?? [],
      testCasesByVersion.get(v.id) ?? [],
    );
  }
  return map;
}

function groupByVersionId<T extends { versionId: string }>(items: T[]): Map<string, T[]> {
  const map = new Map<string, T[]>();
  for (const item of items) {
    const group = map.get(item.versionId) ?? [];
    group.push(item);
    map.set(item.versionId, group);
  }
  return map;
}
