"use client";
import { formatDuration } from "@/lib/aula/duration";
import TaskDialog from "./TaskDialog";
import ResourceLink from "@/components/ui/ResourceLink";

import { useSystemNotifications } from "@/components/ui/SystemNotifications";
import Link from "next/link";
import { useRouter } from "next/navigation";
import AulaVideoPlayer from "@/components/alumno/AulaVideoPlayer";
import type { PublicProgress } from "@/lib/alumno/rules";
import { entrarModulo } from "@/app/actions/aprendizaje";
import { useState, useTransition } from "react";
import { Button, Card } from "@heroui/react";
import {
  ArrowLeft,
  ArrowRight,
  BookOpen,
  ChevronDown,
  ClipboardList,
  ExternalLink,
  FileCheck2,
  FolderOpen,
  ListOrdered,
  Play,
  LockKeyhole,
  CheckCircle2,
} from "lucide-react";
import type { ContenidoAlumno } from "@/lib/data/contenido-alumno";
import { formatDisplayName } from "@/lib/format-display";

type PublicContent = Extract<NonNullable<ContenidoAlumno>, { estado: "disponible" }>;
type Props = {
  enrollmentId: number;
  aulaId: number;
  initialProgress: PublicProgress;
  initialId?: string;
  initialNextEntry?: boolean;
  content: Pick<
    PublicContent,
    "cronologia" | "materiales" | "evaluaciones" | "foroActivo" | "modulos" | "siguienteModulo"
  >;
};
const labels = { video: "Videoclase", tarea: "Tarea", evaluacion: "Evaluación", examen: "Examen" };
function date(value: string | null) {
  return value
    ? new Intl.DateTimeFormat("es-MX", {
        timeZone: "America/Mexico_City",
        day: "numeric",
        month: "short",
        year: "numeric",
        hour: "2-digit",
        minute: "2-digit",
      }).format(new Date(value))
    : "Sin fecha registrada";
}

