import { useState } from "react";
import { Form, redirect, Link } from "react-router";
import { getAuth } from "@clerk/react-router/server";
import type { Route } from "./+types/new";

import { logger } from "~/lib/logger";
import { createLeague, setCurrentSeason } from "~/models/league";
import { createCommissioner } from "~/models/commissioner";
import { createSeason } from "~/models/season";
import { linkMultipleSportsToSeason } from "~/models/season-sport";
import { createManyTeams } from "~/models/team";
import { findActiveSeasonTemplates, findSeasonTemplateWithSportsSeasons } from "~/models/season-template";
import { findDraftableSportsSeasons } from "~/models/sports-season";
import { generateUniqueTeamNames } from "~/utils/team-names";
import { format } from "date-fns";
import { CalendarIcon, Check } from "lucide-react";
import { Button } from "~/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "~/components/ui/card";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "~/components/ui/select";
import { Badge } from "~/components/ui/badge";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { Checkbox } from "~/components/ui/checkbox";
import { Calendar } from "~/components/ui/calendar";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "~/components/ui/popover";
import { cn } from "~/lib/utils";
import { parseDraftSpeed } from "~/lib/draft-timer";
import { ScoringRulesEditor } from "~/components/scoring/ScoringRulesEditor";

export function meta(): Route.MetaDescriptors {
  return [{ title: "New League - Brackt" }];
}

export async function loader() {
  const templates = await findActiveSeasonTemplates();
  const allSportsSeasons = await findDraftableSportsSeasons();
  
  // Fetch templates with their sports seasons for mapping
  const templatesWithSports = await Promise.all(
    templates.map(async (template) => {
      const templateWithSports = await findSeasonTemplateWithSportsSeasons(template.id);
      return {
        ...template,
        sportsSeasonIds: templateWithSports?.seasonTemplateSports?.map(
          (ts: { sportsSeason: { id: string } }) => ts.sportsSeason.id
        ) || []
      };
    })
  );
  
  return {
    templates: templatesWithSports,
    allSportsSeasons: allSportsSeasons as Array<typeof allSportsSeasons[0] & { sport: { id: string; name: string; type: string; slug: string } }>
  };
}

export async function action(args: Route.ActionArgs) {
  const { userId } = await getAuth(args);
  const { request } = args;
  
  if (!userId) {
    throw new Response("Unauthorized", { status: 401 });
  }

  const formData = await request.formData();
  const name = formData.get("name");
  const teamCount = formData.get("teamCount");
  const templateId = formData.get("templateId");
  const draftRounds = formData.get("draftRounds");
  const draftDateTime = formData.get("draftDateTime");
  const draftSpeed = formData.get("draftSpeed");
  const draftTimerMode = (formData.get("draftTimerMode") as "chess_clock" | "standard") || "chess_clock";

  // Map draft speed to time values
  const { draftInitialTime: draftInitialTimeNum, draftIncrementTime: draftIncrementTimeNum } =
    parseDraftSpeed(draftSpeed as string | null, draftTimerMode);

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

  if (typeof teamCount !== "string") {
    return { error: "Number of teams is required" };
  }

  const teamCountNum = parseInt(teamCount, 10);
  if (isNaN(teamCountNum) || teamCountNum < 6 || teamCountNum > 16) {
    return { error: "Number of teams must be between 6 and 16" };
  }

  const draftRoundsNum = typeof draftRounds === "string" ? parseInt(draftRounds, 10) : 20;
  if (isNaN(draftRoundsNum) || draftRoundsNum < 1 || draftRoundsNum > 50) {
    return { error: "Draft rounds must be between 1 and 50" };
  }

  // Extract and validate scoring rules
  const scoringFields = [
    "pointsFor1st", "pointsFor2nd", "pointsFor3rd", "pointsFor4th",
    "pointsFor5th", "pointsFor6th", "pointsFor7th", "pointsFor8th"
  ];

  const scoringRules: Record<string, number> = {};
  for (const field of scoringFields) {
    const value = formData.get(field);
    if (typeof value === "string") {
      const points = parseInt(value, 10);
      if (!isNaN(points)) {
        if (points < 0 || points > 1000) {
          return { error: `${field} must be between 0 and 1000 points` };
        }
        scoringRules[field] = points;
      }
    }
  }

  try {
    // Create league
    const league = await createLeague({
      name: name.trim(),
      createdBy: userId,
    });

    // Make creator a commissioner
    await createCommissioner({
      leagueId: league.id,
      userId: userId,
    });

    // Create first season
    const currentYear = new Date().getFullYear();
    const season = await createSeason({
      leagueId: league.id,
      year: currentYear,
      status: "pre_draft",
      templateId: typeof templateId === "string" && templateId !== "" ? templateId : null,
      draftRounds: draftRoundsNum,
      draftDateTime: typeof draftDateTime === "string" && draftDateTime ? new Date(draftDateTime) : null,
      draftInitialTime: draftInitialTimeNum,
      draftIncrementTime: draftIncrementTimeNum,
      draftTimerMode,
      ...scoringRules,
    });

    // Set this as the current season for the league
    await setCurrentSeason(league.id, season.id);

    // Add selected sports to the season
    const selectedSports = formData.getAll("sportsSeasons");
    
    // Validate that draft rounds is at least the number of sports
    if (selectedSports.length > draftRoundsNum) {
      return { 
        error: `You need at least ${selectedSports.length} draft rounds for the ${selectedSports.length} sports selected. Currently set to ${draftRoundsNum} rounds.` 
      };
    }
    
    if (selectedSports.length > 0) {
      await linkMultipleSportsToSeason(
        selectedSports.map((id) => ({
          seasonId: season.id,
          sportsSeasonId: id as string,
        }))
      );
    }

    // Create teams with fun random names
    const joinAsPlayer = formData.get("joinAsPlayer") === "on";
    const teamNames = generateUniqueTeamNames(teamCountNum);
    const teams = teamNames.map((teamName, i) => ({
      seasonId: season.id,
      name: teamName,
      ownerId: joinAsPlayer && i === 0 ? userId : null,
    }));

    await createManyTeams(teams);

    // Redirect to league homepage
    return redirect(`/leagues/${league.id}`);
  } catch (error) {
    logger.error("Error creating league:", error);
    return { error: "Failed to create league. Please try again." };
  }
}

