import { describe, expect, it } from "vitest";
import {
  buildReportAnalytics,
  type ReportDataset,
  type ReportFilters
} from "@/lib/report-analytics";

const dataset: ReportDataset = {
  year: 2026,
  defaultComparisonMonth: 4,
  sponsors: [
    { id: "s1", name: "المتبرع الأول" },
    { id: "s2", name: "المتبرع الثاني" }
  ],
  payments: [
    {
      id: "p0",
      sponsorshipId: "sp0",
      sponsorId: "s0",
      sponsorName: "المتبرع السابق",
      sponsorPhone: null,
      orphanId: "o0",
      orphanName: "الحالة السابقة",
      caseNumber: "000",
      year: 2025,
      month: 12,
      expectedAmount: 40_000,
      receivedAmount: 40_000,
      paymentStatus: "paid",
      paymentDate: "2025-12-05"
    },
    {
      id: "p1",
      sponsorshipId: "sp1",
      sponsorId: "s1",
      sponsorName: "المتبرع الأول",
      sponsorPhone: null,
      orphanId: "o1",
      orphanName: "الحالة الأولى",
      caseNumber: "001",
      year: 2026,
      month: 1,
      expectedAmount: 50_000,
      receivedAmount: 50_000,
      paymentStatus: "paid",
      paymentDate: "2026-01-05"
    },
    {
      id: "p2",
      sponsorshipId: "sp2",
      sponsorId: "s2",
      sponsorName: "المتبرع الثاني",
      sponsorPhone: null,
      orphanId: "o1",
      orphanName: "الحالة الأولى",
      caseNumber: "001",
      year: 2026,
      month: 1,
      expectedAmount: 30_000,
      receivedAmount: 30_000,
      paymentStatus: "paid",
      paymentDate: "2026-01-07"
    },
    {
      id: "p3",
      sponsorshipId: "sp1",
      sponsorId: "s1",
      sponsorName: "المتبرع الأول",
      sponsorPhone: null,
      orphanId: "o1",
      orphanName: "الحالة الأولى",
      caseNumber: "001",
      year: 2026,
      month: 2,
      expectedAmount: 50_000,
      receivedAmount: 50_000,
      paymentStatus: "paid",
      paymentDate: "2026-02-05"
    },
    {
      id: "p4",
      sponsorshipId: "sp1",
      sponsorId: "s1",
      sponsorName: "المتبرع الأول",
      sponsorPhone: null,
      orphanId: "o1",
      orphanName: "الحالة الأولى",
      caseNumber: "001",
      year: 2026,
      month: 3,
      expectedAmount: 50_000,
      receivedAmount: 0,
      paymentStatus: "unpaid",
      paymentDate: null
    },
    {
      id: "p5",
      sponsorshipId: "sp1",
      sponsorId: "s1",
      sponsorName: "المتبرع الأول",
      sponsorPhone: null,
      orphanId: "o1",
      orphanName: "الحالة الأولى",
      caseNumber: "001",
      year: 2026,
      month: 4,
      expectedAmount: 50_000,
      receivedAmount: 0,
      paymentStatus: "unpaid",
      paymentDate: null
    }
  ],
  transfers: [
    {
      id: "t1",
      orphanId: "o1",
      orphanName: "الحالة الأولى",
      caseNumber: "001",
      sponsorIds: ["s1", "s2"],
      sponsorNames: ["المتبرع الأول", "المتبرع الثاني"],
      year: 2026,
      month: 1,
      amount: 80_000,
      transferDate: "2026-01-10",
      hasReceipt: true
    },
    {
      id: "t2",
      orphanId: "o1",
      orphanName: "الحالة الأولى",
      caseNumber: "001",
      sponsorIds: ["s1"],
      sponsorNames: ["المتبرع الأول"],
      year: 2026,
      month: 4,
      amount: 50_000,
      transferDate: "2026-04-10",
      hasReceipt: false
    }
  ],
  sponsorships: [
    {
      id: "sp1",
      sponsorId: "s1",
      sponsorName: "المتبرع الأول",
      orphanId: "o1",
      orphanName: "الحالة الأولى",
      caseNumber: "001",
      monthlyAmount: 50_000,
      status: "active",
      startDate: "2026-01-01",
      endDate: null
    },
    {
      id: "sp2",
      sponsorId: "s2",
      sponsorName: "المتبرع الثاني",
      orphanId: "o1",
      orphanName: "الحالة الأولى",
      caseNumber: "001",
      monthlyAmount: 30_000,
      status: "active",
      startDate: "2026-01-01",
      endDate: null
    },
    {
      id: "sp3",
      sponsorId: "s1",
      sponsorName: "المتبرع الأول",
      orphanId: "o2",
      orphanName: "الحالة الثانية",
      caseNumber: "002",
      monthlyAmount: 20_000,
      status: "ended",
      startDate: "2026-01-01",
      endDate: "2026-02-28"
    }
  ],
  orphans: [
    {
      id: "o1",
      name: "الحالة الأولى",
      caseNumber: "001",
      status: "partially_covered",
      monthlyNeed: 100_000,
      coveredAmount: 80_000,
      missingItems: ["صورة شهادة وفاة الأب"],
      missingDocumentItems: ["صورة شهادة وفاة الأب"],
      completionPercentage: 93
    },
    {
      id: "o2",
      name: "الحالة الثانية",
      caseNumber: "002",
      status: "available",
      monthlyNeed: 50_000,
      coveredAmount: 0,
      missingItems: ["العنوان", "صورة شهادة وفاة الأب"],
      missingDocumentItems: ["صورة شهادة وفاة الأب"],
      completionPercentage: 86
    }
  ],
  history: {
    periods: [
      { year: 2025, month: 12 },
      { year: 2026, month: 1 },
      { year: 2026, month: 2 },
      { year: 2026, month: 3 },
      { year: 2026, month: 4 }
    ],
    orphanSnapshots: [
      {
        year: 2025,
        month: 12,
        orphanId: "o0",
        name: "الحالة السابقة",
        caseNumber: "000",
        monthlyNeed: 40_000,
        status: "fully_covered",
        createdAt: "2025-12-01T00:00:00Z"
      },
      ...[1, 2, 3, 4].map((month) => ({
        year: 2026,
        month,
        orphanId: "o1",
        name: "الحالة الأولى",
        caseNumber: "001",
        monthlyNeed: 100_000,
        status: "partially_covered" as const,
        createdAt: "2026-01-01T00:00:00Z"
      })),
      ...[3, 4].map((month) => ({
        year: 2026,
        month,
        orphanId: "o2",
        name: "الحالة الثانية",
        caseNumber: "002",
        monthlyNeed: 50_000,
        status: "partially_covered" as const,
        createdAt: "2026-03-02T00:00:00Z"
      }))
    ],
    sponsorshipSnapshots: [
      {
        year: 2025,
        month: 12,
        sponsorshipId: "sp0",
        sponsorId: "s0",
        sponsorName: "المتبرع السابق",
        orphanId: "o0",
        orphanName: "الحالة السابقة",
        caseNumber: "000",
        monthlyAmount: 40_000,
        startDate: "2025-12-01",
        endDate: null
      },
      ...[1, 2, 3, 4].flatMap((month) => [
        {
          year: 2026,
          month,
          sponsorshipId: "sp1",
          sponsorId: "s1",
          sponsorName: "المتبرع الأول",
          orphanId: "o1",
          orphanName: "الحالة الأولى",
          caseNumber: "001",
          monthlyAmount: 50_000,
          startDate: "2026-01-01",
          endDate: null
        },
        {
          year: 2026,
          month,
          sponsorshipId: "sp2",
          sponsorId: "s2",
          sponsorName: "المتبرع الثاني",
          orphanId: "o1",
          orphanName: "الحالة الأولى",
          caseNumber: "001",
          monthlyAmount: 30_000,
          startDate: "2026-01-01",
          endDate: null
        }
      ]),
      ...[3, 4].map((month) => ({
        year: 2026,
        month,
        sponsorshipId: "sp4",
        sponsorId: "s2",
        sponsorName: "المتبرع الثاني",
        orphanId: "o2",
        orphanName: "الحالة الثانية",
        caseNumber: "002",
        monthlyAmount: 30_000,
        startDate: "2026-03-01",
        endDate: null
      }))
    ]
  }
};

