import { describe, expect, it } from "vitest";
import type { TguPlanUi, TimelineRow } from "../../model/timelineTypes";
import { buildTimelineLayout, clipPlanToRange, timeToX } from "./tguTimelineLayout";
import { parseLocal } from "../../utils/localTime";

const range = {
  fromMs: parseLocal("2026-05-29T00:00:00"),
  toMs: parseLocal("2026-05-30T00:00:00")
};

function plan(
  id: string,
  startTime: string,
  endTime: string,
  spacecraftId = "56756",
  extra: Partial<TguPlanUi> = {}
): TguPlanUi {
  return {
    planId: id,
    spacecraftId,
    startTime,
    endTime,
    kppId: "KPP-1",
    status: "PLANNED",
    startMs: parseLocal(startTime),
    endMs: parseLocal(endTime),
    ...extra
  };
}

describe("tguTimelineLayout", () => {
  it("maps time to x inside the selected interval", () => {
    expect(timeToX(parseLocal("2026-05-29T12:00:00"), range, 1200)).toBe(600);
  });

  it("clips partially visible plans to the selected interval", () => {
    const clipped = clipPlanToRange(plan("p1", "2026-05-28T23:00:00", "2026-05-29T02:00:00"), range);

    expect(clipped).toEqual({
      startMs: range.fromMs,
      endMs: parseLocal("2026-05-29T02:00:00")
    });
  });

  it("keeps non-overlapping plans on a single lane", () => {
    const rows: TimelineRow[] = [
      {
        spacecraftId: "56756",
        plans: [
          plan("p1", "2026-05-29T01:00:00", "2026-05-29T02:00:00"),
          plan("p2", "2026-05-29T03:00:00", "2026-05-29T04:00:00"),
          plan("p3", "2026-05-29T05:00:00", "2026-05-29T06:00:00")
        ]
      }
    ];

    const lanes = buildTimelineLayout(rows, range, 1200).segments.map((segment) => segment.lane);
    expect(lanes).toEqual([0, 0, 0]);
  });

  it("stacks overlapping plans onto separate lanes", () => {
    const rows: TimelineRow[] = [
      {
        spacecraftId: "56756",
        plans: [
          plan("d1", "2026-05-29T02:00:00", "2026-05-29T04:00:00"),
          plan("d2", "2026-05-29T02:00:00", "2026-05-29T04:00:00"),
          plan("d3", "2026-05-29T02:30:00", "2026-05-29T04:30:00")
        ]
      }
    ];

    const layout = buildTimelineLayout(rows, range, 1200);
    // Все три пересекаются — каждый на своей дорожке.
    expect(new Set(layout.segments.map((segment) => segment.lane))).toEqual(new Set([0, 1, 2]));
    // Разные дорожки — разные вертикальные координаты.
    expect(new Set(layout.segments.map((segment) => segment.centerY)).size).toBe(3);
    // Строка с тремя дорожками выше строки с одной.
    expect(layout.rowLayouts[0].laneCount).toBe(3);
  });

  it("grows row height with the deepest lane stack", () => {
    const single: TimelineRow[] = [
      { spacecraftId: "56756", plans: [plan("p1", "2026-05-29T01:00:00", "2026-05-29T02:00:00")] }
    ];
    const stacked: TimelineRow[] = [
      {
        spacecraftId: "56756",
        plans: [
          plan("d1", "2026-05-29T02:00:00", "2026-05-29T04:00:00"),
          plan("d2", "2026-05-29T02:00:00", "2026-05-29T04:00:00")
        ]
      }
    ];

    expect(buildTimelineLayout(stacked, range, 1200).rowLayouts[0].height).toBeGreaterThan(
      buildTimelineLayout(single, range, 1200).rowLayouts[0].height
    );
  });
});
