import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, fireEvent } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MiniDraftGrid } from "~/components/draft/MiniDraftGrid";

const draftSlots = [
  { id: "slot-1", draftOrder: 1, team: { id: "team-1", name: "Alpha", logoUrl: null } },
  { id: "slot-2", draftOrder: 2, team: { id: "team-2", name: "Bravo", logoUrl: null } },
];

const ownerMap = { "team-1": "Alpha", "team-2": "Bravo" };

// Round 1: team-1 pick 1 (filled), team-2 pick 2 (current/empty)
// Round 2 (snake): team-2 pick 3, team-1 pick 4 — both empty
const draftGrid = [
  [
    { pickNumber: 1, round: 1, pickInRound: 1, teamId: "team-1", pick: { participant: { name: "Player A" }, sport: { name: "NFL" } } },
    { pickNumber: 2, round: 1, pickInRound: 2, teamId: "team-2" },
  ],
  [
    { pickNumber: 3, round: 2, pickInRound: 1, teamId: "team-2" },
    { pickNumber: 4, round: 2, pickInRound: 2, teamId: "team-1" },
  ],
];

const baseProps = {
  draftSlots,
  draftGrid,
  currentPick: 2,
  currentRound: 1,
  ownerMap,
};

describe("MiniDraftGrid", () => {
  beforeEach(() => vi.clearAllMocks());

  describe("Team header layout", () => {
    it("renders all team names", () => {
      render(<MiniDraftGrid {...baseProps} />);
      expect(screen.getAllByText("Alpha").length).toBeGreaterThan(0);
      expect(screen.getAllByText("Bravo").length).toBeGreaterThan(0);
    });

    it("non-commissioner headers carry flex sizing classes", () => {
      render(<MiniDraftGrid {...baseProps} />);
      const alphaHeader = screen.getAllByText("Alpha")[0].closest(".flex-1");
      expect(alphaHeader).toHaveClass("flex-1", "min-w-20");
    });

    it("commissioner headers carry flex sizing classes", () => {
      render(
        <MiniDraftGrid
          {...baseProps}
          onAdjustTimeBankOpen={vi.fn()}
          onSetAutodraftOpen={vi.fn()}
        />
      );
      const alphaHeader = screen.getAllByText("Alpha")[0].closest(".flex-1");
      expect(alphaHeader).toHaveClass("flex-1", "min-w-20");
    });
  });

  describe("Disconnected team styling", () => {
    it("applies italic + muted style to disconnected teams when connectedTeams provided", () => {
      render(
        <MiniDraftGrid
          {...baseProps}
          connectedTeams={new Set(["team-1"])}
        />
      );
      const bravoSpan = screen.getAllByText("Bravo")[0];
      expect(bravoSpan).toHaveClass("italic", "text-muted-foreground");
      const alphaSpan = screen.getAllByText("Alpha")[0];
      expect(alphaSpan).not.toHaveClass("italic");
    });

    it("treats all teams as connected when connectedTeams is not provided", () => {
      render(<MiniDraftGrid {...baseProps} />);
      expect(screen.getAllByText("Alpha")[0]).not.toHaveClass("italic");
      expect(screen.getAllByText("Bravo")[0]).not.toHaveClass("italic");
    });
  });

  describe("Team header context menus (commissioner)", () => {
    it("shows no context menu when callbacks are absent", () => {
      render(<MiniDraftGrid {...baseProps} />);
      const alphaHeader = screen.getAllByText("Alpha")[0];
      fireEvent.contextMenu(alphaHeader);
      expect(screen.queryByText("Adjust Time Bank...")).not.toBeInTheDocument();
      expect(screen.queryByText("Set Autodraft...")).not.toBeInTheDocument();
    });

    it("shows Adjust Time Bank and Set Autodraft on right-click when both callbacks provided", () => {
      render(
        <MiniDraftGrid
          {...baseProps}
          onAdjustTimeBankOpen={vi.fn()}
          onSetAutodraftOpen={vi.fn()}
        />
      );
      fireEvent.contextMenu(screen.getAllByText("Alpha")[0]);
      expect(screen.getByText("Adjust Time Bank...")).toBeInTheDocument();
      expect(screen.getByText("Set Autodraft...")).toBeInTheDocument();
    });

    it("shows only Adjust Time Bank when only that callback is provided", () => {
      render(
        <MiniDraftGrid {...baseProps} onAdjustTimeBankOpen={vi.fn()} />
      );
      fireEvent.contextMenu(screen.getAllByText("Alpha")[0]);
      expect(screen.getByText("Adjust Time Bank...")).toBeInTheDocument();
      expect(screen.queryByText("Set Autodraft...")).not.toBeInTheDocument();
    });

    it("calls onAdjustTimeBankOpen with the correct teamId", async () => {
      const user = userEvent.setup();
      const onAdjustTimeBankOpen = vi.fn();
      render(
        <MiniDraftGrid {...baseProps} onAdjustTimeBankOpen={onAdjustTimeBankOpen} />
      );
      fireEvent.contextMenu(screen.getAllByText("Bravo")[0]);
      await user.click(screen.getByText("Adjust Time Bank..."));
      expect(onAdjustTimeBankOpen).toHaveBeenCalledWith("team-2");
    });

    it("calls onSetAutodraftOpen with the correct teamId", async () => {
      const user = userEvent.setup();
      const onSetAutodraftOpen = vi.fn();
      render(
        <MiniDraftGrid {...baseProps} onSetAutodraftOpen={onSetAutodraftOpen} />
      );
      fireEvent.contextMenu(screen.getAllByText("Alpha")[0]);
      await user.click(screen.getByText("Set Autodraft..."));
      expect(onSetAutodraftOpen).toHaveBeenCalledWith("team-1");
    });
  });

  describe("Current cell context menu (commissioner)", () => {
    it("shows Force Auto Pick and Force Manual Pick on right-click of current cell", () => {
      render(
        <MiniDraftGrid
          {...baseProps}
          onForceAutopick={vi.fn()}
          onForceManualPickOpen={vi.fn()}
        />
      );
      // Pick 2 is the current cell (team-2, round 1)
      const currentCell = screen.getByTitle("Overall Pick #2");
      fireEvent.contextMenu(currentCell);
      expect(screen.getByText("Force Auto Pick")).toBeInTheDocument();
      expect(screen.getByText("Force Manual Pick")).toBeInTheDocument();
    });

    it("calls onForceAutopick with correct args", async () => {
      const user = userEvent.setup();
      const onForceAutopick = vi.fn();
      render(
        <MiniDraftGrid {...baseProps} onForceAutopick={onForceAutopick} />
      );
      fireEvent.contextMenu(screen.getByTitle("Overall Pick #2"));
      await user.click(screen.getByText("Force Auto Pick"));
      expect(onForceAutopick).toHaveBeenCalledWith(2, "team-2");
    });

    it("calls onForceManualPickOpen with correct args", async () => {
      const user = userEvent.setup();
      const onForceManualPickOpen = vi.fn();
      render(
        <MiniDraftGrid {...baseProps} onForceManualPickOpen={onForceManualPickOpen} />
      );
      fireEvent.contextMenu(screen.getByTitle("Overall Pick #2"));
      await user.click(screen.getByText("Force Manual Pick"));
      expect(onForceManualPickOpen).toHaveBeenCalledWith(2, "team-2");
    });

    it("shows no force-pick menu when no callbacks provided", () => {
      render(<MiniDraftGrid {...baseProps} />);
      fireEvent.contextMenu(screen.getByTitle("Overall Pick #2"));
      expect(screen.queryByText("Force Auto Pick")).not.toBeInTheDocument();
      expect(screen.queryByText("Force Manual Pick")).not.toBeInTheDocument();
    });
  });

  describe("Picked cell context menu (commissioner)", () => {
    it("shows Replace Pick and Roll Back on right-click of a picked cell", () => {
      render(
        <MiniDraftGrid
          {...baseProps}
          onReplacePick={vi.fn()}
          onRollbackToPick={vi.fn()}
        />
      );
      // Pick 1 is already picked (team-1)
      const pickedCell = screen.getByTitle("Overall Pick #1");
      fireEvent.contextMenu(pickedCell);
      expect(screen.getByText("Replace Pick")).toBeInTheDocument();
      expect(screen.getByText("Roll Back to This Pick")).toBeInTheDocument();
    });

    it("calls onReplacePick with correct args", async () => {
      const user = userEvent.setup();
      const onReplacePick = vi.fn();
      render(
        <MiniDraftGrid {...baseProps} onReplacePick={onReplacePick} />
      );
      fireEvent.contextMenu(screen.getByTitle("Overall Pick #1"));
      await user.click(screen.getByText("Replace Pick"));
      expect(onReplacePick).toHaveBeenCalledWith(1, "team-1");
    });

    it("calls onRollbackToPick with correct pickNumber", async () => {
      const user = userEvent.setup();
      const onRollbackToPick = vi.fn();
      render(
        <MiniDraftGrid {...baseProps} onRollbackToPick={onRollbackToPick} />
      );
      fireEvent.contextMenu(screen.getByTitle("Overall Pick #1"));
      await user.click(screen.getByText("Roll Back to This Pick"));
      expect(onRollbackToPick).toHaveBeenCalledWith(1);
    });

    it("shows no menu on picked cell when no callbacks provided", () => {
      render(<MiniDraftGrid {...baseProps} />);
      fireEvent.contextMenu(screen.getByTitle("Overall Pick #1"));
      expect(screen.queryByText("Replace Pick")).not.toBeInTheDocument();
    });
  });

  describe("Empty grid", () => {
    it("renders nothing when draftGrid is empty", () => {
      const { container } = render(
        <MiniDraftGrid {...baseProps} draftGrid={[]} />
      );
      expect(container.firstChild).toBeNull();
    });
  });
});
