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 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;
}

/**
 * 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]
  );

  // Custom comparators
  const comparators = useMemo(
    () => ({
      // Rank: ascending by rank, ties broken alphabetically by team name
      currentRank: (a: StandingRow, b: StandingRow, dir: SortDirection) => {
        const cmp = a.currentRank - b.currentRank;
        if (cmp !== 0) return dir === "asc" ? cmp : -cmp;
        // Within ties, always sort by team name A→Z regardless of direction
        return a.teamName.localeCompare(b.teamName);
      },
      // Points: descending by default means best score first
      _sortPoints: (a: StandingRow, b: StandingRow, dir: SortDirection) => {
        const cmp = b._sortPoints - a._sortPoints;
        return dir === "asc" ? -cmp : cmp;
      },
      // 7-day point change: higher change = better, descending first
      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;
      },
      // Team name: A→Z ascending
      teamName: (a: StandingRow, b: StandingRow, dir: SortDirection) => {
        const cmp = a.teamName.localeCompare(b.teamName);
        return dir === "asc" ? cmp : -cmp;
      },
      // Remaining: fewer remaining = closer to done, ascending = most remaining first
      participantsRemaining: (a: StandingRow, b: StandingRow, dir: SortDirection) => {
        const cmp = a.participantsRemaining - b.participantsRemaining;
        return dir === "asc" ? cmp : -cmp;
      },
    }),
    []
  );

  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: string;
  sortConfig: { key: string | null; direction: "asc" | "desc" };
  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">
      {/* Point change — always non-negative */}
      <span className="text-sm font-medium text-emerald-400">
        +{pointChange.toFixed(2)} pts
      </span>
      {/* Rank change */}
      {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>
  );
}