const allFilters: ReportFilters = {
  month: null,
  sponsorId: null,
  orphanId: null,
  status: "all"
};

describe("report analytics", () => {
  it("keeps shared transfer amounts unique while exposing both donor links", () => {
    const analytics = buildReportAnalytics(dataset, allFilters);

    expect(analytics.kpis).toMatchObject({
      expectedAmount: 230_000,
      receivedAmount: 130_000,
      unpaidAmount: 100_000,
      transferAmount: 130_000,
      paidSponsors: 1,
      unpaidSponsors: 1,
      activeCases: 2,
      missingReceipts: 1
    });
    expect(analytics.transfersBySponsor).toEqual([
      { id: "s1", label: "المتبرع الأول", value: 2 },
      { id: "s2", label: "المتبرع الثاني", value: 1 }
    ]);
  });

  it("builds the four reconciliation states without merging payment and transfer records", () => {
    const analytics = buildReportAnalytics(dataset, allFilters);
    const firstRelationship = analytics.reconciliation.find((row) => row.sponsorshipId === "sp1");

    expect(firstRelationship?.months.slice(0, 4).map((item) => item.status)).toEqual([
      "complete",
      "payment_missing_transfer",
      "unpaid",
      "transfer_exists"
    ]);
  });

  it("updates period totals and donor payment counts when the month changes", () => {
    const analytics = buildReportAnalytics(dataset, { ...allFilters, month: 1 });

    expect(analytics.kpis.expectedAmount).toBe(80_000);
    expect(analytics.kpis.receivedAmount).toBe(80_000);
    expect(analytics.kpis.transferAmount).toBe(80_000);
    expect(analytics.kpis.paidSponsors).toBe(2);
    expect(analytics.kpis.unpaidSponsors).toBe(0);
    expect(analytics.periodMonthly).toHaveLength(1);
    expect(analytics.annualTotals.expectedAmount).toBe(230_000);
  });

  it("filters missing receipts without inventing or duplicating financial totals", () => {
    const analytics = buildReportAnalytics(dataset, { ...allFilters, status: "missing_receipt" });

    expect(analytics.transfers).toHaveLength(1);
    expect(analytics.kpis.transferAmount).toBe(50_000);
    expect(analytics.kpis.missingReceipts).toBe(1);
    expect(analytics.payments).toHaveLength(5);
  });

  it("calculates coverage and missing-data counts from the same filtered orphan set", () => {
    const analytics = buildReportAnalytics(dataset, allFilters);

    expect(analytics.coverageStatus).toEqual([
      { key: "full", label: "مغطاة بالكامل", value: 0 },
      { key: "partial", label: "مغطاة جزئياً", value: 1 },
      { key: "uncovered", label: "غير مغطاة", value: 1 }
    ]);
    expect(analytics.coverageTotals).toEqual({
      need: 150_000,
      covered: 80_000,
      remaining: 70_000
    });
    expect(analytics.missingData[0]).toEqual({ label: "صورة شهادة وفاة الأب", value: 2 });
  });

  it("keeps closed monthly snapshots unchanged when later cases and sponsorships appear", () => {
    const january = buildReportAnalytics(dataset, { ...allFilters, month: 1 });
    const march = buildReportAnalytics(dataset, { ...allFilters, month: 3 });

    expect(january.history.current).toMatchObject({
      sponsoredOrphans: 1,
      newOrphans: 1,
      activeSponsors: 2,
      requiredAmount: 100_000,
      commitmentAmount: 80_000,
      paymentAmount: 80_000,
      transferAmount: 80_000
    });
    expect(march.history.current).toMatchObject({
      sponsoredOrphans: 2,
      newOrphans: 1,
      activeSponsors: 2,
      requiredAmount: 150_000,
      commitmentAmount: 110_000
    });
    expect(january.history.current.sponsoredOrphans).toBe(1);
    expect(january.history.current.requiredAmount).toBe(100_000);
  });

  it("reports numeric and percentage changes against the previous month", () => {
    const analytics = buildReportAnalytics(dataset, { ...allFilters, month: 3 });

    expect(analytics.history.comparisons.sponsoredOrphans).toEqual({
      current: 2,
      previous: 1,
      difference: 1,
      percentage: 100
    });
    expect(analytics.history.comparisons.commitmentAmount).toEqual({
      current: 110_000,
      previous: 80_000,
      difference: 30_000,
      percentage: 37.5
    });
  });

  it("compares January with December of the previous year", () => {
    const analytics = buildReportAnalytics(dataset, { ...allFilters, month: 1 });

    expect(analytics.history.previous).toMatchObject({
      year: 2025,
      month: 12,
      paymentAmount: 40_000
    });
    expect(analytics.history.comparisons.paymentAmount).toEqual({
      current: 80_000,
      previous: 40_000,
      difference: 40_000,
      percentage: 100
    });
  });
});