export default function NewLeague({ loaderData, actionData }: Route.ComponentProps) {
  const { templates, allSportsSeasons } = loaderData;
  const [selectedTemplate, setSelectedTemplate] = useState<string>("");
  const [selectedSports, setSelectedSports] = useState<Set<string>>(new Set());
  const [draftRounds, setDraftRounds] = useState<number>(20);
  const [draftDate, setDraftDate] = useState<Date>();
  const [draftTime, setDraftTime] = useState<string>("");
  const [timerMode, setTimerMode] = useState<"chess_clock" | "standard">("chess_clock");

  const handleSportToggle = (sportId: string) => {
    const newSelected = new Set(selectedSports);
    if (newSelected.has(sportId)) {
      newSelected.delete(sportId);
    } else {
      newSelected.add(sportId);
    }
    setSelectedSports(newSelected);
  };

  const handleTemplateClick = (templateId: string, sportsSeasonIds: string[]) => {
    setSelectedTemplate(templateId);
    setSelectedSports(new Set(sportsSeasonIds));
  };

  // Calculate flex spots and minimum rounds
  const sportsCount = selectedSports.size;
  const minRounds = sportsCount;
  const recommendedRounds = Math.ceil(sportsCount * 1.25);
  const flexSpots = Math.max(0, draftRounds - sportsCount);

  return (
    <div className="container max-w-2xl mx-auto py-8 px-4">
      <Card>
        <CardHeader>
          <CardTitle className="text-3xl">Start a New League</CardTitle>
          <CardDescription>
            Create your fantasy league and invite your friends to compete.
          </CardDescription>
        </CardHeader>
        <CardContent>
          <Form method="post" className="space-y-6">
            <div className="space-y-2">
              <Label htmlFor="name">League Name</Label>
              <Input
                id="name"
                name="name"
                type="text"
                placeholder="Enter league name"
                required
                minLength={3}
                maxLength={50}
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="teamCount">Number of Teams</Label>
              <Select name="teamCount" defaultValue="12" required>
                <SelectTrigger id="teamCount">
                  <SelectValue placeholder="Select number of teams" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="6">6 Teams</SelectItem>
                  <SelectItem value="7">7 Teams</SelectItem>
                  <SelectItem value="8">8 Teams</SelectItem>
                  <SelectItem value="9">9 Teams</SelectItem>
                  <SelectItem value="10">10 Teams</SelectItem>
                  <SelectItem value="11">11 Teams</SelectItem>
                  <SelectItem value="12">12 Teams</SelectItem>
                  <SelectItem value="13">13 Teams</SelectItem>
                  <SelectItem value="14">14 Teams</SelectItem>
                  <SelectItem value="15">15 Teams</SelectItem>
                  <SelectItem value="16">16 Teams</SelectItem>
                </SelectContent>
              </Select>
              <p className="text-sm text-muted-foreground">
                Choose between 6 and 16 teams
              </p>
            </div>

            <div className="space-y-2">
              <Label htmlFor="draftRounds">Draft Rounds</Label>
              <Select 
                name="draftRounds" 
                value={draftRounds.toString()} 
                onValueChange={(value) => setDraftRounds(parseInt(value))}
                required
              >
                <SelectTrigger id="draftRounds">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {Array.from({ length: 50 }, (_, i) => i + 1)
                    .filter(num => num >= minRounds)
                    .map((num) => (
                      <SelectItem 
                        key={num} 
                        value={num.toString()}
                      >
                        {num} Round{num !== 1 ? 's' : ''}
                        {num === recommendedRounds && ' (recommended)'}
                      </SelectItem>
                    ))}
                </SelectContent>
              </Select>
              <div className="space-y-1">
                <p className="text-sm text-muted-foreground">
                  Minimum: {minRounds} (number of sports selected)
                  {recommendedRounds > minRounds && ` • Recommended: ${recommendedRounds}`}
                </p>
                {sportsCount > 0 && draftRounds < sportsCount && (
                  <p className="text-sm font-medium text-destructive">
                    ⚠️ You need at least {sportsCount} rounds for the {sportsCount} sports selected
                  </p>
                )}
                {sportsCount > 0 && draftRounds >= sportsCount && (
                  <p className="text-sm font-medium text-primary">
                    Flex Spots: {flexSpots}
                  </p>
                )}
              </div>
            </div>

            <div className="space-y-2">
              <Label htmlFor="draftDate">Draft Date & Time</Label>
              <div className="grid gap-2 sm:grid-cols-2">
                <Popover>
                  <PopoverTrigger asChild>
                    <Button
                      variant={"outline"}
                      className={cn(
                        "justify-start text-left font-normal",
                        !draftDate && "text-muted-foreground"
                      )}
                    >
                      <CalendarIcon className="mr-2 h-4 w-4" />
                      {draftDate ? format(draftDate, "PPP") : <span>Pick a date</span>}
                    </Button>
                  </PopoverTrigger>
                  <PopoverContent className="w-auto p-0">
                    <Calendar
                      mode="single"
                      selected={draftDate}
                      onSelect={setDraftDate}
                      initialFocus
                      disabled={(date) => date < new Date(new Date().setHours(0, 0, 0, 0))}
                    />
                  </PopoverContent>
                </Popover>
                <Input
                  type="time"
                  value={draftTime}
                  onChange={(e) => setDraftTime(e.target.value)}
                  placeholder="Select time"
                />
              </div>
              {draftDate && draftTime && (
                <input 
                  type="hidden" 
                  name="draftDateTime" 
                  value={new Date(`${format(draftDate, "yyyy-MM-dd")}T${draftTime}`).toISOString()} 
                />
              )}
              <p className="text-sm text-muted-foreground">
                You must set a draft date and time before starting the draft
              </p>
            </div>

            <div className="space-y-2">
              <Label htmlFor="draftTimerMode">Timer Mode</Label>
              <select
                id="draftTimerMode"
                name="draftTimerMode"
                className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
                value={timerMode}
                onChange={(e) => setTimerMode(e.target.value as "chess_clock" | "standard")}
                required
              >
                <option value="chess_clock">Chess Clock (accumulating bank)</option>
                <option value="standard">Standard (per-pick countdown)</option>
              </select>
              <p className="text-sm text-muted-foreground">
                Chess Clock: unused time carries over between picks. Standard: timer resets each pick.
              </p>
            </div>

            <div className="space-y-2">
              <Label htmlFor="draftSpeed">Draft Speed</Label>
              <select
                id="draftSpeed"
                name="draftSpeed"
                className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
                defaultValue={timerMode === "standard" ? "90" : "standard"}
                key={timerMode}
                required
              >
                {timerMode === "standard" ? (
                  <>
                    <option value="15">15 seconds</option>
                    <option value="30">30 seconds</option>
                    <option value="60">1 minute</option>
                    <option value="90">90 seconds (default)</option>
                    <option value="120">2 minutes</option>
                    <option value="900">15 minutes</option>
                    <option value="3600">1 hour</option>
                    <option value="7200">2 hours</option>
                    <option value="14400">4 hours</option>
                    <option value="28800">8 hours</option>
                    <option value="43200">12 hours</option>
                  </>
                ) : (
                  <>
                    <option value="fast">Fast (1 min + 10 sec)</option>
                    <option value="standard">Standard (2 min + 15 sec)</option>
                    <option value="slow">Slow (8 hours + 1 hour)</option>
                    <option value="very-slow">Very Slow (12 hours + 1 hour)</option>
                  </>
                )}
              </select>
              <p className="text-sm text-muted-foreground">
                {timerMode === "standard"
                  ? "Time per pick — resets to this value after each selection"
                  : "Initial time bank + increment added after each pick"}
              </p>
            </div>

            <ScoringRulesEditor disabled={false} />

            <div className="space-y-4">
              <Label>Sports Selection</Label>
              <p className="text-sm text-muted-foreground">
                Choose a template to auto-select sports, or manually select your own
              </p>
              
              <input type="hidden" name="templateId" value={selectedTemplate} />
              
              {/* Template Cards */}
              {templates.length > 0 && (
                <div className="grid gap-3">
                  {templates.map((template) => (
                    <Card
                      key={template.id}
                      className={`cursor-pointer transition-all ${
                        selectedTemplate === template.id
                          ? "ring-2 ring-primary"
                          : "hover:border-primary/50"
                      }`}
                      onClick={() => handleTemplateClick(template.id, template.sportsSeasonIds)}
                    >
                      <CardHeader className="pb-3">
                        <div className="flex items-start justify-between">
                          <div className="flex-1">
                            <CardTitle className="text-lg">{template.name}</CardTitle>
                            <CardDescription>{template.year}</CardDescription>
                          </div>
                          {selectedTemplate === template.id && (
                            <div className="rounded-full bg-primary text-primary-foreground p-1">
                              <Check className="h-4 w-4" />
                            </div>
                          )}
                        </div>
                      </CardHeader>
                      {template.description && (
                        <CardContent className="pt-0">
                          <p className="text-sm text-muted-foreground">{template.description}</p>
                        </CardContent>
                      )}
                    </Card>
                  ))}
                </div>
              )}

              {/* Sports Checkboxes */}
              <div className="space-y-3">
                <div className="bg-muted/50 border border-muted-foreground/20 rounded-md p-3">
                  <p className="text-sm text-muted-foreground">
                    <strong>Recommendation:</strong> Select 16-20 sports seasons for optimal league balance and variety.
                  </p>
                </div>
                <div className="space-y-2">
                  <Label className="text-sm font-medium">
                    Sports Seasons ({selectedSports.size} selected)
                  </Label>
                  <div className="max-h-64 overflow-y-auto border rounded-md p-3 space-y-2">
                    {allSportsSeasons.length > 0 ? (
                      allSportsSeasons.map((season) => (
                        <div key={season.id} className="flex items-center space-x-2">
                          <Checkbox
                            id={season.id}
                            name="sportsSeasons"
                            value={season.id}
                            checked={selectedSports.has(season.id)}
                            onCheckedChange={() => handleSportToggle(season.id)}
                          />
                          <Label
                            htmlFor={season.id}
                            className="font-normal cursor-pointer flex-1"
                          >
                            <span className="font-medium">{season.sport.name}</span> - {season.name} ({season.year})
                            <Badge variant="outline" className="ml-2 text-xs">
                              {season.scoringType.replace("_", " ")}
                            </Badge>
                          </Label>
                        </div>
                      ))
                    ) : (
                      <p className="text-sm text-muted-foreground">
                        No sports seasons available
                      </p>
                    )}
                  </div>
                </div>
              </div>
            </div>

            <div className="flex items-center space-x-2">
              <Checkbox
                id="joinAsPlayer"
                name="joinAsPlayer"
                defaultChecked={true}
              />
              <Label htmlFor="joinAsPlayer" className="font-normal cursor-pointer">
                I want to play in this league (claim a team)
              </Label>
            </div>

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

            <div className="flex gap-4">
              <Button type="submit" className="flex-1">
                Create League
              </Button>
              <Button type="button" variant="outline" asChild>
                <Link to="/">Cancel</Link>
              </Button>
            </div>
          </Form>
        </CardContent>
      </Card>
    </div>
  );
}
