import { useEffect, useState, type ReactNode } from "react";
import { Controller, useForm } from "react-hook-form";
import { CheckCircle2, Loader2, Send } from "lucide-react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { LOCATIONS, REGIONS, ROLES, type RoleId } from "@/lib/careers";
import { applicantSchema, submitApplication } from "@/lib/applicants";
import { cn } from "@/lib/utils";

type FormValues = {
  name: string;
  email: string;
  phone: string;
  age: string;
  location: string;
  role: string;
};

type Props = {
  preferredRole?: RoleId | null;
  onRoleChange?: (role: RoleId | null) => void;
};

export function ApplicationForm({ preferredRole, onRoleChange }: Props) {
  const [submittedId, setSubmittedId] = useState<string | null>(null);

  const form = useForm<FormValues>({
    defaultValues: {
      name: "",
      email: "",
      phone: "",
      age: "",
      location: "",
      role: preferredRole ?? "",
    },
    mode: "onBlur",
  });

  useEffect(() => {
    if (preferredRole) {
      form.setValue("role", preferredRole, { shouldValidate: true });
    }
  }, [preferredRole, form]);

  async function onSubmit(raw: FormValues) {
    const parsed = applicantSchema.safeParse({
      ...raw,
      age: raw.age === "" ? NaN : Number(raw.age),
      notes: "",
    });

    if (!parsed.success) {
      const fieldErrors = parsed.error.flatten().fieldErrors;
      (Object.keys(fieldErrors) as Array<keyof FormValues>).forEach((key) => {
        const msg = fieldErrors[key as keyof typeof fieldErrors]?.[0];
        if (msg) form.setError(key, { message: msg });
      });
      toast.error("Please check the form and try again.");
      return;
    }

    try {
      const result = await submitApplication({ data: parsed.data });
      setSubmittedId(result.id);
      toast.success("Application received");
      form.reset({
        name: "",
        email: "",
        phone: "",
        age: "",
        location: "",
        role: preferredRole ?? "",
      });
    } catch {
      toast.error("Could not submit application. Please try again.");
    }
  }

  if (submittedId) {
    return (
      <div className="flex flex-col items-start gap-4 rounded-[var(--radius-xl)] border border-[color-mix(in_oklab,var(--color-success)_35%,var(--color-border))] bg-[color-mix(in_oklab,var(--color-success)_8%,var(--color-surface))] p-6 sm:p-8">
        <div className="flex size-12 items-center justify-center rounded-full bg-[color-mix(in_oklab,var(--color-success)_18%,transparent)] text-[var(--color-success)]">
          <CheckCircle2 className="size-6" strokeWidth={2} />
        </div>
        <div className="space-y-2">
          <h3 className="font-display text-2xl font-semibold tracking-tight">Application submitted</h3>
          <p className="max-w-md text-sm leading-relaxed text-[var(--color-fg-muted)]">
            Thanks for applying to Perfect Game SEC. Our tournament staff will review your
            information and reach out if there is a match for your location and role.
          </p>
          <p className="text-xs text-[var(--color-fg-subtle)]">Reference · {submittedId.slice(0, 8)}</p>
        </div>
        <Button type="button" variant="secondary" onClick={() => setSubmittedId(null)}>
          Submit another application
        </Button>
      </div>
    );
  }

  const {
    register,
    handleSubmit,
    control,
    formState: { errors, isSubmitting },
  } = form;

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-3" noValidate>
      <div className="grid gap-x-4 gap-y-2 sm:grid-cols-2">
        <Field label="Full name" htmlFor="name" error={errors.name?.message}>
          <Input
            id="name"
            autoComplete="name"
            placeholder="Alex Morgan"
            aria-invalid={!!errors.name}
            {...register("name")}
          />
        </Field>
        <Field label="Email" htmlFor="email" error={errors.email?.message}>
          <Input
            id="email"
            type="email"
            autoComplete="email"
            placeholder="you@email.com"
            aria-invalid={!!errors.email}
            {...register("email")}
          />
        </Field>
        <Field label="Phone" htmlFor="phone" error={errors.phone?.message}>
          <Input
            id="phone"
            type="tel"
            autoComplete="tel"
            placeholder="(555) 555-0123"
            aria-invalid={!!errors.phone}
            {...register("phone")}
          />
        </Field>
        <Field label="Age" htmlFor="age" error={errors.age?.message}>
          <Input
            id="age"
            type="number"
            inputMode="numeric"
            min={16}
            max={99}
            placeholder="18"
            aria-invalid={!!errors.age}
            {...register("age")}
          />
        </Field>
        <Field label="Hiring location" htmlFor="location" error={errors.location?.message}>
          <Controller
            control={control}
            name="location"
            render={({ field }) => (
              <Select value={field.value || undefined} onValueChange={field.onChange}>
                <SelectTrigger id="location" aria-invalid={!!errors.location}>
                  <SelectValue placeholder="Select a region" />
                </SelectTrigger>
                <SelectContent>
                  {REGIONS.map((region) => (
                    <SelectGroup key={region}>
                      <SelectLabel>{region}</SelectLabel>
                      {LOCATIONS.filter((l) => l.region === region).map((loc) => (
                        <SelectItem key={loc.id} value={loc.id}>
                          {loc.label}
                        </SelectItem>
                      ))}
                    </SelectGroup>
                  ))}
                </SelectContent>
              </Select>
            )}
          />
        </Field>
        <Field label="Role interest" htmlFor="role" error={errors.role?.message}>
          <Controller
            control={control}
            name="role"
            render={({ field }) => (
              <Select
                value={field.value || undefined}
                onValueChange={(v) => {
                  field.onChange(v);
                  onRoleChange?.(v as RoleId);
                }}
              >
                <SelectTrigger id="role" aria-invalid={!!errors.role}>
                  <SelectValue placeholder="Select a role" />
                </SelectTrigger>
                <SelectContent>
                  {ROLES.map((role) => (
                    <SelectItem key={role.id} value={role.id}>
                      {role.title}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            )}
          />
        </Field>
      </div>

      <div className="flex flex-col gap-3 pt-1 sm:flex-row sm:items-center sm:justify-between">
        <p className="text-xs leading-relaxed text-[var(--color-fg-subtle)]">
          By submitting, you confirm the information is accurate and you can work event weekends.
        </p>
        <Button type="submit" size="lg" disabled={isSubmitting} className="w-full sm:w-auto">
          {isSubmitting ? (
            <>
              <Loader2 className="size-4 animate-spin" />
              Submitting…
            </>
          ) : (
            <>
              <Send className="size-4" />
              Submit application
            </>
          )}
        </Button>
      </div>
    </form>
  );
}

function Field({
  label,
  htmlFor,
  error,
  children,
}: {
  label: string;
  htmlFor: string;
  error?: string;
  children: ReactNode;
}) {
  return (
    <div className="space-y-1.5">
      <Label htmlFor={htmlFor}>{label}</Label>
      {children}
      <p
        className={cn(
          "min-h-3.5 text-xs leading-tight text-[var(--color-primary)] transition-opacity",
          error ? "opacity-100" : "opacity-0",
        )}
        role={error ? "alert" : undefined}
      >
        {error || "\u00a0"}
      </p>
    </div>
  );
}
