import { describe, it, expect } from "vitest";
import { computeDocStatusMap } from "./docStatus";
import { EXPECTED_RETROFIT_ASSESSMENT_DOC_TYPES } from "./types";
import type { HubspotDeal, ApprovalsByDeal } from "./types";

function makeDeal(overrides: Partial<HubspotDeal> = {}): HubspotDeal {
  return {
    id: "1",
    dealId: "deal-1",
    dealname: "Test Property",
    dealstage: null,
    companyId: null,
    projectCode: null,
    landlordPropertyId: null,
    uprn: null,
    outcome: null,
    outcomeNotes: null,
    majorConditionIssueDescription: null,
    majorConditionIssuePhotos: null,
    majorConditionIssuePhotosS3: null,
    coordinationStatus: null,
    designStatus: null,
    bookingStatus: null,
    pashubLink: null,
    sharepointLink: null,
    dampMouldFlag: null,
    dampMouldAndRepairComments: null,
    preSapScore: null,
    coordinator: null,
    ioeV1Date: null,
    ioeV2Date: null,
    ioeV3Date: null,
    proposedMeasures: null,
    approvedPackage: null,
    designer: null,
    designDate: null,
    actualMeasuresInstalled: null,
    installer: null,
    installerHandover: null,
    lodgementStatus: null,
    measuresLodgementDate: null,
    fullLodgementDate: null,
    confirmedSurveyDate: null,
    confirmedSurveyTime: null,
    surveyedDate: null,
    designType: null,
    eiScore: null,
    eiScorePotential: null,
    epcSapScore: null,
    potentialPostSapScoreDropdown: null,
    epcPrn: null,
    surveyType: null,
    measuresForPibiOrdered: null,
    pibiOrderDate: null,
    pibiCompletedDate: null,
    propertyHaltedDate: null,
    propertyHaltedReason: null,
    technicalApprovedMeasuresForInstall: null,
    domnaSurveyType: null,
    domnaSurveyDate: null,
    batch: null,
    batchDescription: null,
    planningAuthority: null,
    designatedArea: null,
    article4PdRights: null,
    listedBuilding: null,
    designConstraints: null,
    planningComments: null,
    planningStatus: null,
    planningSuggestedApproach: null,
    coordinationComments: null,
    domnasurveyRequired: null,
    createdAt: new Date(),
    updatedAt: new Date(),
    ...overrides,
  };
}

const allSurveyDocs = EXPECTED_RETROFIT_ASSESSMENT_DOC_TYPES.map((t) => ({
  fileType: t,
  measureName: null,
}));

describe("computeDocStatusMap", () => {
  it("marks survey as complete when all 9 mandatory doc types are present", () => {
    const deal = makeDeal({ dealId: "deal-1" });
    const docs = new Map([["deal-1", allSurveyDocs]]);

    const result = computeDocStatusMap([deal], docs, {});

    expect(result["deal-1"].isSurveyComplete).toBe(true);
    expect(result["deal-1"].hasSurveyDocs).toBe(true);
  });

  it("marks survey as incomplete when only some mandatory doc types are present", () => {
    const deal = makeDeal({ dealId: "deal-1" });
    const partialSurveyDocs = [{ fileType: "photo_pack", measureName: null }];
    const docs = new Map([["deal-1", partialSurveyDocs]]);

    const result = computeDocStatusMap([deal], docs, {});

    expect(result["deal-1"].isSurveyComplete).toBe(false);
    expect(result["deal-1"].hasSurveyDocs).toBe(true);
  });

  it("omits a deal from the map when it has no uploaded documents", () => {
    const deal = makeDeal({ dealId: "deal-1" });

    const result = computeDocStatusMap([deal], new Map(), {});

    expect(result["deal-1"]).toBeUndefined();
  });

  it("uses approved measures in preference to proposed measures", () => {
    const deal = makeDeal({ dealId: "deal-1", proposedMeasures: "CWI" });
    const approvalsByDeal: ApprovalsByDeal = { "deal-1": ["ASHP"] };
    const docs = new Map([["deal-1", allSurveyDocs]]);

    const result = computeDocStatusMap([deal], docs, approvalsByDeal);

    const measureNames = result["deal-1"].measureProgress.map((m) => m.measureName);
    expect(measureNames).toEqual(["ASHP"]);
    expect(measureNames).not.toContain("CWI");
  });

  describe("installStatus", () => {
    // CWI requires only BASE_DOCS — simple to satisfy in tests
    const cwi = "CWI";
    const cwiRequiredDocs = [
      "pre_photo",
      "mid_photo",
      "post_photo",
      "pre_installation_building_inspection",
      "claim_of_compliance",
      "insurance_guarantee",
      "workmanship_warranty",
    ];

    it('is "all" when every measure has all required install docs uploaded', () => {
      const deal = makeDeal({ dealId: "deal-1", proposedMeasures: cwi });
      const installDocs = cwiRequiredDocs.map((ft) => ({
        fileType: ft,
        measureName: cwi,
      }));
      const docs = new Map([["deal-1", installDocs]]);

      const result = computeDocStatusMap([deal], docs, {});

      expect(result["deal-1"].installStatus).toBe("all");
    });

    it('is "partial" when some (but not all) measures have docs uploaded', () => {
      const deal = makeDeal({ dealId: "deal-1", proposedMeasures: cwi });
      const partialInstallDocs = [{ fileType: "pre_photo", measureName: cwi }];
      const docs = new Map([["deal-1", partialInstallDocs]]);

      const result = computeDocStatusMap([deal], docs, {});

      expect(result["deal-1"].installStatus).toBe("partial");
    });

    it('is "hasDocs" when install docs exist but no measures are defined on the deal', () => {
      const deal = makeDeal({ dealId: "deal-1", proposedMeasures: null });
      const installDocs = [{ fileType: "pre_photo", measureName: null }];
      const docs = new Map([["deal-1", installDocs]]);

      const result = computeDocStatusMap([deal], docs, {});

      expect(result["deal-1"].installStatus).toBe("hasDocs");
    });

    it('is "none" when measures are defined but no install docs have been uploaded', () => {
      const deal = makeDeal({ dealId: "deal-1", proposedMeasures: cwi });
      // Only survey docs — no install docs
      const docs = new Map([["deal-1", allSurveyDocs]]);

      const result = computeDocStatusMap([deal], docs, {});

      expect(result["deal-1"].installStatus).toBe("none");
    });
  });
});
