import { useLoaderData, Link } from "react-router";
import { database } from "~/database/context";
import { eq } from "drizzle-orm";
import * as schema from "~/database/schema";
import { requireLeagueAccess } from "~/lib/auth";
import { Button } from "~/components/ui/button";
import { logger } from "~/lib/logger";
import { getSevenDayStandingsChange, getSeasonPointProgression } from "~/models/standings";
import { isSeasonComplete, getSeasonCompletionPercentage } from "~/lib/season-helpers.server";
import { getRecentTeamScoreEvents } from "~/models/team-score-events";
import { PointProgressionChart } from "~/components/standings/PointProgressionChart";
import { findUsersByIds, getUserDisplayName } from "~/models/user";
import { resolveUserAvatarData } from "~/lib/avatar-data";
import { StandingsPreview } from "~/components/league/StandingsPreview";
import { buildTiedRankChecker, getDisplayRank } from "~/lib/standings-display";
import { RecentScoresCard } from "~/components/standings/RecentScoresCard";
import type { Route } from "./+types/$leagueId.standings.$seasonId";

export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
  return [{ title: `Standings — ${data?.league?.name ?? "League"} - Brackt` }];
}

export async function loader(args: Route.LoaderArgs) {
  try {
    const { params } = args;
    const { leagueId, seasonId } = params;

    const db = database();

  // Fetch league
  const league = await db.query.leagues.findFirst({
    where: eq(schema.leagues.id, leagueId),
  });

  if (!league) {
    throw new Response("League not found", { status: 404 });
  }

  // Fetch season
  const season = await db.query.seasons.findFirst({
    where: eq(schema.seasons.id, seasonId),
  });

  if (!season || season.leagueId !== leagueId) {
    throw new Response("Season not found", { status: 404 });
  }

  // Check access
  await requireLeagueAccess(args, {
    leagueId,
    seasonId,
    db,
    unauthMessage: "You must be logged in to view standings",
    unauthorizedMessage: "You do not have access to this league",
  });

  // Fetch standings, teams (for owner lookup), and independent data in parallel
  const [standingsWithComparison, teams, progressionData, seasonComplete, completionPercentage, recentScoreEvents] =
    await Promise.all([
      getSevenDayStandingsChange(seasonId, db),
      db.query.teams.findMany({
        where: eq(schema.teams.seasonId, seasonId),
        columns: { id: true, ownerId: true, logoUrl: true, flagConfig: true, avatarType: true },
      }),
      getSeasonPointProgression(seasonId, db),
      isSeasonComplete(seasonId, db),
      getSeasonCompletionPercentage(seasonId, db),
      getRecentTeamScoreEvents(seasonId, 10, db),
    ]);

  // Build teamId -> ownerName map
  const ownerIds = [...new Set(teams.map((t) => t.ownerId).filter((id): id is string => id !== null))];
  const userRows = await findUsersByIds(ownerIds);
  const userById = new Map(userRows.map((u) => [u.id, u]));
  const ownerNameByTeamId = new Map(
    teams
      .filter((t): t is typeof t & { ownerId: string } => t.ownerId !== null)
      .map((t) => {
        const user = userById.get(t.ownerId);
        return [t.id, user ? getUserDisplayName(user) : null] as const;
      })
  );

  const ownerAvatarDataByUserId = new Map(userRows.map((u) => [u.id, resolveUserAvatarData(u)]));
  const teamById = new Map(teams.map((t) => [t.id, t]));

  // Map to format expected by component (use sevenDayRankChange instead of previousRank)
  const formattedStandings = standingsWithComparison.map((standing) => {
    const team = teamById.get(standing.teamId);
    const ownerAvatarData = team?.ownerId ? (ownerAvatarDataByUserId.get(team.ownerId) ?? null) : null;
    return {
      ...standing,
      rankChange: standing.sevenDayRankChange,
      ownerName: ownerNameByTeamId.get(standing.teamId) ?? null,
      logoUrl: team?.logoUrl ?? null,
      flagConfig: team?.flagConfig ?? null,
      avatarType: team?.avatarType ?? null,
      ownerAvatarData,
    };
  });

  // Enrich recentScoreEvents with owner names
  const enrichedScoreEvents = recentScoreEvents.map((event) => ({
    ...event,
    ownerName: ownerNameByTeamId.get(event.teamId) ?? null,
  }));

    return {
      league,
      season,
      standings: formattedStandings,
      progressionData,
      seasonComplete,
      completionPercentage,
      recentScoreEvents: enrichedScoreEvents,
    };
  } catch (error) {
    if (error instanceof Response) {
      throw error;
    }
    logger.error("Error loading standings:", error);
    throw error;
  }
}

export default function LeagueStandings() {
  const { league, season, standings, progressionData, seasonComplete, completionPercentage, recentScoreEvents } = useLoaderData<typeof loader>();

  const isTied = buildTiedRankChecker(standings.map((s) => s.currentRank));
  const previewEntries = standings.map((s) => ({
    teamId: s.teamId,
    teamName: s.teamName,
    ownerName: s.ownerName,
    logoUrl: s.logoUrl,
    flagConfig: s.flagConfig,
    avatarType: s.avatarType,
    ownerAvatarData: s.ownerAvatarData,
    displayRank: getDisplayRank(s, standings.length, isTied(s.currentRank)),
    currentRank: s.currentRank,
    points: s.totalPoints,
    rankChange: s.rankChange,
    pointChange: s.sevenDayPointChange,
    projectedPoints: s.projectedPoints,
    participantsRemaining: s.participantsRemaining,
    href: `/leagues/${league.id}/standings/${season.id}/teams/${s.teamId}`,
  }));

  return (
    <div className="container mx-auto py-8 px-4">
      {/* Header */}
      <div className="mb-8">
        <Button variant="ghost" className="mb-4" asChild>
          <Link to={`/leagues/${league.id}`}>
            ← Back to League
          </Link>
        </Button>

        <div className="flex items-center justify-between">
          <div>
            <h1 className="text-4xl font-bold mb-2">{league.name}</h1>
            <p className="text-muted-foreground text-lg">
              {season.year} Season Standings
            </p>
          </div>
          <div className="text-right">
            {seasonComplete ? (
              <div className="inline-flex items-center px-3 py-1 rounded-full bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-100 text-sm font-medium">
                ✓ Season Complete
              </div>
            ) : (
              <div className="text-sm text-muted-foreground">
                {completionPercentage}% Complete
              </div>
            )}
          </div>
        </div>
      </div>

      {/* Two-column layout */}
      <div className="grid gap-6 md:grid-cols-3">
        {/* Left: Standings + Point Progression (2/3 width) */}
        <div className="md:col-span-2 space-y-6">
          <StandingsPreview
            entries={previewEntries}
            description={seasonComplete ? "Final Standings" : "Current Standings"}
            showProjected={!seasonComplete}
          />

          {progressionData.chartData.length > 0 && (
            <PointProgressionChart
              chartData={progressionData.chartData}
              teams={progressionData.teams}
            />
          )}
        </div>

        {/* Right: Recent Scores (1/3 width) */}
        <RecentScoresCard events={recentScoreEvents} />
      </div>
    </div>
  );
}
