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

import { logger } from "~/lib/logger";
import { findSportsSeasonById, findSportsSeasonsBySportId } from "~/models/sports-season";
import {
  findParticipantsBySportsSeasonId,
  findParticipantByName,
  createParticipant,
  deleteParticipant,
  updateParticipant,
  copyParticipantsFromSeason,
} from "~/models/season-participant";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { Textarea } from "~/components/ui/textarea";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "~/components/ui/card";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "~/components/ui/table";
import { Plus, Trash2, ArrowLeft, Pencil, Check, X, Copy } from "lucide-react";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "~/components/ui/select";

export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
  return [{ title: `Participants — ${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 sameSportSeasons = (await findSportsSeasonsBySportId(sportsSeason.sportId))
    .filter((s) => s.id !== params.id)
    .toSorted((a, b) => b.year - a.year);

  // Type assertion since we know the sport relation is included
  return { 
    sportsSeason: sportsSeason as typeof sportsSeason & { sport: { id: string; name: string; type: string; slug: string } }, 
    participants,
    sameSportSeasons,
  };
}

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

  if (intent === "delete") {
    const participantId = formData.get("participantId");
    if (typeof participantId === "string") {
      await deleteParticipant(participantId);
    }
    return { success: true };
  }

  if (intent === "update-participant") {
    const participantId = formData.get("participantId");
    const newName = formData.get("newName");
    const newExternalId = formData.get("newExternalId");

    if (typeof participantId !== "string") {
      return { error: "Invalid participant", intent: "update-participant" };
    }

    if (typeof newName !== "string" || !newName.trim()) {
      return { error: "Name is required", intent: "update-participant" };
    }

    const trimmedName = newName.trim();
    const existing = await findParticipantByName(params.id, trimmedName);
    if (existing && existing.id !== participantId) {
      return { error: `"${trimmedName}" already exists in this season.`, intent: "update-participant" };
    }

    const externalIdValue =
      typeof newExternalId === "string" && newExternalId.trim()
        ? newExternalId.trim()
        : null;

    try {
      await updateParticipant(participantId, { name: trimmedName, externalId: externalIdValue });
      return { success: true, intent: "update-participant" };
    } catch (error) {
      logger.error("Error updating participant:", error);
      return { error: "Failed to update participant. Please try again.", intent: "update-participant" };
    }
  }

  if (intent === "update-name") {
    const participantId = formData.get("participantId");
    const newName = formData.get("newName");

    if (typeof participantId !== "string") {
      return { error: "Invalid participant", intent: "update-name" };
    }

    if (typeof newName !== "string" || !newName.trim()) {
      return { error: "Name is required", intent: "update-name" };
    }

    const trimmedName = newName.trim();
    const existing = await findParticipantByName(params.id, trimmedName);
    if (existing && existing.id !== participantId) {
      return { error: `"${trimmedName}" already exists in this season.`, intent: "update-name" };
    }

    try {
      await updateParticipant(participantId, { name: trimmedName });
      return { success: true, intent: "update-name" };
    } catch (error) {
      logger.error("Error updating participant:", error);
      return { error: "Failed to update participant. Please try again.", intent: "update-name" };
    }
  }

  // Bulk add participants
  if (intent === "bulk") {
    const bulkNames = formData.get("bulkNames");

    if (typeof bulkNames !== "string" || !bulkNames.trim()) {
      return { error: "Please enter at least one participant name" };
    }

    // Dedup case-insensitively, preserving first occurrence's casing
    const seenKeys = new Map<string, string>();
    for (const raw of bulkNames.split("\n").map(n => n.trim()).filter(n => n.length > 0)) {
      const key = raw.toLowerCase();
      if (!seenKeys.has(key)) seenKeys.set(key, raw);
    }
    const names = [...seenKeys.values()];

    if (names.length === 0) {
      return { error: "Please enter at least one participant name" };
    }

    try {
      const existingParticipants = await findParticipantsBySportsSeasonId(params.id);
      const existingNames = new Set(existingParticipants.map(p => p.name.toLowerCase()));

      const skipped: string[] = [];
      let added = 0;

      for (const name of names) {
        if (existingNames.has(name.toLowerCase())) {
          skipped.push(name);
          continue;
        }
        await createParticipant({
          sportsSeasonId: params.id,
          name,
          shortName: null,
          externalId: null,
          expectedValue: "0",
        });
        added++;
      }

      return { success: true, count: added, skipped };
    } catch (error) {
      logger.error("Error creating participants:", error);
      return { error: "Failed to add participants. Please try again." };
    }
  }

  if (intent === "copy-from-season") {
    const sourceSeasonId = formData.get("sourceSeasonId");
    if (typeof sourceSeasonId !== "string" || !sourceSeasonId) {
      return { error: "Please select a source season.", intent: "copy-from-season" };
    }

    const targetSeason = await findSportsSeasonById(params.id);
    if (!targetSeason) {
      return { error: "Target season not found.", intent: "copy-from-season" };
    }

    const sourceSeason = await findSportsSeasonById(sourceSeasonId);
    if (!sourceSeason) {
      return { error: "Source season not found.", intent: "copy-from-season" };
    }

    if (sourceSeason.sportId !== targetSeason.sportId) {
      return { error: "Source season must be the same sport.", intent: "copy-from-season" };
    }

    try {
      const result = await copyParticipantsFromSeason(sourceSeasonId, params.id);
      return { success: true, intent: "copy-from-season", copyResult: result };
    } catch (error) {
      logger.error("Error copying participants:", error);
      return { error: "Failed to copy participants. Please try again.", intent: "copy-from-season" };
    }
  }

  // Add single participant
  const name = formData.get("name");

  if (typeof name !== "string" || !name.trim()) {
    return { error: "Participant name is required" };
  }

  const trimmedName = name.trim();
  const existing = await findParticipantByName(params.id, trimmedName);
  if (existing) {
    return { error: `"${trimmedName}" already exists in this season.` };
  }

  try {
    await createParticipant({
      sportsSeasonId: params.id,
      name: trimmedName,
      shortName: null,
      externalId: null,
      expectedValue: "0",
    });

    return { success: true };
  } catch (error) {
    logger.error("Error creating participant:", error);
    return { error: "Failed to add participant. Please try again." };
  }
}

export default function ManageParticipants({ loaderData, actionData }: Route.ComponentProps) {
  const { sportsSeason, participants, sameSportSeasons } = loaderData;
  const [editing, setEditing] = useState<{ id: string; name: string; externalId: string } | null>(null);
  const [sourceSeasonId, setSourceSeasonId] = useState("");

  const cancelEdit = () => setEditing(null);

  // Use success state to reset forms by changing the key
  const formKey = actionData?.success ? Date.now() : 'static';

  useEffect(() => {
    if (actionData?.success && (actionData?.intent === "update-name" || actionData?.intent === "update-participant")) {
      cancelEdit();
    }
  }, [actionData]);

  return (
    <div className="p-8">
      <div className="max-w-4xl">
        <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">Manage Participants</h1>
          <p className="text-muted-foreground mt-1">
            {sportsSeason.sport.name} - {sportsSeason.name}
          </p>
        </div>

        <div className="grid gap-6 md:grid-cols-2 mb-6">
          <Card>
            <CardHeader>
              <CardTitle>Add Participant</CardTitle>
              <CardDescription>
                Add a {sportsSeason.sport.type === "team" ? "team" : "player"} to this season
              </CardDescription>
            </CardHeader>
            <CardContent>
              <Form method="post" className="space-y-4" key={`single-${formKey}`}>
                <div className="space-y-2">
                  <Label htmlFor="name">Participant Name</Label>
                  <Input
                    id="name"
                    name="name"
                    type="text"
                    placeholder={sportsSeason.sport.type === "team" ? "e.g., Kansas City Chiefs" : "e.g., Tiger Woods"}
                    required
                  />
                </div>

                {actionData?.error && !actionData?.count && actionData?.intent !== "update-name" && actionData?.intent !== "update-participant" && (
                  <div className="bg-destructive/15 text-destructive px-4 py-3 rounded-md text-sm">
                    {actionData.error}
                  </div>
                )}

                {actionData?.success && !actionData?.count && actionData?.intent !== "update-participant" && (
                  <div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
                    Participant added successfully!
                  </div>
                )}

                <Button type="submit" className="w-full">
                  <Plus className="mr-2 h-4 w-4" />
                  Add Participant
                </Button>
              </Form>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>Bulk Add Participants</CardTitle>
              <CardDescription>
                Add multiple participants at once (one per line)
              </CardDescription>
            </CardHeader>
            <CardContent>
              <Form method="post" className="space-y-4" key={`bulk-${formKey}`}>
                <input type="hidden" name="intent" value="bulk" />
                <div className="space-y-2">
                  <Label htmlFor="bulkNames">Participant Names</Label>
                  <Textarea
                    id="bulkNames"
                    name="bulkNames"
                    placeholder={sportsSeason.sport.type === "team" 
                      ? "Kansas City Chiefs\nBuffalo Bills\nSan Francisco 49ers" 
                      : "Tiger Woods\nRory McIlroy\nJon Rahm"}
                    rows={8}
                    className="font-mono text-sm"
                  />
                  <p className="text-xs text-muted-foreground">
                    Enter one participant name per line
                  </p>
                </div>

                {actionData?.error && actionData?.count === undefined && actionData?.intent !== "update-name" && actionData?.intent !== "update-participant" && (
                  <div className="bg-destructive/15 text-destructive px-4 py-3 rounded-md text-sm">
                    {actionData.error}
                  </div>
                )}

                {actionData?.success && actionData?.count !== undefined && (
                  <div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
                    {actionData.count} participant{actionData.count !== 1 ? 's' : ''} added.
                    {actionData.skipped && actionData.skipped.length > 0 && (
                      <span className="block mt-1 text-yellow-400">
                        {actionData.skipped.length} skipped (already exist): {actionData.skipped.join(", ")}
                      </span>
                    )}
                  </div>
                )}

                <Button type="submit" className="w-full">
                  <Plus className="mr-2 h-4 w-4" />
                  Add All Participants
                </Button>
              </Form>
            </CardContent>
          </Card>
        </div>

        {sameSportSeasons.length > 0 && (
          <Card className="mb-6">
            <CardHeader>
              <CardTitle>Copy from Another Season</CardTitle>
              <CardDescription>
                Copy participants and their EV data (odds, Elo, rankings) from an
                existing {sportsSeason.sport.name} season. Duplicates are skipped by name.
                Golf skills and tennis surface Elos are shared automatically via canonical
                player records.
              </CardDescription>
            </CardHeader>
            <CardContent>
              <Form method="post" className="space-y-4" key={`copy-${formKey}`}>
                <input type="hidden" name="intent" value="copy-from-season" />
                <div className="flex gap-4 items-end">
                  <div className="flex-1 space-y-2">
                    <Label htmlFor="sourceSeasonId">Source Season</Label>
                    <Select name="sourceSeasonId" value={sourceSeasonId} onValueChange={setSourceSeasonId}>
                      <SelectTrigger>
                        <SelectValue placeholder="Select a season to copy from" />
                      </SelectTrigger>
                      <SelectContent>
                        {sameSportSeasons.map((s) => (
                          <SelectItem key={s.id} value={s.id}>
                            {s.name} ({s.year}) — {s.status}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  </div>
                  <Button type="submit" disabled={!sourceSeasonId}>
                    <Copy className="mr-2 h-4 w-4" />
                    Copy Participants
                  </Button>
                </div>

                {actionData?.error && actionData?.intent === "copy-from-season" && (
                  <div className="bg-destructive/15 text-destructive px-4 py-3 rounded-md text-sm">
                    {actionData.error}
                  </div>
                )}

                {actionData?.success && actionData?.intent === "copy-from-season" && actionData.copyResult && (
                  <div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
                    {actionData.copyResult.copied} participant{actionData.copyResult.copied !== 1 ? "s" : ""} copied
                    {actionData.copyResult.skipped > 0 && `, ${actionData.copyResult.skipped} skipped (already exist)`}
                    {actionData.copyResult.evStubsCopied > 0 && ` — ${actionData.copyResult.evStubsCopied} EV stubs (odds/Elo) copied`}
                  </div>
                )}
              </Form>
            </CardContent>
          </Card>
        )}

        <Card>
            <CardHeader>
              <CardTitle>All Participants</CardTitle>
              <CardDescription>
                {participants.length} {participants.length === 1 ? "participant" : "participants"} total
              </CardDescription>
            </CardHeader>
            <CardContent>
              {participants.length === 0 ? (
                <p className="text-sm text-muted-foreground text-center py-8">
                  No participants yet. Add your first {sportsSeason.sport.type === "team" ? "team" : "player"}.
                </p>
              ) : (
                <div className="max-h-[500px] overflow-y-auto">
                  <Table>
                    <TableHeader>
                      <TableRow>
                        <TableHead>Name</TableHead>
                        <TableHead className="w-[120px]">Group</TableHead>
                        <TableHead className="w-[100px]" />
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {participants.map((participant) => (
                        <TableRow key={participant.id}>
                          <TableCell className="font-medium">
                            {editing?.id === participant.id ? (
                              <div className="space-y-1">
                                <Input
                                  value={editing.name}
                                  onChange={(e) => setEditing({ ...editing, name: e.target.value })}
                                  className="h-8"
                                  autoFocus
                                  onKeyDown={(e) => { if (e.key === "Escape") cancelEdit(); }}
                                />
                                {actionData?.error && (actionData?.intent === "update-name" || actionData?.intent === "update-participant") && (
                                  <p className="text-xs text-destructive">{actionData.error}</p>
                                )}
                              </div>
                            ) : (
                              participant.name
                            )}
                          </TableCell>
                          <TableCell>
                            {editing?.id === participant.id ? (
                              <Input
                                value={editing.externalId}
                                onChange={(e) => setEditing({ ...editing, externalId: e.target.value })}
                                className="h-8 font-mono text-xs"
                                placeholder="US, Intl, US:A…"
                                onKeyDown={(e) => { if (e.key === "Escape") cancelEdit(); }}
                              />
                            ) : (
                              <span className="text-xs font-mono text-muted-foreground">
                                {participant.externalId ?? "—"}
                              </span>
                            )}
                          </TableCell>
                          <TableCell>
                            {editing?.id === participant.id ? (
                              <div className="flex gap-1">
                                <Form method="post">
                                  <input type="hidden" name="intent" value="update-participant" />
                                  <input type="hidden" name="participantId" value={participant.id} />
                                  <input type="hidden" name="newName" value={editing.name} />
                                  <input type="hidden" name="newExternalId" value={editing.externalId} />
                                  <Button
                                    type="submit"
                                    variant="ghost"
                                    size="sm"
                                    className="h-8 w-8 p-0 text-emerald-500 hover:text-emerald-400"
                                  >
                                    <Check className="h-4 w-4" />
                                  </Button>
                                </Form>
                                <Button
                                  type="button"
                                  variant="ghost"
                                  size="sm"
                                  className="h-8 w-8 p-0"
                                  onClick={cancelEdit}
                                >
                                  <X className="h-4 w-4" />
                                </Button>
                              </div>
                            ) : (
                              <div className="flex gap-1">
                                <Button
                                  type="button"
                                  variant="ghost"
                                  size="sm"
                                  className="h-8 w-8 p-0"
                                  onClick={() => setEditing({ id: participant.id, name: participant.name, externalId: participant.externalId ?? "" })}
                                >
                                  <Pencil className="h-4 w-4" />
                                </Button>
                                <Form method="post">
                                  <input type="hidden" name="intent" value="delete" />
                                  <input type="hidden" name="participantId" value={participant.id} />
                                  <Button
                                    type="submit"
                                    variant="ghost"
                                    size="sm"
                                    className="h-8 w-8 p-0 text-destructive hover:text-destructive"
                                  >
                                    <Trash2 className="h-4 w-4" />
                                  </Button>
                                </Form>
                              </div>
                            )}
                          </TableCell>
                        </TableRow>
                      ))}
                    </TableBody>
                  </Table>
                </div>
              )}
            </CardContent>
          </Card>
      </div>
    </div>
  );
}
