import type { KpiRowDTO, KpiRowStatus, KpiSectionDTO } from "@/lib/kpis/types";
import { isDueSoonIso, isOverdueIso } from "@/lib/kpis/date";

export type StatusDistributionItem = {
  status: KpiRowStatus;
  label: string;
  value: number;
};

export type DueBucketItem = {
  key: "overdue" | "due_7d" | "due_14d" | "later" | "no_due";
  label: string;
  value: number;
};

export type KpiSectionHealth = {
  sectionId: string;
  sectionKey: string;
  label: string;
  ownerTeamLabel: string | null;
  totalRows: number;
  riskRows: number;
  dueSoonRows: number;
  worstCompliancePct: number | null;
  healthScore: number;
};

const STATUS_LABELS: Record<KpiRowStatus, string> = {
  on_track: "En ruta",
  watch: "Seguimiento",
  risk: "Riesgo",
  no_score: "Sin score",
};

function clamp(value: number, min: number, max: number): number {
  return Math.min(max, Math.max(min, value));
}

function healthScoreForSection(rows: KpiRowDTO[]): number {
  if (rows.length === 0) {
    return 0;
  }

  const scoredRows = rows.filter((row) => row.status !== "no_score");
  const complianceAvg =
    scoredRows.length > 0
      ? scoredRows.reduce((acc, row) => acc + (row.compliancePct ?? 0), 0) / scoredRows.length
      : 0;

  const riskPenalty = rows.filter((row) => row.status === "risk").length / rows.length;
  const watchPenalty = rows.filter((row) => row.status === "watch").length / rows.length;
  const noScorePenalty = rows.filter((row) => row.status === "no_score").length / rows.length;
  const penalty = riskPenalty * 30 + watchPenalty * 12 + noScorePenalty * 8;

  return Math.round(clamp(complianceAvg - penalty, 0, 100) * 10) / 10;
}

export function buildStatusDistribution(rows: KpiRowDTO[]): StatusDistributionItem[] {
  const base: StatusDistributionItem[] = [
    { status: "on_track", label: STATUS_LABELS.on_track, value: 0 },
    { status: "watch", label: STATUS_LABELS.watch, value: 0 },
    { status: "risk", label: STATUS_LABELS.risk, value: 0 },
    { status: "no_score", label: STATUS_LABELS.no_score, value: 0 },
  ];

  for (const row of rows) {
    const item = base.find((candidate) => candidate.status === row.status);
    if (item) {
      item.value += 1;
    }
  }

  return base;
}

export function buildDueBuckets(rows: KpiRowDTO[], referenceIso: string): DueBucketItem[] {
  const due14Reference = new Date(`${referenceIso}T00:00:00.000Z`).getTime() + 14 * 24 * 60 * 60 * 1000;
  const buckets: DueBucketItem[] = [
    { key: "overdue", label: "Vencido", value: 0 },
    { key: "due_7d", label: "0-7 días", value: 0 },
    { key: "due_14d", label: "8-14 días", value: 0 },
    { key: "later", label: "15+ días", value: 0 },
    { key: "no_due", label: "Sin fecha", value: 0 },
  ];

  for (const row of rows) {
    if (!row.dueDate) {
      buckets.find((bucket) => bucket.key === "no_due")!.value += 1;
      continue;
    }

    if (isOverdueIso(row.dueDate, referenceIso)) {
      buckets.find((bucket) => bucket.key === "overdue")!.value += 1;
      continue;
    }

    if (isDueSoonIso(row.dueDate, referenceIso, 7)) {
      buckets.find((bucket) => bucket.key === "due_7d")!.value += 1;
      continue;
    }

    const dueAt = new Date(`${row.dueDate}T00:00:00.000Z`).getTime();
    if (dueAt <= due14Reference) {
      buckets.find((bucket) => bucket.key === "due_14d")!.value += 1;
      continue;
    }

    buckets.find((bucket) => bucket.key === "later")!.value += 1;
  }

  return buckets;
}

export function buildSectionHealth(sections: KpiSectionDTO[], referenceIso: string): KpiSectionHealth[] {
  return sections.map((section) => {
    const worstCompliancePct = section.rows.reduce<number | null>((worst, row) => {
      if (row.compliancePct === null) {
        return worst;
      }

      if (worst === null) {
        return row.compliancePct;
      }

      return Math.min(worst, row.compliancePct);
    }, null);

    return {
      sectionId: section.id,
      sectionKey: section.sectionKey,
      label: section.rawSectionLabel,
      ownerTeamLabel: section.ownerTeamLabel,
      totalRows: section.rows.length,
      riskRows: section.rows.filter((row) => row.status === "risk").length,
      dueSoonRows: section.rows.filter((row) => row.dueDate && isDueSoonIso(row.dueDate, referenceIso, 7)).length,
      worstCompliancePct: worstCompliancePct === null ? null : Math.round(worstCompliancePct * 10) / 10,
      healthScore: healthScoreForSection(section.rows),
    };
  });
}

export function summaryDelta(current: number, previous: number | undefined): number | null {
  if (typeof previous !== "number" || Number.isNaN(previous)) {
    return null;
  }

  return Math.round((current - previous) * 10) / 10;
}
