import {
  getActiveGlitchSlide,
  getActiveSegment,
  getActiveSlide,
  getCompatibleGlitchSlides,
  getDefaultGlitchSlide,
  getLocalTimeWithinSegment,
  getSlideEndTime
} from "./timeline";
import type { LectureDefinition } from "../types/lecture";

const lectureFixture: LectureDefinition = {
  id: "lecture-1",
  title: "Fixture",
  version: "0.1.0",
  durationSec: 9,
  segments: [
    { id: "seg-1", src: "/seg-1.mp4", startTimeSec: 0, durationSec: 3 },
    { id: "seg-2", src: "/seg-2.mp4", startTimeSec: 3, durationSec: 3 },
    { id: "seg-3", src: "/seg-3.mp4", startTimeSec: 6, durationSec: 3 }
  ],
  slides: [
    {
      id: "slide-1",
      startTimeSec: 0,
      endTimeSec: 2.5,
      displayMode: "square",
      glitchSlides: [
        {
          id: "a",
          score: 0.3,
          componentKey: "SquareYellow",
          props: {
            header: "A",
            imageSrc: "/a.png",
            imageAlt: "A"
          }
        },
        {
          id: "b",
          score: 0.9,
          componentKey: "FullscreenSplit",
          props: {
            title: "B",
            body: "B body",
            imageSrc: "/b.png",
            imageAlt: "B"
          },
          orientation: "desktop"
        }
      ]
    },
    {
      id: "slide-2",
      startTimeSec: 2.5,
      displayMode: "fullscreen",
      glitchSlides: [
        {
          id: "c",
          score: 0.4,
          componentKey: "SquareYellow",
          props: {
            header: "C",
            imageSrc: "/c.png",
            imageAlt: "C"
          }
        },
        {
          id: "d",
          score: 0.7,
          componentKey: "FullscreenSplit",
          props: {
            title: "D",
            body: "D body",
            imageSrc: "/d.png",
            imageAlt: "D"
          }
        }
      ]
    }
  ]
};

describe("timeline", () => {
  it("finds the correct segment across boundaries", () => {
    expect(getActiveSegment(lectureFixture.segments, 2.9)?.id).toBe("seg-1");
    expect(getActiveSegment(lectureFixture.segments, 3.1)?.id).toBe("seg-2");
  });

  it("translates global time into local segment time", () => {
    expect(getLocalTimeWithinSegment(lectureFixture.segments[1], 4.25)).toBeCloseTo(
      1.25
    );
  });

  it("resolves open-ended slide timing against the next cue", () => {
    expect(
      getSlideEndTime(lectureFixture.slides, "slide-2", lectureFixture.durationSec)
    ).toBe(lectureFixture.durationSec);
  });

  it("returns the active slide for interval and open-ended slides", () => {
    expect(
      getActiveSlide(lectureFixture.slides, 1.5, lectureFixture.durationSec)?.id
    ).toBe("slide-1");
    expect(
      getActiveSlide(lectureFixture.slides, 7, lectureFixture.durationSec)?.id
    ).toBe("slide-2");
  });

  it("picks the highest-scoring default glitch slide and only honors compatible overrides", () => {
    expect(getDefaultGlitchSlide(lectureFixture.slides[0]).id).toBe("b");
    expect(getActiveGlitchSlide(lectureFixture.slides[0], "desktop").id).toBe("b");
    expect(getActiveGlitchSlide(lectureFixture.slides[0], "desktop", "a").id).toBe("b");
  });

  it("filters candidates to the current viewport before scoring", () => {
    expect(
      getCompatibleGlitchSlides(lectureFixture.slides[0], "mobile-portrait").map(
        (candidate) => candidate.id
      )
    ).toEqual(["a"]);
    expect(getActiveGlitchSlide(lectureFixture.slides[0], "mobile-portrait").id).toBe(
      "a"
    );
  });
});
