import { describe, expect, it } from "vitest";
import type { SlotDTO } from "../../model/slotTypes";
import { applySlotFilters, slotStatusKey, type SlotFilterState } from "./slotFilters";

function slot(over: Partial<SlotDTO>): SlotDTO {
  return {
    cycle: 1,
    satelliteId: 2,
    tn: "2026-06-15T10:00:00",
    tk: "2026-06-15T10:00:10",
    roll: 30,
    contour: "POLYGON EMPTY",
    revolution: 281,
    revolutionSign: "ASC",
    slotNumber: 1,
    state: "AVAILABLE",
    latitude: 55,
    longitude: 37,
    ...over,
  };
}

const allStatuses = new Set(["free", "booked", "occupied"] as const);
const allBranches = new Set(["ASC", "DESC"] as const);

describe("slotStatusKey", () => {
  it("бронь важнее state (booked, даже если state=AVAILABLE)", () => {
    expect(slotStatusKey({ state: "AVAILABLE" }, true)).toBe("booked");
  });
  it("BUSY → occupied, когда не бронь", () => {
    expect(slotStatusKey({ state: "BUSY" }, false)).toBe("occupied");
  });
  it("AVAILABLE → free", () => {
    expect(slotStatusKey({ state: "AVAILABLE" }, false)).toBe("free");
  });
});

describe("applySlotFilters", () => {
  const rows = [
    slot({ slotNumber: 1, satelliteId: 2, revolutionSign: "ASC", state: "AVAILABLE" }),
    slot({ slotNumber: 2, satelliteId: 2, revolutionSign: "DESC", state: "BUSY" }),
    slot({ slotNumber: 3, satelliteId: 5, revolutionSign: "ASC", state: "AVAILABLE" }),
  ];
  const booked = new Set([1]); // слот №1 — бронь
  const isBooked = (s: SlotDTO) => booked.has(s.slotNumber);
  const base: SlotFilterState = {
    status: allStatuses,
    satellites: new Set([2, 5]),
    branches: allBranches,
  };

  it("дефолт (все оси) пропускает всё", () => {
    expect(applySlotFilters(rows, base, isBooked)).toHaveLength(3);
  });
  it("статус free убирает бронь и занятый", () => {
    const out = applySlotFilters(rows, { ...base, status: new Set(["free"]) }, isBooked);
    expect(out.map((s) => s.slotNumber)).toEqual([3]);
  });
  it("фильтр по КА оставляет только выбранный спутник", () => {
    const out = applySlotFilters(rows, { ...base, satellites: new Set([5]) }, isBooked);
    expect(out.map((s) => s.slotNumber)).toEqual([3]);
  });
  it("ветвь ASC оставляет только восходящие", () => {
    const out = applySlotFilters(rows, { ...base, branches: new Set(["ASC"]) }, isBooked);
    expect(out.map((s) => s.slotNumber)).toEqual([1, 3]);
  });
  it("снятие последней галочки оси (пустое множество) → ничего не видно", () => {
    expect(applySlotFilters(rows, { ...base, status: new Set() }, isBooked)).toHaveLength(0);
    expect(applySlotFilters(rows, { ...base, satellites: new Set() }, isBooked)).toHaveLength(0);
  });
});
