import { Form, Link } from "react-router";
import type { Route } from "./+types/admin.sports-seasons.$id.regular-standings";

import { logger } from "~/lib/logger";
import { findSportsSeasonById } from "~/models/sports-season";
import { findParticipantsBySportsSeasonId } from "~/models/participant";
import { getRegularSeasonStandings, upsertManualStanding } from "~/models/regular-season-standings";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "~/components/ui/card";
import { ArrowLeft, Save, BarChart3 } from "lucide-react";

export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
  return [{ title: `Regular Season Standings — ${data?.sportsSeason?.name ?? "Sports Season"} - Brackt Admin` }];
}

export async function loader({ params }: Route.LoaderArgs) {
  const sportsSeason = await findSportsSeasonById(params.id);
  if (!sportsSeason) {
    throw new Response("Sports season not found", { status: 404 });
  }

  const participants = await findParticipantsBySportsSeasonId(params.id);
  const standingsRecords = await getRegularSeasonStandings(params.id);

  // Build a map of existing records keyed by participantId
  const standingsMap = Object.fromEntries(
    standingsRecords.map((r) => [r.participantId, r])
  );

  return {
    sportsSeason: sportsSeason as typeof sportsSeason & { sport: { id: string; name: string; type: string } },
    participants,
    standingsMap,
  };
}

export async function action({ request, params }: Route.ActionArgs) {
  const formData = await request.formData();

  // Parse updates from form fields: wins_<id>, losses_<id>, otLosses_<id>, conference_<id>, division_<id>
  const byId = new Map<
    string,
    {
      wins?: number;
      losses?: number;
      otLosses?: number | null;
      conference?: string | null;
      division?: string | null;
    }
  >();

  for (const [key, value] of formData.entries()) {
    const winsMatch = key.match(/^wins_(.+)$/);
    const lossesMatch = key.match(/^losses_(.+)$/);
    const otMatch = key.match(/^otLosses_(.+)$/);
    const confMatch = key.match(/^conference_(.+)$/);
    const divMatch = key.match(/^division_(.+)$/);

    if (winsMatch) {
      const id = winsMatch[1];
      const wins = parseInt(value as string, 10);
      if (!isNaN(wins)) byId.set(id, { ...byId.get(id), wins });
    } else if (lossesMatch) {
      const id = lossesMatch[1];
      const losses = parseInt(value as string, 10);
      if (!isNaN(losses)) byId.set(id, { ...byId.get(id), losses });
    } else if (otMatch) {
      const id = otMatch[1];
      const otLosses = value === "" ? null : parseInt(value as string, 10);
      byId.set(id, { ...byId.get(id), otLosses: isNaN(otLosses as number) ? null : otLosses });
    } else if (confMatch) {
      const id = confMatch[1];
      byId.set(id, { ...byId.get(id), conference: (value as string).trim() || null });
    } else if (divMatch) {
      const id = divMatch[1];
      byId.set(id, { ...byId.get(id), division: (value as string).trim() || null });
    }
  }

  try {
    for (const [participantId, data] of byId.entries()) {
      if (data.wins === null && data.losses === null) continue;
      const wins = data.wins ?? 0;
      const losses = data.losses ?? 0;
      const gamesPlayed = wins + losses + (data.otLosses ?? 0);
      const winPct = gamesPlayed > 0 ? wins / gamesPlayed : 0;

      await upsertManualStanding(participantId, params.id, {
        wins,
        losses,
        otLosses: data.otLosses ?? null,
        gamesPlayed,
        winPct,
        conference: data.conference ?? null,
        division: data.division ?? null,
      });
    }
    return { success: true };
  } catch (error) {
    logger.error("Error saving regular season standings:", error);
    return { error: "Failed to save standings. Please try again." };
  }
}

