import { useMemo } from "react";
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "~/components/ui/table";
import { Badge } from "~/components/ui/badge";
import { TeamNameDisplay } from "~/components/ui/team-name-display";
import { PointsDisplay } from "~/components/standings/PointsDisplay";
import { useSortableData, type SortConfig, type SortDirection } from "~/hooks/useSortableData";
import { type TeamStanding } from "~/types/standings";

interface StandingsTableProps {
  standings: TeamStanding[];
  leagueId: string;
  seasonId: string;
}

// Flat row shape used for sorting
interface StandingRow extends TeamStanding {
  _sortPoints: number;
}

// Comparators are pure functions with no component state — define at module level
const comparators = {
  // Rank: ties broken alphabetically by team name regardless of sort direction
  currentRank: (a: StandingRow, b: StandingRow, dir: SortDirection) => {
    const cmp = a.currentRank - b.currentRank;
    if (cmp !== 0) return dir === "asc" ? cmp : -cmp;
    return a.teamName.localeCompare(b.teamName);
  },
  _sortPoints: (a: StandingRow, b: StandingRow, dir: SortDirection) => {
    const cmp = b._sortPoints - a._sortPoints;
    return dir === "asc" ? -cmp : cmp;
  },
  sevenDayPointChange: (a: StandingRow, b: StandingRow, dir: SortDirection) => {
    const aVal = a.sevenDayPointChange ?? 0;
    const bVal = b.sevenDayPointChange ?? 0;
    const cmp = bVal - aVal;
    return dir === "asc" ? -cmp : cmp;
  },
  teamName: (a: StandingRow, b: StandingRow, dir: SortDirection) => {
    const cmp = a.teamName.localeCompare(b.teamName);
    return dir === "asc" ? cmp : -cmp;
  },
  participantsRemaining: (a: StandingRow, b: StandingRow, dir: SortDirection) => {
    const cmp = a.participantsRemaining - b.participantsRemaining;
    return dir === "asc" ? cmp : -cmp;
  },
};

/**
 * Display team standings with ranking, points, 7-day change, and sortable columns.
 */
