import { describe, expect, it } from "vitest";
import {
  CONSTRUCTION_AGE_BANDS,
  PROPERTY_TYPE_LABELS,
} from "./epcSources";
import {
  PROPERTY_TYPE_OPTIONS,
  YEAR_BUILT_OPTIONS,
} from "@/app/utils/propertyFilters";

// The reporting age-band bucketing in getCountByAgeBand (databaseFunctions.ts),
// mirrored so the CONSTRUCTION_AGE_BANDS representative years stay anchored to
// the buckets the chart renders.
function reportingAgeBand(year: number): string {
  if (year < 1900) return "<1900";
  if (year <= 1929) return "1900–1929";
  if (year <= 1949) return "1930–1949";
  if (year <= 1975) return "1950–1975";
  if (year <= 1999) return "1976–1999";
  return "2000+";
}

describe("CONSTRUCTION_AGE_BANDS", () => {
  it("keeps each representative year consistent with the band's label", () => {
    for (const { label, year } of Object.values(CONSTRUCTION_AGE_BANDS)) {
      if (label.startsWith("before")) {
        expect(year).toBeLessThan(1900);
      } else {
        const start = Number(label.match(/\d{4}/)![0]);
        expect(year).toBe(start);
      }
    }
  });

  it("buckets every RdSAP band into the expected reporting age band", () => {
    const buckets = Object.fromEntries(
      Object.entries(CONSTRUCTION_AGE_BANDS).map(([code, { year }]) => [
        code,
        reportingAgeBand(year),
      ]),
    );
    expect(buckets).toEqual({
      A: "<1900",
      B: "1900–1929",
      C: "1930–1949",
      D: "1950–1975",
      E: "1950–1975",
      F: "1976–1999",
      G: "1976–1999",
      H: "1976–1999",
      // I (1996–2002) straddles the 1976–1999 / 2000+ boundary; it buckets by
      // its start year.
      I: "1976–1999",
      J: "2000+",
      K: "2000+",
      L: "2000+",
      M: "2000+",
    });
  });
});

describe("PROPERTY_TYPE_LABELS", () => {
  it("maps every code to a label the property-type filter offers as an option", () => {
    const optionLabels = new Set(PROPERTY_TYPE_OPTIONS.map((o) => o.label));
    for (const label of Object.values(PROPERTY_TYPE_LABELS)) {
      expect(optionLabels).toContain(label);
    }
  });
});

describe("YEAR_BUILT_OPTIONS (Construction Age)", () => {
  // Guards the band-native filter (ADR-0012) against label drift — a mismatched
  // en-dash or reworded band would silently make the filter match nothing.
  it("is exactly the RdSAP band labels in order, plus Unknown", () => {
    const bandLabels = Object.values(CONSTRUCTION_AGE_BANDS).map((b) => b.label);
    expect(YEAR_BUILT_OPTIONS.map((o) => o.label)).toEqual([
      ...bandLabels,
      "Unknown",
    ]);
  });

  it("uses each band label as its own dbValue", () => {
    for (const o of YEAR_BUILT_OPTIONS) expect(o.dbValues).toEqual([o.label]);
  });
});
