import { useMemo, useState, type ComponentType } from "react";
import { Navigate, useNavigate } from "react-router-dom";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
import {
  BookOpen,
  GraduationCap,
  Headphones,
  Layers,
  Loader2,
  Mic,
  PenLine,
  Sparkles,
  Users,
} from "lucide-react";
import { format } from "date-fns";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Progress } from "@/components/ui/progress";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { Slider } from "@/components/ui/slider";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Calendar } from "@/components/ui/calendar";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { cn } from "@/lib/utils";
import { useAuth } from "@/contexts/AuthContext";
import { useCompleteOnboarding, useGoals } from "@/hooks/queries/useSignup";
import { ApiError } from "@/lib/api-client";
import type { CEFRLevel, OnboardingData, StudyMode } from "@/types";
import type { UserRole } from "@/types/auth";

const steps = ["Goal", "Target", "Study", "Placement"] as const;

const cefrOptions: { value: CEFRLevel; label: string }[] = [
  { value: "pre_a1", label: "Pre-A1" },
  { value: "a1", label: "A1" },
  { value: "a2", label: "A2" },
  { value: "b1", label: "B1" },
  { value: "b2", label: "B2" },
  { value: "c1", label: "C1" },
  { value: "c2", label: "C2" },
];

const formSchema = z.object({
  goal: z.string().min(1, "Choose a goal"),
  targetBand: z.number().min(4).max(9),
  targetLevel: z.string().min(1, "Select a CEFR level"),
  examDate: z.date().optional(),
  noExamDate: z.boolean(),
  hoursPerWeek: z.number().min(1).max(40),
  studyMode: z.enum(["self_study", "with_teacher"]),
  learningVisual: z.boolean(),
  learningAudio: z.boolean(),
  learningReading: z.boolean(),
  learningMixed: z.boolean(),
  placementDecision: z.enum(["take_now", "skip"]),
});

type FormValues = z.infer<typeof formSchema>;

const iconMap: Record<string, ComponentType<{ className?: string }>> = {
  BookOpen,
  Sparkles,
  GraduationCap,
  Layers,
  Mic,
  Headphones,
  PenLine,
  Users,
};

function GoalIcon({ name }: { name: string }) {
  const Icon = iconMap[name] || BookOpen;
  return <Icon className="h-6 w-6" />;
}

function dashboardForRole(role: UserRole): string {
  switch (role) {
    case "student":
      return "/student/dashboard";
    case "teacher":
      return "/teacher/dashboard";
    case "admin":
    case "developer":
      return "/admin/dashboard";
    case "corporate":
    case "mastercorporate":
    case "agent":
      return "/admin/platform";
    default:
      return "/student/dashboard";
  }
}

function toOnboardingPayload(values: FormValues): OnboardingData {
  const learning_style: OnboardingData["learning_style"] = [];
  if (values.learningVisual) learning_style.push("visual");
  if (values.learningAudio) learning_style.push("audio");
  if (values.learningReading) learning_style.push("reading");
  if (values.learningMixed) learning_style.push("mixed");
  return {
    goal: values.goal,
    target_band: values.targetBand,
    target_level: values.targetLevel,
    exam_date: values.noExamDate ? undefined : values.examDate ? format(values.examDate, "yyyy-MM-dd") : undefined,
    hours_per_week: values.hoursPerWeek,
    study_mode: values.studyMode as StudyMode,
    learning_style,
    placement_decision: values.placementDecision,
  };
}

