import { describe, it, expect } from "vitest";
import {
  splitDocumentsByType,
  getMissingSurveyDocTypes,
  getUnassignedInstallDocs,
} from "./propertyDocuments";
import type { PropertyDocument, MeasureDocProgress } from "./types";
import { EXPECTED_RETROFIT_ASSESSMENT_DOC_TYPES } from "./types";

function makeDoc(overrides: Partial<PropertyDocument> = {}): PropertyDocument {
  return {
    id: "1",
    s3FileKey: "key",
    s3FileBucket: "bucket",
    docType: "photo_pack",
    s3UploadTimestamp: "2024-01-01T00:00:00Z",
    uprn: null,
    landlordPropertyId: null,
    measureName: null,
    ...overrides,
  };
}

function makeMeasureProgress(overrides: Partial<MeasureDocProgress> = {}): MeasureDocProgress {
  return {
    measureName: "ASHP",
    required: ["pre_photo", "post_photo"],
    uploaded: [],
    isComplete: false,
    uploadedCount: 0,
    requiredCount: 2,
    ...overrides,
  };
}

describe("splitDocumentsByType", () => {
  it("puts survey doc types in retrofitDocs", () => {
    const doc = makeDoc({ docType: "photo_pack" });
    const { docs: retrofitDocs, installDocs } = splitDocumentsByType([doc]);
    expect(retrofitDocs).toHaveLength(1);
    expect(installDocs).toHaveLength(0);
  });

  it("puts install doc types in installDocs", () => {
    const doc = makeDoc({ docType: "pre_photo" });
    const { docs: retrofitDocs, installDocs } = splitDocumentsByType([doc]);
    expect(retrofitDocs).toHaveLength(0);
    expect(installDocs).toHaveLength(1);
  });

  it("includes optional ecmk types in retrofitDocs", () => {
    const doc = makeDoc({ docType: "ecmk_site_note" });
    const { docs: retrofitDocs } = splitDocumentsByType([doc]);
    expect(retrofitDocs).toHaveLength(1);
  });

  it("splits a mixed list correctly", () => {
    const docs = [
      makeDoc({ id: "1", docType: "photo_pack" }),
      makeDoc({ id: "2", docType: "pre_photo" }),
      makeDoc({ id: "3", docType: "site_note" }),
      makeDoc({ id: "4", docType: "post_photo" }),
    ];
    const { docs: retrofitDocs, installDocs } = splitDocumentsByType(docs);
    expect(retrofitDocs).toHaveLength(2);
    expect(installDocs).toHaveLength(2);
  });

  it("returns empty arrays for empty input", () => {
    const { docs: retrofitDocs, installDocs } = splitDocumentsByType([]);
    expect(retrofitDocs).toHaveLength(0);
    expect(installDocs).toHaveLength(0);
  });
});

describe("getMissingRetrofitTypes", () => {
  it("returns all mandatory types when no docs uploaded", () => {
    const missing = getMissingSurveyDocTypes([]);
    expect(missing).toHaveLength(EXPECTED_RETROFIT_ASSESSMENT_DOC_TYPES.length);
  });

  it("excludes types that have been uploaded", () => {
    const uploaded = [makeDoc({ docType: "photo_pack" })];
    const missing = getMissingSurveyDocTypes(uploaded);
    expect(missing).not.toContain("photo_pack");
    expect(missing).toHaveLength(EXPECTED_RETROFIT_ASSESSMENT_DOC_TYPES.length - 1);
  });

  it("returns empty array when all mandatory types uploaded", () => {
    const uploaded = EXPECTED_RETROFIT_ASSESSMENT_DOC_TYPES.map((docType, i) =>
      makeDoc({ id: String(i), docType })
    );
    expect(getMissingSurveyDocTypes(uploaded)).toHaveLength(0);
  });

  it("does not count ecmk types as mandatory", () => {
    const uploaded = [makeDoc({ docType: "ecmk_site_note" })];
    const missing = getMissingSurveyDocTypes(uploaded);
    expect(missing).not.toContain("ecmk_site_note");
    expect(missing).toHaveLength(EXPECTED_RETROFIT_ASSESSMENT_DOC_TYPES.length);
  });
});

describe("getUnassignedInstallDocs", () => {
  it("returns docs with no measureName", () => {
    const doc = makeDoc({ docType: "pre_photo", measureName: null });
    const result = getUnassignedInstallDocs([doc], [makeMeasureProgress()]);
    expect(result).toContain(doc);
  });

  it("returns docs whose measureName is not in measureProgress", () => {
    const doc = makeDoc({ docType: "pre_photo", measureName: "SolarPV" });
    const progress = [makeMeasureProgress({ measureName: "ASHP" })];
    const result = getUnassignedInstallDocs([doc], progress);
    expect(result).toContain(doc);
  });

  it("excludes docs assigned to a known measure", () => {
    const doc = makeDoc({ docType: "pre_photo", measureName: "ASHP" });
    const progress = [makeMeasureProgress({ measureName: "ASHP" })];
    const result = getUnassignedInstallDocs([doc], progress);
    expect(result).toHaveLength(0);
  });

  it("returns empty array when all docs are assigned", () => {
    const docs = [
      makeDoc({ id: "1", docType: "pre_photo", measureName: "ASHP" }),
      makeDoc({ id: "2", docType: "post_photo", measureName: "CWI" }),
    ];
    const progress = [
      makeMeasureProgress({ measureName: "ASHP" }),
      makeMeasureProgress({ measureName: "CWI" }),
    ];
    expect(getUnassignedInstallDocs(docs, progress)).toHaveLength(0);
  });
});