export function StandingsTable({ standings, leagueId, seasonId }: StandingsTableProps) {
  const rows: StandingRow[] = useMemo(
    () =>
      standings.map((s) => ({
        ...s,
        _sortPoints: s.actualPoints ?? s.totalPoints,
      })),
    [standings]
  );

  const { sortedData, sortConfig, requestSort } = useSortableData<StandingRow>(
    rows,
    "currentRank",
    "asc",
    comparators
  );

  return (
    <div className="rounded-md border">
      <Table>
        <TableHeader>
          <TableRow>
            <SortableHead
              label="Rank"
              sortKey="currentRank"
              sortConfig={sortConfig}
              onSort={() => requestSort("currentRank")}
              className="w-[110px]"
            />
            <SortableHead
              label="Team"
              sortKey="teamName"
              sortConfig={sortConfig}
              onSort={() => requestSort("teamName")}
            />
            <SortableHead
              label={
                <div>
                  <div>Points</div>
                  <div className="text-xs font-normal text-muted-foreground">actual / projected</div>
                </div>
              }
              sortKey="_sortPoints"
              sortConfig={sortConfig}
              onSort={() => requestSort("_sortPoints")}
              className="text-right"
            />
            <SortableHead
              label={
                <div>
                  <div>7-Day Change</div>
                  <div className="text-xs font-normal text-muted-foreground">pts / rank</div>
                </div>
              }
              sortKey="sevenDayPointChange"
              sortConfig={sortConfig}
              onSort={() => requestSort("sevenDayPointChange")}
              className="text-right"
            />
            <SortableHead
              label="Remaining"
              sortKey="participantsRemaining"
              sortConfig={sortConfig}
              onSort={() => requestSort("participantsRemaining")}
              className="text-right"
            />
          </TableRow>
        </TableHeader>
        <TableBody>
          {sortedData.length === 0 ? (
            <TableRow>
              <TableCell colSpan={5} className="text-center text-muted-foreground">
                No standings data available
              </TableCell>
            </TableRow>
          ) : (
            sortedData.map((standing) => (
              <TableRow key={standing.teamId}>
                <TableCell>
                  <div className="flex items-center gap-2">
                    <RankBadge rank={standing.currentRank} />
                    {standing.rankChange !== 0 && (
                      <MovementIndicator change={standing.rankChange} />
                    )}
                  </div>
                </TableCell>
                <TableCell className="font-medium">
                  <TeamNameDisplay
                    teamName={standing.teamName}
                    ownerName={standing.ownerName}
                    href={`/leagues/${leagueId}/standings/${seasonId}/teams/${standing.teamId}`}
                  />
                </TableCell>
                <TableCell className="text-right">
                  <PointsDisplay
                    actualPoints={standing.actualPoints}
                    projectedPoints={standing.projectedPoints}
                    totalPoints={standing.totalPoints}
                    participantsRemaining={standing.participantsRemaining}
                  />
                </TableCell>
                <TableCell className="text-right">
                  <SevenDayChange
                    pointChange={standing.sevenDayPointChange}
                    rankChange={standing.rankChange}
                  />
                </TableCell>
                <TableCell className="text-right text-muted-foreground">
                  {standing.participantsRemaining > 0 ? (
                    <Badge variant="secondary">
                      {standing.participantsRemaining} remaining
                    </Badge>
                  ) : (
                    <Badge variant="outline">Complete</Badge>
                  )}
                </TableCell>
              </TableRow>
            ))
          )}
        </TableBody>
      </Table>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Sub-components
// ---------------------------------------------------------------------------

interface SortableHeadProps {
  label: React.ReactNode;
  sortKey: keyof StandingRow;
  sortConfig: SortConfig<StandingRow>;
  onSort: () => void;
  className?: string;
}

function SortableHead({ label, sortKey, sortConfig, onSort, className }: SortableHeadProps) {
  const isActive = sortConfig.key === sortKey;
  const arrow = isActive ? (sortConfig.direction === "asc" ? " ↑" : " ↓") : " ↕";

  return (
    <TableHead
      className={`cursor-pointer select-none hover:text-foreground ${isActive ? "text-foreground" : "text-muted-foreground"} ${className ?? ""}`}
      onClick={onSort}
    >
      <span className="inline-flex items-baseline gap-0.5">
        {label}
        <span className="text-xs opacity-60">{arrow}</span>
      </span>
    </TableHead>
  );
}

function RankBadge({ rank }: { rank: number }) {
  if (rank === 1) {
    return (
      <Badge className="bg-amber-accent hover:bg-amber-accent/80 text-background font-bold">
        🏆 1st
      </Badge>
    );
  }
  if (rank === 2) {
    return (
      <Badge className="bg-muted hover:bg-muted/80 text-muted-foreground font-bold">
        🥈 2nd
      </Badge>
    );
  }
  if (rank === 3) {
    return (
      <Badge className="bg-coral-accent hover:bg-coral-accent/80 text-background font-bold">
        🥉 3rd
      </Badge>
    );
  }
  return (
    <Badge variant="outline" className="font-semibold">
      {rank}
    </Badge>
  );
}

function MovementIndicator({ change }: { change: number }) {
  if (change > 0) {
    return (
      <span
        className="text-emerald-400 text-sm font-medium"
        title={`Up ${change} ${change === 1 ? "place" : "places"} vs 7 days ago`}
      >
        ↑{change}
      </span>
    );
  }
  if (change < 0) {
    return (
      <span
        className="text-coral-accent text-sm font-medium"
        title={`Down ${Math.abs(change)} ${Math.abs(change) === 1 ? "place" : "places"} vs 7 days ago`}
      >
        ↓{Math.abs(change)}
      </span>
    );
  }
  return null;
}

function SevenDayChange({
  pointChange,
  rankChange,
}: {
  pointChange?: number;
  rankChange: number;
}) {
  const hasData = pointChange !== undefined;

  if (!hasData) {
    return <span className="text-muted-foreground text-sm">—</span>;
  }

  return (
    <div className="flex flex-col items-end gap-0.5">
      <span className={`text-sm font-medium ${pointChange >= 0 ? "text-emerald-400" : "text-coral-accent"}`}>
        {pointChange >= 0 ? "+" : ""}{pointChange.toFixed(2)} pts
      </span>
      {rankChange > 0 ? (
        <span className="text-xs text-emerald-400">↑{rankChange} rank</span>
      ) : rankChange < 0 ? (
        <span className="text-xs text-coral-accent">↓{Math.abs(rankChange)} rank</span>
      ) : (
        <span className="text-xs text-muted-foreground">— rank</span>
      )}
    </div>
  );
}