export default function ManageRegularStandings({ loaderData, actionData }: Route.ComponentProps) {
  const { sportsSeason, participants, standingsMap } = loaderData;
  const isNhl = sportsSeason.sport?.name?.toLowerCase().includes("nhl") ||
    sportsSeason.sport?.name?.toLowerCase().includes("hockey");

  // Sort participants: those with records first (by wins desc), then unrecorded
  const sorted = [...participants].toSorted((a, b) => {
    const recA = standingsMap[a.id];
    const recB = standingsMap[b.id];
    if (recA && recB) return (recB.wins ?? 0) - (recA.wins ?? 0);
    if (recA) return -1;
    if (recB) return 1;
    return a.name.localeCompare(b.name);
  });

  return (
    <div className="p-8">
      <div className="max-w-3xl">
        <div className="mb-6">
          <Button variant="ghost" size="sm" asChild className="mb-2">
            <Link to={`/admin/sports-seasons/${sportsSeason.id}`}>
              <ArrowLeft className="mr-2 h-4 w-4" />
              Back to Sports Season
            </Link>
          </Button>
          <h1 className="text-3xl font-bold">Regular Season Standings</h1>
          <p className="text-muted-foreground mt-1">
            {sportsSeason.sport.name} — {sportsSeason.name}
          </p>
          <p className="text-sm text-muted-foreground mt-1">
            Manually enter W/L records. These will be overwritten on the next auto-sync unless you use this page again afterward.
          </p>
        </div>

        <div className="space-y-6">
          {actionData?.error && (
            <div className="bg-destructive/15 text-destructive px-4 py-3 rounded-md text-sm">
              {actionData.error}
            </div>
          )}
          {actionData?.success && (
            <div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
              Standings saved.
            </div>
          )}

          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                <BarChart3 className="h-5 w-5" />
                W/L Records
              </CardTitle>
              <CardDescription>
                Enter wins, losses{isNhl ? ", and OT losses" : ""} for each team. Conference and division are optional but improve the standings display.
              </CardDescription>
            </CardHeader>
            <CardContent>
              <Form method="post">
                <input type="hidden" name="_isNhl" value={isNhl ? "true" : "false"} />

                <div className="space-y-1 mb-4">
                  <div className={`grid gap-2 px-2 pb-1 text-xs font-medium text-muted-foreground uppercase tracking-wide border-b ${isNhl ? "grid-cols-[1fr_3.5rem_3.5rem_3.5rem_6rem_6rem]" : "grid-cols-[1fr_3.5rem_3.5rem_6rem_6rem]"}`}>
                    <span>Team</span>
                    <span>W</span>
                    <span>L</span>
                    {isNhl && <span>OTL</span>}
                    <span>Conference</span>
                    <span>Division</span>
                  </div>

                  {sorted.map((participant) => {
                    const record = standingsMap[participant.id];
                    const isSynced = record && record.syncedAt !== null;
                    return (
                      <div
                        key={participant.id}
                        className={`grid gap-2 items-center px-2 py-1.5 rounded hover:bg-muted/40 ${isNhl ? "grid-cols-[1fr_3.5rem_3.5rem_3.5rem_6rem_6rem]" : "grid-cols-[1fr_3.5rem_3.5rem_6rem_6rem]"}`}
                      >
                        <span className="text-sm font-medium truncate flex items-center gap-1.5">
                          {participant.name}
                          {isSynced && (
                            <span className="text-xs text-muted-foreground font-normal">(synced)</span>
                          )}
                        </span>
                        <Input
                          name={`wins_${participant.id}`}
                          type="number"
                          min="0"
                          defaultValue={record?.wins ?? ""}
                          placeholder="—"
                          className="h-8 text-sm"
                        />
                        <Input
                          name={`losses_${participant.id}`}
                          type="number"
                          min="0"
                          defaultValue={record?.losses ?? ""}
                          placeholder="—"
                          className="h-8 text-sm"
                        />
                        {isNhl && (
                          <Input
                            name={`otLosses_${participant.id}`}
                            type="number"
                            min="0"
                            defaultValue={record?.otLosses ?? ""}
                            placeholder="—"
                            className="h-8 text-sm"
                          />
                        )}
                        <Input
                          name={`conference_${participant.id}`}
                          type="text"
                          defaultValue={record?.conference ?? ""}
                          placeholder="Eastern"
                          className="h-8 text-sm"
                        />
                        <Input
                          name={`division_${participant.id}`}
                          type="text"
                          defaultValue={record?.division ?? ""}
                          placeholder="Atlantic"
                          className="h-8 text-sm"
                        />
                      </div>
                    );
                  })}
                </div>

                <Button type="submit" className="w-full">
                  <Save className="mr-2 h-4 w-4" />
                  Save Standings
                </Button>
              </Form>
            </CardContent>
          </Card>
        </div>
      </div>
    </div>
  );
}
