import { describe, expect, it } from "vitest";
import type { RevolutionSign } from "../../model/slotTypes";
import { groupPasses } from "./slotPasses";

/** Минимальный слот для группировки в витки. */
type S = {
  satelliteId: number;
  slotNumber: number;
  cycle: number;
  revolution: number;
  revolutionSign: RevolutionSign;
  tn: string;
};

const keyOf = (s: S) => `${s.satelliteId}:${s.slotNumber}:${s.cycle}`;

/** Слот на минуту mm от базовой даты; виток задаётся (revolution, sign, cycle). */
function slot(
  satelliteId: number,
  slotNumber: number,
  mm: number,
  revolution: number,
  revolutionSign: RevolutionSign = "ASC",
  cycle = 1,
): S {
  return {
    satelliteId,
    slotNumber,
    cycle,
    revolution,
    revolutionSign,
    tn: `2026-06-17T10:${String(mm).padStart(2, "0")}:00`,
  };
}

describe("groupPasses", () => {
  it("пустой вход → пустой список", () => {
    expect(groupPasses([], keyOf)).toEqual([]);
  });

  it("веер кренов одного оборота → один виток (крен не дробит)", () => {
    // Три нацеливания одного прохода КА 1, оборот 100, восх — все в один виток.
    const passes = groupPasses(
      [slot(1, 1, 0, 100), slot(1, 2, 0, 100), slot(1, 3, 1, 100)],
      keyOf,
    );
    expect(passes).toHaveLength(1);
    expect(passes[0].id).toBe("1:1:100:ASC");
    expect(passes[0].keys).toEqual(["1:1:1", "1:2:1", "1:3:1"]);
    expect(passes[0].satelliteId).toBe(1);
    expect(passes[0].revolution).toBe(100);
  });

  it("разные обороты / ветви / КА → разные витки", () => {
    const passes = groupPasses(
      [
        slot(1, 1, 0, 100, "ASC"),
        slot(1, 2, 5, 100, "DESC"), // та же revolution, другая ветвь
        slot(1, 3, 10, 101, "ASC"), // другой оборот
        slot(2, 4, 2, 100, "ASC"), // другой КА
      ],
      keyOf,
    );
    expect(passes.map((p) => p.id)).toEqual([
      "1:1:100:ASC", // 10:00
      "2:1:100:ASC", // 10:02
      "1:1:100:DESC", // 10:05
      "1:1:101:ASC", // 10:10
    ]);
  });

  it("витки упорядочены по началу прохода (хронология по всем КА)", () => {
    const passes = groupPasses(
      [slot(1, 1, 30, 100), slot(2, 2, 5, 200), slot(1, 3, 15, 101)],
      keyOf,
    );
    expect(passes.map((p) => p.startMs)).toEqual(
      [...passes.map((p) => p.startMs)].sort((a, b) => a - b),
    );
    expect(passes[0].satelliteId).toBe(2); // самый ранний (10:05)
  });

  it("ключи внутри витка отсортированы по времени", () => {
    const passes = groupPasses(
      [slot(1, 3, 2, 100), slot(1, 1, 0, 100), slot(1, 2, 1, 100)],
      keyOf,
    );
    expect(passes[0].keys).toEqual(["1:1:1", "1:2:1", "1:3:1"]);
  });
});
