import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { createFileRoute, Link } from "@tanstack/react-router";
import { useServerFn } from "@tanstack/react-start";
import { Award, CalendarDays, Clock, Lock } from "lucide-react";
import { toast } from "sonner";

import { AppShell } from "@/components/app-shell";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Progress } from "@/components/ui/progress";
import { Skeleton } from "@/components/ui/skeleton";
import { issueCertificate } from "@/lib/certificates.functions";
import { enrollInCourse, getMyCourse, setLessonComplete } from "@/lib/learning.functions";

type Lesson = { title: string; body?: string; summary?: string };

export const Route = createFileRoute("/_authenticated/learn/$slug")({
  head: () => ({
    meta: [
      { title: "Course | UZIA Academy" },
      { name: "description", content: "Work through your weekly modules and track progress." },
      { name: "robots", content: "noindex" },
    ],
  }),
  component: LearnCourse,
});

function LearnCourse() {
  const { slug } = Route.useParams();
  const queryClient = useQueryClient();
  const fetchCourse = useServerFn(getMyCourse);
  const enroll = useServerFn(enrollInCourse);
  const setComplete = useServerFn(setLessonComplete);
  const claim = useServerFn(issueCertificate);

  const { data, isLoading } = useQuery({
    queryKey: ["my-course", slug],
    queryFn: () => fetchCourse({ data: { slug } }),
  });

  const invalidate = () => queryClient.invalidateQueries({ queryKey: ["my-course", slug] });

  const enrollMutation = useMutation({
    mutationFn: (courseId: string) => enroll({ data: { courseId } }),
    onSuccess: async () => {
      await invalidate();
      toast.success("You're enrolled. Start with week one.");
    },
    onError: (e) => toast.error(e instanceof Error ? e.message : "Could not enrol"),
  });

  const progressMutation = useMutation({
    mutationFn: (vars: { courseId: string; lessonIndex: number; complete: boolean }) =>
      setComplete({ data: vars }),
    onSuccess: invalidate,
    onError: (e) => toast.error(e instanceof Error ? e.message : "Could not save progress"),
  });

  const claimMutation = useMutation({
    mutationFn: (courseId: string) => claim({ data: { courseId } }),
    onSuccess: async (res) => {
      await queryClient.invalidateQueries({ queryKey: ["my-certificates"] });
      toast.success(
        res.created
          ? `Certificate issued: ${res.certificate.certificate_number}`
          : `Already issued: ${res.certificate.certificate_number}`,
      );
    },
    onError: (e) => toast.error(e instanceof Error ? e.message : "Could not issue certificate"),
  });

  if (isLoading) {
    return (
      <AppShell title="Course">
        <Skeleton className="h-64 w-full" />
      </AppShell>
    );
  }

  if (!data?.course) {
    return (
      <AppShell title="Course not found">
        <Button asChild className="rounded-full">
          <Link to="/courses">Back to catalogue</Link>
        </Button>
      </AppShell>
    );
  }

  if (data.locked) {
    return (
      <AppShell
        title={data.course.title}
        description="This programme is part of the Pro catalogue."
      >
        <div className="mx-auto max-w-2xl rounded-3xl border border-border bg-surface p-8 text-center">
          <Lock className="mx-auto size-7 text-primary" />
          <p className="mt-4 text-sm text-muted-foreground">
            Foundation programmes are fully sponsored for every learner. Upgrade to Pro to unlock
            {" "}
            {data.course.credential_level}-level modules, your action plan and the rest of the
            catalogue.
          </p>
          <Button asChild className="mt-6 rounded-full">
            <Link to="/pricing">See plans</Link>
          </Button>
        </div>
      </AppShell>
    );
  }

  const course = data.course;
  const lessons: Lesson[] = Array.isArray(course.lessons) ? (course.lessons as Lesson[]) : [];
  const done = data.completedLessons;
  const pct = lessons.length ? Math.round((done.length / lessons.length) * 100) : 0;
  const finished = lessons.length > 0 && done.length >= lessons.length;

  return (
    <AppShell title={course.title} description={course.summary}>
      <div className="mx-auto max-w-3xl">
        <div className="flex flex-wrap items-center gap-2">
          <Badge variant="secondary">
            {course.group_code} · {course.group_name}
          </Badge>
          <Badge className="bg-gold text-gold-foreground">{course.credential_level}</Badge>
          <Badge variant="outline">{course.domain_code}</Badge>
        </div>

        <div className="mt-4 flex flex-wrap gap-5 text-sm text-muted-foreground">
          <span className="flex items-center gap-1.5">
            <CalendarDays className="size-4" /> {course.duration_weeks} weeks
          </span>
          <span className="flex items-center gap-1.5">
            <Clock className="size-4" /> {course.learning_hours} learning hours
          </span>
        </div>

        {data.enrolled ? (
          <div className="mt-6 rounded-2xl border border-border bg-surface p-5">
            <div className="flex items-center justify-between text-sm">
              <span className="font-medium">Your progress</span>
              <span className="text-muted-foreground">
                {done.length}/{lessons.length} modules · {pct}%
              </span>
            </div>
            <Progress value={pct} className="mt-3" />
          </div>
        ) : (
          <div className="mt-6 rounded-2xl bg-sunset p-6 text-center text-primary-foreground shadow-warm">
            <p className="text-sm opacity-90">
              Enrol to unlock module tracking and your UZIA certificate.
            </p>
            <Button
              className="mt-4 rounded-full bg-gold text-gold-foreground hover:bg-gold/90"
              disabled={enrollMutation.isPending}
              onClick={() => enrollMutation.mutate(course.id)}
            >
              {enrollMutation.isPending ? "Enrolling…" : "Enrol in this programme"}
            </Button>
          </div>
        )}

        {finished ? (
          <div className="mt-6 rounded-2xl border border-border bg-card p-6 text-center">
            <Award className="mx-auto size-7 text-primary" />
            <p className="mt-3 font-display text-lg font-bold">All modules complete</p>
            <p className="mt-1 text-sm text-muted-foreground">
              Claim your {course.certificate_type} with a publicly verifiable number.
            </p>
            <Button
              className="mt-4 rounded-full"
              disabled={claimMutation.isPending}
              onClick={() => claimMutation.mutate(course.id)}
            >
              {claimMutation.isPending ? "Issuing…" : "Claim my certificate"}
            </Button>
          </div>
        ) : null}

        <ol className="mt-8 space-y-3">
          {lessons.map((lesson, i) => {
            const complete = done.includes(i);
            return (
              <li
                key={lesson.title}
                className="flex items-start gap-4 rounded-2xl border border-border bg-card p-5"
              >
                <Checkbox
                  className="mt-0.5"
                  checked={complete}
                  disabled={!data.enrolled || progressMutation.isPending}
                  aria-label={`Mark ${lesson.title} complete`}
                  onCheckedChange={(v) =>
                    progressMutation.mutate({
                      courseId: course.id,
                      lessonIndex: i,
                      complete: Boolean(v),
                    })
                  }
                />
                <div>
                  <p className="text-sm font-semibold">
                    Week {i + 1}: {lesson.title}
                  </p>
                  {lesson.body ?? lesson.summary ? (
                    <p className="mt-1 text-sm text-muted-foreground">
                      {lesson.body ?? lesson.summary}
                    </p>
                  ) : null}
                </div>
              </li>
            );
          })}
        </ol>
      </div>
    </AppShell>
  );
}