export default function DashboardAlumnoRecorrido({
  content,
  initialId,
  initialNextEntry = false,
  aulaId,
  enrollmentId,
  initialProgress,
}: Props) {
  const router = useRouter();
  const [progress, setProgress] = useState(initialProgress);
  const { notify } = useSystemNotifications();
  const requestedId = initialId ?? initialProgress.ultimaClaseId;
  const requested = requestedId && initialProgress.bloqueos[requestedId];
  const fallback = content.evaluaciones.find((e) => e.id === requested);
  const [selectedId, setSelectedId] = useState<string | null>(
    requested ? fallback?.claseId || requested : (requestedId ?? null),
  );
  const [entryError, setEntryError] = useState("");
  const [entering, startEntering] = useTransition();
  const examHref = (id: string) => "/aula/" + aulaId + "/evaluacion/" + encodeURIComponent(id);
  function openEvaluation(id: string) {
    router.push(examHref(id));
  }
  const selectedModule = content.modulos[0];
  const sessions = content.cronologia.filter((s) => s.contenido.moduloId === selectedModule?.id);
  const foundIndex = sessions.findIndex((s) => s.contenido.id === selectedId);
  const selectedIndex = foundIndex >= 0 ? foundIndex : sessions.length ? 0 : -1;
  const selected = sessions[selectedIndex];
  const classId = selected?.tipo === "video" ? selected.contenido.id : selected?.contenido.claseId;
  const resources = content.materiales.filter(
    (m) => m.moduloId === selectedModule?.id && (!m.claseId || m.claseId === classId),
  );
  function select(index: number) {
    const item = sessions[index];
    if (!item) return;
    const gateId = progress.bloqueos[item.contenido.id];
    if (gateId) {
      const gate = content.evaluaciones.find((e) => e.id === gateId);
      notify({
        id: "evaluacion-pendiente",
        status: "warning",
        title: "Evaluación pendiente",
        children:
          "Aprueba primero «" + (gate?.titulo || "la evaluación pendiente") + "» para continuar.",
      });
      return;
    }
    setSelectedId(item.contenido.id);
  }
  function assessmentReady(e: PublicContent["evaluaciones"][number]) {
    if (progress.bloqueos[e.id]) return false;
    if (
      progress.aprobadas.includes(e.id) ||
      !e.claseId ||
      e.momento === "modular" ||
      e.momento === "inicio_video"
    )
      return true;
    const lesson = progress.lecciones[e.claseId];
    return e.momento === "final_video"
      ? !!lesson?.completado
      : !!lesson && lesson.duracion > 0 && lesson.segundos >= lesson.duracion / 2 - 0.5;
  }
  const moments = { inicio_video: 0, mitad_video: 1, final_video: 2, modular: 3 };
  const linkedPending =
    selected?.tipo === "video"
      ? content.evaluaciones
          .filter(
            (e) =>
              e.claseId === selected.contenido.id &&
              e.momento !== "modular" &&
              !progress.aprobadas.includes(e.id),
          )
          .sort((a, b) => moments[a.momento] - moments[b.momento])[0]
      : undefined;
  const nextIndex = sessions.findIndex(
    (item, index) =>
      index > selectedIndex &&
      !(
        (item.tipo === "evaluacion" || item.tipo === "examen") &&
        progress.aprobadas.includes(item.contenido.id)
      ),
  );
  const nextItem = sessions[nextIndex];
  const nextEvaluation =
    linkedPending ??
    (selected &&
    (selected.tipo === "evaluacion" || selected.tipo === "examen") &&
    !progress.aprobadas.includes(selected.contenido.id)
      ? selected.contenido
      : nextItem && (nextItem.tipo === "evaluacion" || nextItem.tipo === "examen")
        ? nextItem.contenido
        : undefined);
  const nextBlocked = !!nextItem && !!progress.bloqueos[nextItem.contenido.id];
  const navigation = (
    <div className="flex flex-wrap items-center justify-between gap-3">
      <Button
        className="rounded-full"
        variant="secondary"
        isDisabled={selectedIndex <= 0}
        onPress={() => select(selectedIndex - 1)}
      >
        <ArrowLeft className="size-4" />
        Anterior
      </Button>
      <span className="text-xs text-zinc-400">
        {selectedIndex + 1} / {sessions.length}
      </span>
      <Button
        className="rounded-full"
        variant="secondary"
        isDisabled={nextEvaluation ? !assessmentReady(nextEvaluation) : !nextItem}
        onPress={() => (nextEvaluation ? openEvaluation(nextEvaluation.id) : select(nextIndex))}
      >
        {nextEvaluation ? (
          <FileCheck2 className="size-4" />
        ) : nextBlocked ? (
          <LockKeyhole className="size-4" />
        ) : null}
        {nextEvaluation ? "Avanzar a la evaluación" : "Siguiente clase"}
        <ArrowRight className="size-4" />
      </Button>
    </div>
  );

  const introduction = !progress.modulos.actualId
    ? selectedModule
    : initialNextEntry && progress.modulos.completado
      ? content.siguienteModulo
      : null;
  if (introduction)
    return (
      <section className="mx-auto max-w-2xl rounded-2xl border border-zinc-200 bg-white p-6 sm:p-8">
        <BookOpen className="mb-4 size-8 text-[#9d2449]" />
        <p className="text-sm text-zinc-500">
          {progress.modulos.actualId ? "Siguiente módulo" : "Comienza tu módulo"}
        </p>
        <h2 className="mt-2 text-2xl font-semibold">{introduction.titulo}</h2>
        {introduction.descripcion && (
          <p className="mt-4 whitespace-pre-wrap text-sm text-zinc-600">
            {introduction.descripcion}
          </p>
        )}
        <p className="mt-5 text-sm text-zinc-500">
          Cada módulo tiene su propia cronología. Al avanzar al siguiente, el módulo anterior dejará
          de estar disponible.
        </p>
        {entryError && (
          <p role="alert" className="mt-4 text-sm text-red-700">
            {entryError}
          </p>
        )}
        <Button
          isDisabled={entering}
          className="mt-6 rounded-full bg-[#9d2449] text-white"
          onPress={() =>
            startEntering(async () => {
              setEntryError("");
              try {
                const result = await entrarModulo(aulaId, introduction.id);
                if (!result.ok) {
                  setEntryError(result.error);
                  return;
                }
                router.replace(`/aula/${aulaId}`);
                router.refresh();
              } catch {
                setEntryError("No se pudo entrar al módulo. Vuelve a intentarlo.");
              }
            })
          }
        >
          {entering ? "Entrando…" : "Entrar al módulo"}
          <ArrowRight className="size-4" />
        </Button>
      </section>
    );

  return (
    <section
      aria-label="Recorrido del aula"
      className="grid min-w-0 items-start gap-4 lg:grid-cols-12"
    >
      <div className="min-w-0 space-y-4 lg:col-span-8">
        {progress.modulos.completado && (
          <div className="flex flex-col gap-5 rounded-2xl border border-zinc-200/70 bg-white p-5 sm:flex-row sm:items-center sm:justify-between sm:p-6">
            <div className="flex min-w-0 items-start gap-3">
              <span className="flex size-11 shrink-0 items-center justify-center rounded-xl bg-[#9d2449]/8 text-[#9d2449]">
                <CheckCircle2 className="size-5" aria-hidden="true" />
              </span>
              <div className="min-w-0">
                <p className="text-base font-semibold text-zinc-900">Módulo completado</p>
                <p className="mt-1 text-sm leading-relaxed text-zinc-500">
                  {progress.modulos.siguienteId
                    ? "Terminaste las actividades. Continúa con el siguiente módulo."
                    : "Completaste todos los módulos del curso."}
                </p>
              </div>
            </div>
            {progress.modulos.siguienteId ? (
              <Button
                className="min-h-11 shrink-0 gap-2 rounded-full bg-[#9d2449] px-5 py-2.5 text-sm font-medium text-white transition-colors hover:bg-[#801c3a] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#9d2449] motion-reduce:transition-none"
                onPress={() => router.replace(`/aula/${aulaId}?entrada=siguiente`)}
              >
                Continuar al siguiente módulo
                <ArrowRight className="size-4" aria-hidden="true" />
              </Button>
            ) : (
              <span className="self-start rounded-full bg-[#9d2449]/8 px-3 py-1.5 text-xs font-medium text-[#9d2449] sm:self-center">
                Curso completado
              </span>
            )}
          </div>
        )}
        {sessions.length > 0 && (
          <div className="rounded-2xl border border-zinc-200/70 bg-white p-3 sm:p-4">
            {navigation}
          </div>
        )}
        <Card className="min-w-0 gap-0 overflow-hidden border border-zinc-200/70 p-0 shadow-none">
          {selected ? (
            <>
              <Card.Header className="gap-2 p-5 sm:p-6">
                <p className="text-xs font-medium text-[#9d2449]">
                  {labels[selected.tipo]} · Paso {selectedIndex + 1} de {sessions.length}
                </p>
                <Card.Title className="break-words text-xl font-semibold">
                  {formatDisplayName(selected.contenido.titulo)}
                </Card.Title>
              </Card.Header>
              <Card.Content className="min-w-0 px-5 pb-5 sm:px-6 sm:pb-6">
                {selected.tipo === "video" && (
                  <div className="space-y-4">
                    {selected.contenido.url ? (
                      <AulaVideoPlayer
                        key={selected.contenido.id}
                        enrollmentId={enrollmentId}
                        aulaId={aulaId}
                        id={selected.contenido.id}
                        src={selected.contenido.url}
                        titulo={selected.contenido.titulo}
                        initial={progress.lecciones[selected.contenido.id]?.segundos ?? 0}
                        initialDuration={progress.lecciones[selected.contenido.id]?.duracion ?? 0}
                        completed={progress.lecciones[selected.contenido.id]?.completado ?? false}
                        gates={content.evaluaciones
                          .filter(
                            (e) =>
                              e.claseId === selected.contenido.id &&
                              !progress.aprobadas.includes(e.id),
                          )
                          .map((e) => ({ id: e.id, momento: e.momento }))}
                        onGate={openEvaluation}
                        onProgress={setProgress}
                      />
                    ) : (
                      <p className="rounded-xl bg-zinc-50 p-5 text-sm text-zinc-500">
                        El video todavía no está disponible.
                      </p>
                    )}
                    {content.evaluaciones
                      .filter((e) => e.claseId === selected.contenido.id && e.momento !== "modular")
                      .map((e) => (
                        <div
                          key={e.id}
                          className="flex flex-wrap items-center justify-between gap-3 rounded-xl border border-zinc-200 p-3"
                        >
                          <p className="text-xs text-zinc-500">
                            {e.momento === "inicio_video"
                              ? "Antes de comenzar"
                              : e.momento === "mitad_video"
                                ? "A mitad del video"
                                : "Al finalizar el video"}{" "}
                            · {e.titulo}
                          </p>
                          {progress.aprobadas.includes(e.id) ? (
                            <span className="inline-flex items-center gap-1 text-xs text-emerald-700">
                              <CheckCircle2 className="size-3.5" />
                              Aprobada
                            </span>
                          ) : (
                            <Button
                              variant="secondary"
                              isDisabled={!assessmentReady(e)}
                              onPress={() => openEvaluation(e.id)}
                              className="h-8 text-xs rounded-full"
                            >
                              Ir a evaluación
                            </Button>
                          )}
                        </div>
                      ))}

                    <p className="text-xs text-zinc-500">
                      {formatDuration(Math.round(selected.contenido.minutos * 60))}
                    </p>
                    {selected.contenido.descripcion && (
                      <p className="whitespace-pre-wrap break-words text-sm leading-relaxed text-zinc-600">
                        {selected.contenido.descripcion}
                      </p>
                    )}
                    {!!selected.contenido.objetivos.length && (
                      <div>
                        <h3 className="mb-2 text-sm font-semibold">Objetivos de la clase</h3>
                        <ul className="list-disc space-y-1 pl-5 text-sm text-zinc-600">
                          {selected.contenido.objetivos.filter(Boolean).map((objective, i) => (
                            <li key={i}>{objective}</li>
                          ))}
                        </ul>
                      </div>
                    )}
                  </div>
                )}
                {selected.tipo === "tarea" && (
                  <div className="space-y-4">
                    <TaskDialog
                      aulaId={aulaId}
                      taskId={selected.contenido.id}
                      label="Ver y entregar tarea"
                    />
                    <div className="flex flex-wrap gap-3 text-xs">
                      <span className="rounded-lg bg-zinc-100 px-3 py-2">
                        Entrega: {date(selected.contenido.fechaEntrega)}
                      </span>
                      <span
                        className={`rounded-lg px-3 py-2 ${selected.contenido.disponible ? "bg-[#9d2449]/7 text-[#9d2449]" : "bg-zinc-100 text-zinc-500"}`}
                      >
                        {selected.contenido.disponible
                          ? "Instrucciones disponibles"
                          : `Disponible: ${date(selected.contenido.disponibleDesde)}`}
                      </span>
                    </div>
                    <p className="whitespace-pre-wrap break-words text-sm leading-relaxed text-zinc-600">
                      {selected.contenido.disponible
                        ? selected.contenido.instrucciones ||
                          "El instructor no ha agregado instrucciones."
                        : "Las instrucciones se mostrarán en la fecha de disponibilidad."}
                    </p>
                    {selected.contenido.disponible && (
                      <>
                        <p className="text-xs text-zinc-500">
                          {selected.contenido.puntos !== null
                            ? `${selected.contenido.puntos} puntos`
                            : ""}
                          {selected.contenido.formato ? ` · ${selected.contenido.formato}` : ""}
                        </p>
                        {selected.contenido.guiaUrl && (
                          <ResourceLink
                            url={selected.contenido.guiaUrl}
                            title={selected.contenido.guiaNombre}
                            className="inline-flex items-center gap-2 text-sm text-[#9d2449] underline underline-offset-4"
                          >
                            {selected.contenido.guiaNombre}
                            <ExternalLink className="size-3.5" />
                          </ResourceLink>
                        )}
                      </>
                    )}
                  </div>
                )}
                {(selected.tipo === "evaluacion" || selected.tipo === "examen") && (
                  <div className="space-y-4">
                    <p className="text-sm text-zinc-500">
                      Responde una pregunta a la vez. Debes aprobar esta evaluación para continuar.
                    </p>
                    <dl className="grid gap-3 sm:grid-cols-3">
                      <div className="rounded-xl bg-zinc-50 p-4">
                        <dt className="text-xs text-zinc-500">Preguntas</dt>
                        <dd className="mt-1 font-semibold">{selected.contenido.preguntas}</dd>
                      </div>
                      <div className="rounded-xl bg-zinc-50 p-4">
                        <dt className="text-xs text-zinc-500">Tiempo</dt>
                        <dd className="mt-1 font-semibold">
                          {selected.contenido.minutos !== null
                            ? formatDuration(Math.round(selected.contenido.minutos * 60))
                            : "Sin registrar"}
                        </dd>
                      </div>
                      <div className="rounded-xl bg-zinc-50 p-4">
                        <dt className="text-xs text-zinc-500">Calificación mínima</dt>
                        <dd className="mt-1 font-semibold">
                          {selected.contenido.minima !== null
                            ? `${selected.contenido.minima}%`
                            : "Sin registrar"}
                        </dd>
                      </div>
                    </dl>
                    <Link
                      href={examHref(selected.contenido.id)}
                      className="inline-flex items-center gap-2 rounded-xl bg-zinc-900 px-5 py-3 text-sm font-medium text-white hover:bg-zinc-700"
                    >
                      {progress.aprobadas.includes(selected.contenido.id)
                        ? "Ver evaluación"
                        : "Comenzar evaluación"}
                      <ArrowRight className="size-4" />
                    </Link>
                  </div>
                )}
              </Card.Content>
            </>
          ) : (
            <Card.Content className="p-6">
              <BookOpen className="mb-3 size-6 text-[#9d2449]" />
              <h2 className="font-semibold">{selectedModule?.titulo ?? "Contenido del curso"}</h2>
              <p className="mt-2 text-sm text-zinc-500">
                Selecciona una actividad del temario o consulta los materiales de este módulo.
              </p>
            </Card.Content>
          )}
        </Card>
        <Card id="materiales" className="gap-4 border border-zinc-200/70 p-5 shadow-none sm:p-6">
          <Card.Header className="flex flex-row items-center gap-2 p-0">
            <FolderOpen className="size-5 text-[#9d2449]" />
            <Card.Title className="text-base font-semibold">
              Material de apoyo{selectedModule ? ` · ${selectedModule.titulo}` : ""}
            </Card.Title>
          </Card.Header>
          <Card.Content className="p-0">
            {!resources.length ? (
              <p className="text-sm text-zinc-500">No hay materiales de apoyo para esta sección.</p>
            ) : (
              <ul className="divide-y divide-zinc-100">
                {resources.map((m) => (
                  <li key={m.id} className="py-3 first:pt-0 last:pb-0">
                    {m.url ? (
                      <ResourceLink
                        url={m.url}
                        title={formatDisplayName(m.titulo)}
                        className="inline-flex items-start gap-2 text-sm font-medium text-[#9d2449] underline underline-offset-4"
                      >
                        <span className="break-words">{formatDisplayName(m.titulo)}</span>
                        <ExternalLink className="mt-0.5 size-3.5 shrink-0" />
                      </ResourceLink>
                    ) : (
                      <p className="text-sm">{formatDisplayName(m.titulo)}</p>
                    )}
                    <p className="mt-1 text-xs text-zinc-500">
                      {m.categoria}
                      {m.tamano ? ` · ${m.tamano}` : ""}
                    </p>
                  </li>
                ))}
              </ul>
            )}
          </Card.Content>
        </Card>
      </div>
      <aside
        aria-label="Temario del aula"
        className="order-first min-w-0 lg:sticky lg:top-20 lg:order-last lg:col-span-4"
      >
        <Card className="gap-0 overflow-hidden border border-zinc-200/70 p-0 shadow-none">
          <details open>
            <summary className="flex cursor-pointer list-none items-center justify-between gap-3 p-5 [&::-webkit-details-marker]:hidden">
              <span className="flex items-center gap-3">
                <ListOrdered className="size-5 text-[#9d2449]" />
                <span>
                  <span className="block text-base font-semibold">Cronología del módulo</span>
                  <span className="mt-1 block text-xs text-zinc-500">
                    {sessions.length} actividades en el recorrido
                  </span>
                </span>
              </span>
              <ChevronDown className="size-4 text-zinc-400" />
            </summary>
            <ol className="max-h-[35dvh] space-y-2 overflow-y-auto overscroll-contain border-t border-zinc-100 p-3 lg:max-h-[calc(100dvh-15rem)]">
              {sessions.map((item, index) => {
                const Icon =
                  item.tipo === "video" ? Play : item.tipo === "tarea" ? ClipboardList : FileCheck2;
                const linkedVideo =
                  (item.tipo === "evaluacion" || item.tipo === "examen") && item.contenido.claseId
                    ? sessions.find(
                        (s) => s.tipo === "video" && s.contenido.id === item.contenido.claseId,
                      )
                    : undefined;
                const active = index === selectedIndex;
                const locked = !!progress.bloqueos[item.contenido.id];
                const done =
                  progress.aprobadas.includes(item.contenido.id) ||
                  (item.tipo === "video" && progress.lecciones[item.contenido.id]?.completado);
                return (
                  <li
                    key={item.contenido.id}
                    className={linkedVideo ? "ml-6 border-l-2 border-[#9d2449]/20 pl-2" : undefined}
                  >
                    <Button
                      variant="secondary"
                      fullWidth
                      aria-current={active ? "step" : undefined}
                      onPress={() => select(index)}
                      className={`h-auto min-h-16 justify-start gap-3 whitespace-normal rounded-xl p-3 text-left ${active ? "bg-[#9d2449] text-white hover:bg-[#801c3a]" : "bg-transparent text-zinc-700"}`}
                    >
                      <span
                        className={`flex size-8 shrink-0 items-center justify-center rounded-lg ${active ? "bg-white/15" : "bg-zinc-100 text-[#9d2449]"}`}
                      >
                        {locked ? (
                          <LockKeyhole className="size-4" />
                        ) : done ? (
                          <CheckCircle2 className="size-4" />
                        ) : (
                          <Icon className="size-4" />
                        )}
                      </span>
                      <span className="min-w-0 flex-1">
                        <span className="block break-words text-sm font-medium">
                          {index + 1}. {formatDisplayName(item.contenido.titulo)}
                        </span>
                        <span
                          className={`mt-1 block text-xs ${active ? "text-white/75" : "text-zinc-400"}`}
                        >
                          {locked ? "Evaluación previa pendiente · " : ""}
                          {labels[item.tipo]}
                          {item.tipo === "video"
                            ? ` · ${formatDuration(Math.round(item.contenido.minutos * 60))}`
                            : ""}
                        </span>
                        {linkedVideo && (
                          <span
                            className={`mt-1 block text-xs ${active ? "text-white/80" : "text-[#9d2449]"}`}
                          >
                            Asignada a: {linkedVideo.contenido.titulo} ·{" "}
                            {item.tipo !== "video" && item.tipo !== "tarea"
                              ? {
                                  inicio_video: "Antes del video",
                                  mitad_video: "A mitad del video",
                                  final_video: "Al finalizar el video",
                                  modular: "Evaluación vinculada",
                                }[item.contenido.momento]
                              : ""}
                          </span>
                        )}
                      </span>
                    </Button>
                  </li>
                );
              })}
              {!sessions.length && (
                <li className="p-2 text-sm text-zinc-500">El temario aparecerá aquí.</li>
              )}
            </ol>
          </details>
        </Card>
      </aside>
    </section>
  );
}
