import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import { BrowserRouter } from "react-router";
import { UpcomingCalendarPanel } from "../UpcomingCalendarPanel";
import type { CalendarPanelEvent } from "../UpcomingCalendarPanel";

function renderWithRouter(ui: React.ReactElement) {
  return render(<BrowserRouter>{ui}</BrowserRouter>);
}

function makeEvent(overrides: Partial<CalendarPanelEvent> = {}): CalendarPanelEvent {
  return {
    id: overrides.id ?? "event-1",
    name: overrides.name ?? "UCL Quarterfinals",
    // Use explicit key check so callers can pass null to test the null-date path
    eventDate: "eventDate" in overrides ? (overrides.eventDate as string | null) : "2099-04-09",
    earliestGameTime: "earliestGameTime" in overrides ? (overrides.earliestGameTime as string | null) : null,
    matchLabel: overrides.matchLabel ?? null,
    eventType: overrides.eventType ?? "playoff_game",
    sportsSeasonId: overrides.sportsSeasonId ?? "ss-1",
    sportName: overrides.sportName ?? "Football",
    sportSeasonName: overrides.sportSeasonName ?? "UCL 2025",
    leagueName: overrides.leagueName,
    leagueId: overrides.leagueId,
    sportsSeasonPageUrl: overrides.sportsSeasonPageUrl,
    relevantParticipants: overrides.relevantParticipants ?? [
      { id: "p1", name: "Man City" },
    ],
  };
}

describe("UpcomingCalendarPanel", () => {
  describe("empty state", () => {
    it("shows empty state message when no events", () => {
      renderWithRouter(<UpcomingCalendarPanel events={[]} />);
      expect(screen.getByText(/No upcoming events in the next 30 days/i)).toBeInTheDocument();
    });

    it("renders the panel title", () => {
      renderWithRouter(<UpcomingCalendarPanel events={[]} />);
      expect(screen.getByText("Upcoming Events")).toBeInTheDocument();
    });
  });

  describe("event display", () => {
    it("shows event name and formatted date", () => {
      renderWithRouter(
        <UpcomingCalendarPanel events={[makeEvent({ name: "UCL QF", eventDate: "2099-04-09" })]} />
      );
      expect(screen.getByText("UCL QF")).toBeInTheDocument();
      expect(screen.getByText("Apr 9")).toBeInTheDocument();
    });

    it("shows sport name and season name", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[makeEvent({ sportName: "Football", sportSeasonName: "UCL 2025" })]}
        />
      );
      expect(screen.getByText(/Football · UCL 2025/)).toBeInTheDocument();
    });

    it("shows participant badge for bracket events", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[makeEvent({
            eventType: "playoff_game",
            relevantParticipants: [{ id: "p1", name: "Man City" }],
          })]}
        />
      );
      expect(screen.getByText("Man City")).toBeInTheDocument();
    });

    it("shows 'N of your picks' for all-compete events with multiple participants", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[makeEvent({
            eventType: "schedule_event",
            name: "Australian GP",
            relevantParticipants: [
              { id: "p1", name: "Verstappen" },
              { id: "p2", name: "Hamilton" },
              { id: "p3", name: "Leclerc" },
              { id: "p4", name: "Norris" },
              { id: "p5", name: "Russell" },
            ],
          })]}
        />
      );
      expect(screen.getByText("5 of your picks")).toBeInTheDocument();
    });

    it("renders TBD when both eventDate and earliestGameTime are null", () => {
      renderWithRouter(
        <UpcomingCalendarPanel events={[makeEvent({ eventDate: null })]} />
      );
      expect(screen.getByText("TBD")).toBeInTheDocument();
    });

    it("uses earliestGameTime date when eventDate is null", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[makeEvent({ eventDate: null, earliestGameTime: "2099-04-09T14:00:00.000Z" })]}
        />
      );
      // Should not show TBD
      expect(screen.queryByText("TBD")).not.toBeInTheDocument();
    });

    it("shows matchLabel appended to event name when present", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[makeEvent({ name: "PDC World Championship", matchLabel: "Semifinals Game #1" })]}
        />
      );
      expect(screen.getByText(/PDC World Championship — Semifinals Game #1/)).toBeInTheDocument();
    });

    it("shows plain event name when matchLabel is null", () => {
      renderWithRouter(
        <UpcomingCalendarPanel events={[makeEvent({ name: "UCL QF", matchLabel: null })]} />
      );
      expect(screen.getByText("UCL QF")).toBeInTheDocument();
    });
  });

  describe("participant overflow", () => {
    it("shows first 3 participants and an overflow badge for 4+", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[makeEvent({
            eventType: "playoff_game",
            relevantParticipants: [
              { id: "p1", name: "Alpha" },
              { id: "p2", name: "Beta" },
              { id: "p3", name: "Gamma" },
              { id: "p4", name: "Delta" },
              { id: "p5", name: "Epsilon" },
            ],
          })]}
        />
      );
      expect(screen.getByText("Alpha")).toBeInTheDocument();
      expect(screen.getByText("Beta")).toBeInTheDocument();
      expect(screen.getByText("Gamma")).toBeInTheDocument();
      expect(screen.queryByText("Delta")).not.toBeInTheDocument();
      expect(screen.getByText("+2 more")).toBeInTheDocument();
    });

    it("shows all participants when exactly 3", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[makeEvent({
            eventType: "playoff_game",
            relevantParticipants: [
              { id: "p1", name: "Alpha" },
              { id: "p2", name: "Beta" },
              { id: "p3", name: "Gamma" },
            ],
          })]}
        />
      );
      expect(screen.getByText("Alpha")).toBeInTheDocument();
      expect(screen.getByText("Gamma")).toBeInTheDocument();
      expect(screen.queryByText(/\+\d+ more/)).not.toBeInTheDocument();
    });
  });

  describe("league display", () => {
    it("does not show league name when showLeague is false (default)", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[makeEvent({ leagueName: "My League" })]}
          showLeague={false}
        />
      );
      expect(screen.queryByText("My League")).not.toBeInTheDocument();
    });

    it("shows league name badge when showLeague is true", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[makeEvent({ leagueName: "My League" })]}
          showLeague={true}
        />
      );
      expect(screen.getByText("My League")).toBeInTheDocument();
    });

    it("renders multiple events from different leagues", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[
            makeEvent({ id: "e1", name: "UCL QF", leagueName: "League A" }),
            makeEvent({ id: "e2", name: "Australian GP", leagueName: "League B", eventType: "schedule_event" }),
          ]}
          showLeague={true}
        />
      );
      expect(screen.getByText("League A")).toBeInTheDocument();
      expect(screen.getByText("League B")).toBeInTheDocument();
    });
  });

  describe("link behaviour", () => {
    it("wraps event row in a link when sportsSeasonPageUrl is provided", () => {
      renderWithRouter(
        <UpcomingCalendarPanel
          events={[makeEvent({ sportsSeasonPageUrl: "/leagues/l1/sports-seasons/ss1" })]}
        />
      );
      const link = screen.getByRole("link");
      expect(link).toHaveAttribute("href", "/leagues/l1/sports-seasons/ss1");
    });
  });
});
