import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import { BrowserRouter } from "react-router";
import { StandingsTable } from "../StandingsTable";
import { type TeamStanding } from "~/models/standings";

// Helper to wrap component with router context
function renderWithRouter(ui: React.ReactElement) {
  return render(<BrowserRouter>{ui}</BrowserRouter>);
}

describe("StandingsTable", () => {
  const mockLeagueId = "league-123";
  const mockSeasonId = "season-456";

  const mockStandings: TeamStanding[] = [
    {
      teamId: "team1",
      teamName: "Champions United",
      totalPoints: 250.5,
      currentRank: 1,
      previousRank: 2,
      rankChange: 1,
      placementCounts: {
        first: 2,
        second: 1,
        third: 0,
        fourth: 1,
        fifth: 0,
        sixth: 0,
        seventh: 0,
        eighth: 1,
      },
      participantsRemaining: 3,
      calculatedAt: new Date(),
    },
    {
      teamId: "team2",
      teamName: "Second Place Squad",
      totalPoints: 245.0,
      currentRank: 2,
      previousRank: 1,
      rankChange: -1,
      placementCounts: {
        first: 1,
        second: 2,
        third: 1,
        fourth: 0,
        fifth: 1,
        sixth: 0,
        seventh: 0,
        eighth: 0,
      },
      participantsRemaining: 0,
      calculatedAt: new Date(),
    },
    {
      teamId: "team3",
      teamName: "Bronze Warriors",
      totalPoints: 200.0,
      currentRank: 3,
      previousRank: 3,
      rankChange: 0,
      placementCounts: {
        first: 0,
        second: 1,
        third: 2,
        fourth: 1,
        fifth: 0,
        sixth: 0,
        seventh: 0,
        eighth: 0,
      },
      participantsRemaining: 5,
      calculatedAt: new Date(),
    },
  ];

  describe("Basic Rendering", () => {
    it("should render standings table with all teams", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("Champions United")).toBeInTheDocument();
      expect(screen.getByText("Second Place Squad")).toBeInTheDocument();
      expect(screen.getByText("Bronze Warriors")).toBeInTheDocument();
    });

    it("should display total points for each team", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("250.50")).toBeInTheDocument();
      expect(screen.getByText("245.00")).toBeInTheDocument();
      expect(screen.getByText("200.00")).toBeInTheDocument();
    });

    it("should show empty state when no standings", () => {
      renderWithRouter(<StandingsTable standings={[]} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("No standings data available")).toBeInTheDocument();
    });
  });

  describe("Rank Badges", () => {
    it("should show trophy icon for 1st place", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText(/🏆.*1st/)).toBeInTheDocument();
    });

    it("should show silver medal icon for 2nd place", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText(/🥈.*2nd/)).toBeInTheDocument();
    });

    it("should show bronze medal icon for 3rd place", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText(/🥉.*3rd/)).toBeInTheDocument();
    });

    it("should show plain rank for 4th place and below", () => {
      const standings: TeamStanding[] = [
        {
          ...mockStandings[0],
          currentRank: 4,
          teamName: "Fourth Place",
        },
      ];

      renderWithRouter(<StandingsTable standings={standings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      const badge = screen.getByText("4");
      expect(badge).toBeInTheDocument();
    });
  });

  describe("Movement Indicators", () => {
    it("should show up arrow for positive rank change", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("↑1")).toBeInTheDocument();
    });

    it("should show down arrow for negative rank change", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("↓1")).toBeInTheDocument();
    });

    it("should not show indicator for no rank change", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      // Only first two teams have rank changes; use \d to avoid matching sort-header arrows
      const arrows = screen.queryAllByText(/[↑↓]\d/);
      expect(arrows).toHaveLength(2);
    });
  });

  describe("7-Day Change Column", () => {
    it("should show dash when sevenDayPointChange is not present", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      // All mock standings lack sevenDayPointChange, so all rows show —
      const dashes = screen.getAllByText("—");
      expect(dashes.length).toBeGreaterThanOrEqual(3);
    });

    it("should display positive point change in green with + prefix", () => {
      const standings: TeamStanding[] = [
        { ...mockStandings[0], sevenDayPointChange: 12.5 },
      ];

      renderWithRouter(<StandingsTable standings={standings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("+12.50 pts")).toBeInTheDocument();
    });

    it("should display negative point change with no + prefix", () => {
      const standings: TeamStanding[] = [
        { ...mockStandings[0], sevenDayPointChange: -3.25 },
      ];

      renderWithRouter(<StandingsTable standings={standings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("-3.25 pts")).toBeInTheDocument();
    });

    it("should show rank change within the 7-day column", () => {
      const standings: TeamStanding[] = [
        { ...mockStandings[0], sevenDayPointChange: 10, rankChange: 2 },
      ];

      renderWithRouter(<StandingsTable standings={standings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("↑2 rank")).toBeInTheDocument();
    });

    it("should show no rank change indicator when rank is unchanged", () => {
      const standings: TeamStanding[] = [
        { ...mockStandings[0], sevenDayPointChange: 5, rankChange: 0 },
      ];

      renderWithRouter(<StandingsTable standings={standings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("— rank")).toBeInTheDocument();
    });
  });

  describe("Participants Remaining", () => {
    it("should show remaining count when participants are incomplete", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("3 remaining")).toBeInTheDocument();
      expect(screen.getByText("5 remaining")).toBeInTheDocument();
    });

    it("should show 'Complete' badge when all participants done", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("Complete")).toBeInTheDocument();
    });
  });

  describe("Table Structure", () => {
    it("should have correct table headers", () => {
      renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      expect(screen.getByText("Rank")).toBeInTheDocument();
      expect(screen.getByText("Team")).toBeInTheDocument();
      expect(screen.getByText("Points")).toBeInTheDocument();
      expect(screen.getByText("7-Day Change")).toBeInTheDocument();
      expect(screen.getByText("Remaining")).toBeInTheDocument();
    });

    it("should render teams in order by rank", () => {
      const { container } = renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      const rows = container.querySelectorAll("tbody tr");
      expect(rows).toHaveLength(3);

      expect(rows[0].textContent).toContain("Champions United");
      expect(rows[1].textContent).toContain("Second Place Squad");
      expect(rows[2].textContent).toContain("Bronze Warriors");
    });
  });

  describe("Tied Ranks", () => {
    it("should handle teams with same rank", () => {
      const tiedStandings: TeamStanding[] = [
        { ...mockStandings[0], currentRank: 1, teamName: "Team A" },
        { ...mockStandings[1], currentRank: 1, teamName: "Team B" },
        { ...mockStandings[2], currentRank: 3, teamName: "Team C" },
      ];

      renderWithRouter(<StandingsTable standings={tiedStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      const firstPlaceBadges = screen.getAllByText(/🏆.*1st/);
      expect(firstPlaceBadges).toHaveLength(2);

      expect(screen.getByText(/🥉.*3rd/)).toBeInTheDocument();
    });
  });

  describe("Accessibility", () => {
    it("should have title attributes for movement indicators", () => {
      const { container } = renderWithRouter(<StandingsTable standings={mockStandings} leagueId={mockLeagueId} seasonId={mockSeasonId} />);

      const upArrow = container.querySelector('[title*="Up"]');
      expect(upArrow).toBeInTheDocument();
      expect(upArrow?.getAttribute("title")).toContain("Up 1 place");

      const downArrow = container.querySelector('[title*="Down"]');
      expect(downArrow).toBeInTheDocument();
      expect(downArrow?.getAttribute("title")).toContain("Down 1 place");
    });
  });
});