export default function OnboardingWizard() {
  const { user, isLoading: authLoading } = useAuth();
  const navigate = useNavigate();
  const { data: goalsData, isLoading: goalsLoading, error: goalsError } = useGoals();
  const complete = useCompleteOnboarding();
  const [step, setStep] = useState(0);

  const form = useForm<FormValues>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      goal: "",
      targetBand: 6.5,
      targetLevel: "b2",
      examDate: undefined,
      noExamDate: false,
      hoursPerWeek: 8,
      studyMode: "self_study",
      learningVisual: true,
      learningAudio: false,
      learningReading: false,
      learningMixed: true,
      placementDecision: "take_now",
    },
    mode: "onChange",
  });

  const progress = useMemo(() => ((step + 1) / steps.length) * 100, [step]);

  const next = async () => {
    const fields: (keyof FormValues)[][] = [
      ["goal"],
      ["targetBand", "targetLevel", "examDate", "noExamDate"],
      ["hoursPerWeek", "studyMode", "learningVisual", "learningAudio", "learningReading", "learningMixed"],
      ["placementDecision"],
    ];
    if (step === 1) {
      const noExam = form.getValues("noExamDate");
      const exam = form.getValues("examDate");
      if (!noExam && !exam) {
        form.setError("examDate", { message: "Pick a date or check no exam date" });
        return;
      }
      if (noExam) form.clearErrors("examDate");
    }
    if (step === 2) {
      const v = form.getValues();
      const styles = [v.learningVisual, v.learningAudio, v.learningReading, v.learningMixed].filter(Boolean);
      if (styles.length === 0) {
        form.setError("learningVisual", { message: "Select at least one learning style" });
        return;
      }
    }
    const ok =
      step === steps.length - 1
        ? await form.trigger(undefined, { shouldFocus: true })
        : await form.trigger(fields[step] as (keyof FormValues)[], { shouldFocus: true });
    if (!ok) return;
    if (step < steps.length - 1) setStep((s) => s + 1);
    else {
      const values = form.getValues();
      try {
        await complete.mutateAsync(toOnboardingPayload(values));
        if (values.placementDecision === "take_now" && user.user_type === "student") {
          navigate("/student/placement");
        } else {
          navigate(dashboardForRole(user.user_type));
        }
      } catch (e) {
        form.setError("root", {
          message: e instanceof ApiError ? e.message : "Could not save onboarding",
        });
      }
    }
  };

  const back = () => {
    if (step > 0) setStep((s) => s - 1);
  };

  if (authLoading) {
    return (
      <div className="min-h-screen flex items-center justify-center">
        <Loader2 className="h-8 w-8 animate-spin text-primary" />
      </div>
    );
  }

  if (!user) {
    return <Navigate to="/login" replace />;
  }

  if (!user.is_verified) {
    return <Navigate to={`/verify-email?email=${encodeURIComponent(user.email)}`} replace />;
  }

  return (
    <div className="min-h-screen bg-gradient-to-b from-muted/30 to-background py-10 px-4">
      <div className="max-w-2xl mx-auto space-y-8">
        <div className="text-center space-y-2">
          <h1 className="text-2xl font-bold tracking-tight">Welcome to EnCoach</h1>
          <p className="text-muted-foreground text-sm">Tailor your learning path in a few steps.</p>
        </div>

        <div className="space-y-2">
          <div className="flex justify-between text-xs font-medium text-muted-foreground uppercase tracking-wide">
            <span>
              Step {step + 1} of {steps.length}
            </span>
            <span>{steps[step]}</span>
          </div>
          <Progress value={progress} className="h-2" />
        </div>

        <Card className="border-0 shadow-lg">
          <CardHeader>
            <CardTitle>{steps[step]}</CardTitle>
            <CardDescription>
              {step === 0 && "What is your primary learning goal?"}
              {step === 1 && "Set your target band, level, and exam timeline."}
              {step === 2 && "How do you prefer to study?"}
              {step === 3 && "Start with a placement test or jump in later."}
            </CardDescription>
          </CardHeader>
          <CardContent>
            <Form {...form}>
              <form className="space-y-6" onSubmit={(e) => e.preventDefault()}>
                {goalsError && (
                  <Alert variant="destructive">
                    <AlertTitle>Could not load goals</AlertTitle>
                    <AlertDescription>Refresh the page or try again shortly.</AlertDescription>
                  </Alert>
                )}

                {step === 0 && (
                  <FormField
                    control={form.control}
                    name="goal"
                    render={({ field }) => (
                      <FormItem>
                        <FormControl>
                          {goalsLoading ? (
                            <div className="grid gap-3 sm:grid-cols-2">
                              {[1, 2, 3, 4].map((i) => (
                                <div key={i} className="h-24 rounded-xl bg-muted animate-pulse" />
                              ))}
                            </div>
                          ) : (
                            <RadioGroup
                              onValueChange={field.onChange}
                              value={field.value}
                              className="grid gap-3 sm:grid-cols-2"
                            >
                              {goalsData?.goals.map((g) => (
                                <label
                                  key={g.id}
                                  className={cn(
                                    "flex cursor-pointer items-start gap-3 rounded-xl border p-4 transition-colors hover:bg-muted/50",
                                    field.value === g.id && "border-primary ring-2 ring-primary/20 bg-primary/5",
                                  )}
                                >
                                  <RadioGroupItem value={g.id} className="mt-1" />
                                  <div className="flex gap-3 flex-1">
                                    <div className="rounded-lg bg-primary/10 p-2 text-primary">
                                      <GoalIcon name={g.icon} />
                                    </div>
                                    <div>
                                      <div className="font-medium leading-tight">{g.title}</div>
                                      <p className="text-sm text-muted-foreground mt-1">{g.description}</p>
                                    </div>
                                  </div>
                                </label>
                              ))}
                            </RadioGroup>
                          )}
                        </FormControl>
                        <FormMessage />
                      </FormItem>
                    )}
                  />
                )}

                {step === 1 && (
                  <div className="space-y-8">
                    <FormField
                      control={form.control}
                      name="targetBand"
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel>Target band (IELTS)</FormLabel>
                          <div className="pt-4 pb-2">
                            <Slider
                              min={4}
                              max={9}
                              step={0.5}
                              value={[field.value]}
                              onValueChange={(v) => field.onChange(v[0])}
                            />
                          </div>
                          <p className="text-sm text-muted-foreground text-center font-medium tabular-nums">
                            {field.value.toFixed(1)}
                          </p>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    <FormField
                      control={form.control}
                      name="targetLevel"
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel>Target CEFR level</FormLabel>
                          <Select onValueChange={field.onChange} value={field.value}>
                            <FormControl>
                              <SelectTrigger>
                                <SelectValue placeholder="Select level" />
                              </SelectTrigger>
                            </FormControl>
                            <SelectContent>
                              {cefrOptions.map((o) => (
                                <SelectItem key={o.value} value={o.value}>
                                  {o.label}
                                </SelectItem>
                              ))}
                            </SelectContent>
                          </Select>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    <FormField
                      control={form.control}
                      name="noExamDate"
                      render={({ field }) => (
                        <FormItem className="flex flex-row items-center gap-2 space-y-0">
                          <FormControl>
                            <Checkbox checked={field.value} onCheckedChange={(v) => field.onChange(!!v)} />
                          </FormControl>
                          <FormLabel className="font-normal">I don&apos;t have an exam date yet</FormLabel>
                        </FormItem>
                      )}
                    />
                    {!form.watch("noExamDate") && (
                      <FormField
                        control={form.control}
                        name="examDate"
                        render={({ field }) => (
                          <FormItem className="flex flex-col">
                            <FormLabel>Exam date</FormLabel>
                            <Popover>
                              <PopoverTrigger asChild>
                                <FormControl>
                                  <Button variant="outline" className="w-full justify-start text-left font-normal">
                                    {field.value ? format(field.value, "PPP") : "Pick a date"}
                                  </Button>
                                </FormControl>
                              </PopoverTrigger>
                              <PopoverContent className="w-auto p-0" align="start">
                                <Calendar
                                  mode="single"
                                  selected={field.value}
                                  onSelect={field.onChange}
                                  disabled={(d) => d < new Date()}
                                  initialFocus
                                />
                              </PopoverContent>
                            </Popover>
                            <FormMessage />
                          </FormItem>
                        )}
                      />
                    )}
                  </div>
                )}

                {step === 2 && (
                  <div className="space-y-8">
                    <FormField
                      control={form.control}
                      name="hoursPerWeek"
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel>Hours per week</FormLabel>
                          <div className="pt-4 pb-2">
                            <Slider
                              min={1}
                              max={40}
                              step={1}
                              value={[field.value]}
                              onValueChange={(v) => field.onChange(v[0])}
                            />
                          </div>
                          <p className="text-sm text-muted-foreground text-center font-medium">{field.value} h</p>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    <FormField
                      control={form.control}
                      name="studyMode"
                      render={({ field }) => (
                        <FormItem>
                          <FormLabel>Study mode</FormLabel>
                          <FormControl>
                            <RadioGroup
                              onValueChange={field.onChange}
                              value={field.value}
                              className="grid gap-3 sm:grid-cols-2"
                            >
                              <label
                                className={cn(
                                  "flex cursor-pointer items-center gap-3 rounded-xl border p-4",
                                  field.value === "self_study" && "border-primary ring-2 ring-primary/20",
                                )}
                              >
                                <RadioGroupItem value="self_study" />
                                <span>Self-study</span>
                              </label>
                              <label
                                className={cn(
                                  "flex cursor-pointer items-center gap-3 rounded-xl border p-4",
                                  field.value === "with_teacher" && "border-primary ring-2 ring-primary/20",
                                )}
                              >
                                <RadioGroupItem value="with_teacher" />
                                <span>With a teacher</span>
                              </label>
                            </RadioGroup>
                          </FormControl>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    <div className="space-y-3">
                      <FormLabel>Learning style</FormLabel>
                      <div className="grid sm:grid-cols-2 gap-3">
                        {(
                          [
                            ["learningVisual", "Visual"],
                            ["learningAudio", "Audio"],
                            ["learningReading", "Reading"],
                            ["learningMixed", "Mixed"],
                          ] as const
                        ).map(([name, label]) => (
                          <FormField
                            key={name}
                            control={form.control}
                            name={name}
                            render={({ field }) => (
                              <FormItem className="flex flex-row items-center gap-2 space-y-0 rounded-lg border p-3">
                                <FormControl>
                                  <Checkbox checked={field.value} onCheckedChange={field.onChange} />
                                </FormControl>
                                <FormLabel className="font-normal cursor-pointer">{label}</FormLabel>
                              </FormItem>
                            )}
                          />
                        ))}
                      </div>
                      <FormField
                        control={form.control}
                        name="learningVisual"
                        render={() => <FormMessage />}
                      />
                    </div>
                  </div>
                )}

                {step === 3 && (
                  <div className="space-y-6">
                    <FormField
                      control={form.control}
                      name="placementDecision"
                      render={({ field }) => (
                        <FormItem>
                          <FormControl>
                            <RadioGroup
                              onValueChange={field.onChange}
                              value={field.value}
                              className="grid gap-4"
                            >
                              <label
                                className={cn(
                                  "flex cursor-pointer flex-col gap-2 rounded-xl border p-5 transition-colors",
                                  field.value === "take_now" && "border-primary bg-primary/5 ring-2 ring-primary/20",
                                )}
                              >
                                <div className="flex items-center gap-3">
                                  <RadioGroupItem value="take_now" />
                                  <span className="font-semibold">Take Placement Test Now</span>
                                </div>
                                <p className="text-sm text-muted-foreground pl-7">
                                  Get a precise starting level across grammar, vocabulary, reading, and speaking.
                                </p>
                              </label>
                              <label
                                className={cn(
                                  "flex cursor-pointer flex-col gap-2 rounded-xl border p-5 transition-colors",
                                  field.value === "skip" && "border-primary bg-primary/5 ring-2 ring-primary/20",
                                )}
                              >
                                <div className="flex items-center gap-3">
                                  <RadioGroupItem value="skip" />
                                  <span className="font-semibold">Skip for Now</span>
                                </div>
                                <p className="text-sm text-muted-foreground pl-7">
                                  You can take the placement test later from your dashboard. Your path may be less
                                  personalized until you do.
                                </p>
                              </label>
                            </RadioGroup>
                          </FormControl>
                          <FormMessage />
                        </FormItem>
                      )}
                    />
                    {form.watch("placementDecision") === "skip" && (
                      <Alert>
                        <AlertTitle>Heads up</AlertTitle>
                        <AlertDescription>
                          Skipping the placement test means we estimate your level from your profile only. You can
                          always start the test when you are ready.
                        </AlertDescription>
                      </Alert>
                    )}
                  </div>
                )}

                {form.formState.errors.root && (
                  <p className="text-sm text-destructive text-center">{form.formState.errors.root.message}</p>
                )}

                <div className="flex justify-between gap-3 pt-2">
                  <Button type="button" variant="outline" onClick={back} disabled={step === 0 || complete.isPending}>
                    Back
                  </Button>
                  <Button type="button" onClick={() => void next()} disabled={complete.isPending}>
                    {complete.isPending ? (
                      <>
                        <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                        Saving
                      </>
                    ) : step === steps.length - 1 ? (
                      "Finish"
                    ) : (
                      "Next"
                    )}
                  </Button>
                </div>
              </form>
            </Form>
          </CardContent>
        </Card>
      </div>
    </div>
  );
}
