"use client";
import { Check } from "lucide-react";
import DurationField from "./DurationField";
import CourseVideo from "@/components/ui/CourseVideo";
import { importarVideoYouTube } from "@/app/actions/youtube";
import { youtubeId } from "@/lib/aula/youtube";
import ResourceLink from "@/components/ui/ResourceLink";
import { useConfirmDialog } from "@/components/ui/useConfirmDialog";
import SystemAlert from "@/components/ui/SystemAlert";
import { useEffect, useRef, useState, type FormEvent } from "react";
import { useFormDraft } from "./useFormDraft";
import QuestionListEditor from "./QuestionListEditor";
import AulaDateTimeField from "./AulaDateTimeField";
import { type CourseSession, type Question, sessionSchema } from "@/lib/aula/schema";
import {
  ActionButton,
  Field,
  FileUpload,
  Panel,
  SelectField,
  TextField,
  fileHref,
} from "./EditorUI";

type Props = {
  draftKey: string;
  aulaId: number;
  initial: CourseSession;
  videos: CourseSession[];
  onSave: (session: CourseSession) => void;
  onCancel: () => void;
};
export default function SessionEditor({
  draftKey,
  aulaId,
  initial,
  videos,
  onSave,
  onCancel,
}: Props) {
  const { ask, confirmationDialog } = useConfirmDialog();
  const draft = useFormDraft(draftKey, initial, sessionSchema);
  const session = draft.value;
  const setSession = draft.update;
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState("");
  const [activeQuestionId, setActiveQuestionId] = useState<string | null>(null);
  const patch = (data: Partial<CourseSession>) => setSession((s) => ({ ...s, ...data }));
  const [pendingVideo, setPendingVideo] = useState<string | null>(null);
  const [validation, setValidation] = useState<{
    id: string;
    valid: boolean;
    message: string;
  } | null>(null);
  const [validationAttempt, setValidationAttempt] = useState(0);
  const draftUpdate = useRef(setSession);
  const loadedVideo = useRef(
    initial.titulo.trim() && initial.duracionMinutos ? youtubeId(initial.videoSrc ?? "") : null,
  );
  useEffect(() => {
    draftUpdate.current = setSession;
  });
  const videoId = session.tipo === "video" ? youtubeId(session.videoSrc ?? "") : null;
  const videoUrl = session.tipo === "video" ? (session.videoSrc ?? "") : "";
  const videoValidated = !!videoId && validation?.id === videoId && validation.valid;
  const importing = !!videoId && (pendingVideo === videoId || validation?.id !== videoId);
  const videoError =
    videoUrl && !videoId
      ? "El enlace no corresponde a un video de YouTube. Pega el enlace completo de una videoclase."
      : validation?.id === videoId && !validation.valid
        ? validation.message
        : "";
  useEffect(() => {
    if (!videoId) return;
    let active = true;
    const timer = setTimeout(async () => {
      setPendingVideo(videoId);
      setValidation(null);
      try {
        const result = await importarVideoYouTube(
          aulaId,
          `https://www.youtube.com/watch?v=${videoId}`,
        );
        if (!active) return;
        if (!result.ok) {
          setValidation({ id: videoId, valid: false, message: result.error });
          return;
        }
        if (loadedVideo.current !== videoId)
          draftUpdate.current((current) =>
            youtubeId(current.videoSrc ?? "") !== videoId
              ? current
              : {
                  ...current,
                  titulo: result.data.titulo,
                  descripcion: result.data.descripcion ?? current.descripcion,
                  duracionMinutos: result.data.duracionMinutos ?? current.duracionMinutos,
                },
          );
        loadedVideo.current = videoId;
        setValidation({
          id: videoId,
          valid: true,
          message:
            result.data.descripcion === null
              ? "Video verificado. Título importado; reproduce la vista previa para detectar la duración. La descripción puede completarse manualmente."
              : "Video verificado. Sus datos se obtuvieron automáticamente.",
        });
      } catch {
        if (active)
          setValidation({
            id: videoId,
            valid: false,
            message:
              "No se pudo verificar el video. Revisa tu conexión y vuelve a pegar el enlace.",
          });
      } finally {
        if (active) setPendingVideo(null);
      }
    }, 650);
    return () => {
      active = false;
      clearTimeout(timer);
    };
  }, [aulaId, videoId, videoUrl, validationAttempt]);
  const questions = session.questions ?? session.preguntas ?? [];
  function updateQuestions(next: Question[]) {
    patch({ questions: next, preguntas: next });
  }
  function save(event: FormEvent) {
    event.preventDefault();
    const parsed = sessionSchema.safeParse(session);
    if (!parsed.success) {
      setError(parsed.error.issues[0].message);
      return;
    }
    if (session.tipo === "video" && !videoValidated) {
      setError(videoError || "Espera a que se verifique el video de YouTube.");
      return;
    }
    if (!session.titulo.trim()) {
      setError("Escribe el título.");
      return;
    }
    if (session.tipo === "video" && (!session.videoSrc || !session.duracionMinutos)) {
      setError("Agrega un video e indica una duración mayor a cero.");
      return;
    }
    if (session.tipo === "video" && !youtubeId(session.videoSrc ?? "")) {
      setError("Escribe un enlace válido de YouTube.");
      return;
    }
    if (
      session.tipo === "tarea" &&
      (!session.fechaEntrega ||
        (session.fechaDisponible && session.fechaDisponible > session.fechaEntrega))
    ) {
      setError("Revisa las fechas de disponibilidad y entrega.");
      return;
    }
    if (session.tipo === "examen" || session.tipo === "evaluacion") {
      const incomplete = questions.find(
        (q) => !q.question.trim() || q.options.some((option) => !option.trim()),
      );
      if (incomplete) {
        setActiveQuestionId(incomplete.id);
        setError("Completa el enunciado y las opciones de la pregunta seleccionada.");
        return;
      }
    }
    draft.clear();
    onSave(parsed.data);
  }
  const examination = session.tipo === "examen" || session.tipo === "evaluacion";
  return (
    <Panel
      title={
        session.tipo === "video"
          ? "Editar videoclase"
          : session.tipo === "tarea"
            ? "Editar tarea"
            : "Editar evaluación"
      }
    >
      {confirmationDialog}
      <form onSubmit={save} className="space-y-5">
        {draft.recovery && (
          <SystemAlert
            status="warning"
            title="Hay cambios sin aplicar"
            action={
              <>
                <ActionButton onClick={draft.restore}>Recuperar formulario</ActionButton>
                <ActionButton
                  onClick={async () => {
                    if (
                      await ask({
                        title: "¿Descartar la copia del formulario?",
                        description:
                          "Se eliminará esta copia de recuperación. Los cambios del formulario abierto se conservan.",
                        confirmLabel: "Descartar copia",
                        status: "warning",
                      })
                    )
                      draft.clear();
                  }}
                >
                  Descartar copia
                </ActionButton>
              </>
            }
          >
            {"Hay cambios sin aplicar de este formulario."}
          </SystemAlert>
        )}
        {session.tipo === "video" && (
          <div className="space-y-3">
            <div className="relative">
              <Field
                label="Enlace del video de YouTube"
                type="url"
                required
                placeholder="https://www.youtube.com/watch?v=..."
                value={session.videoSrc ?? ""}
                maxLength={2048}
                className={videoValidated ? "pr-12" : undefined}
                aria-invalid={!!videoError}
                aria-describedby="youtube-video-status"
                onPaste={() => setValidationAttempt((n) => n + 1)}
                onChange={(e) => {
                  const url = e.target.value.trim();
                  const changed = youtubeId(url) !== youtubeId(session.videoSrc ?? "");
                  if (changed) loadedVideo.current = null;
                  patch({
                    videoSrc: url,
                    videoFileName: "",
                    ...(changed ? { titulo: "", descripcion: "", duracionMinutos: 0 } : {}),
                  });
                  setPendingVideo(null);
                  setValidation(null);
                }}
              />
              {videoValidated && (
                <span
                  id="youtube-video-status"
                  role="status"
                  className="pointer-events-none absolute right-3 bottom-2 flex size-6 items-center justify-center rounded-full bg-emerald-100 text-emerald-700"
                >
                  <Check className="size-4" strokeWidth={3} aria-hidden="true" />
                  <span className="sr-only">Video verificado</span>
                </span>
              )}
            </div>
            {videoError ? (
              <SystemAlert status="danger" title="Revisa el enlace del video">
                <span id="youtube-video-status">{videoError}</span>
              </SystemAlert>
            ) : !videoValidated ? (
              <p id="youtube-video-status" role="status" className="text-sm text-zinc-500">
                {importing
                  ? "Verificando video y obteniendo sus datos…"
                  : "Pega el enlace para verificar el video y obtener sus datos automáticamente."}
              </p>
            ) : null}
          </div>
        )}
        <Field
          label="Título"
          required
          maxLength={255}
          value={session.titulo}
          onChange={(e) => patch({ titulo: e.target.value })}
        />
        <TextField
          label={session.tipo === "tarea" ? "Instrucciones" : "Descripción"}
          maxLength={20000}
          value={
            session.tipo === "tarea"
              ? (session.instrucciones ?? session.descripcion ?? "")
              : (session.descripcion ?? "")
          }
          onChange={(e) =>
            patch(
              session.tipo === "tarea"
                ? { instrucciones: e.target.value, descripcion: e.target.value }
                : { descripcion: e.target.value },
            )
          }
        />
        {session.tipo === "video" && (
          <>
            {videoValidated && (
              <div className="space-y-2">
                <CourseVideo
                  key={session.videoSrc}
                  onError={() => {
                    if (videoId)
                      setValidation({
                        id: videoId,
                        valid: false,
                        message:
                          "Este video no puede reproducirse dentro del aula. Comprueba que esté disponible y permita inserción, y vuelve a pegar el enlace.",
                      });
                  }}
                  onDuration={(seconds) => {
                    if (Number.isFinite(seconds) && seconds > 0)
                      patch({
                        duracionMinutos: Math.max(1, Math.round(seconds)) / 60,
                      });
                  }}
                  controls
                  preload="metadata"
                  src={session.videoSrc}
                  className="aspect-video min-h-[200px] w-full overflow-hidden rounded-2xl bg-zinc-950 object-contain"
                />
              </div>
            )}
            <DurationField
              label="Duración"
              value={session.duracionMinutos ?? 0}
              onChange={(minutes) => patch({ duracionMinutos: minutes })}
            />
            <TextField
              label="Objetivos (uno por línea)"
              value={(session.objetivos ?? []).join("\n")}
              onChange={(e) => patch({ objetivos: e.target.value.split("\n") })}
            />
          </>
        )}
        {session.tipo !== "video" && (
          <SelectField
            label="Videoclase vinculada"
            value={session.claseVinculadaId ?? ""}
            onChange={(e) =>
              patch({
                claseVinculadaId: e.target.value,
                claseVinculadaTitulo: videos.find((v) => v.id === e.target.value)?.titulo,
              })
            }
          >
            <option value="">Sin vincular</option>
            {videos.map((v) => (
              <option key={v.id} value={v.id}>
                {v.titulo}
              </option>
            ))}
          </SelectField>
        )}
        {session.tipo === "tarea" && (
          <>
            <div className="grid gap-4 sm:grid-cols-2">
              <AulaDateTimeField
                label="Disponible desde"
                value={session.fechaDisponible ?? ""}
                onChange={(value) => patch({ fechaDisponible: value })}
              />
              <AulaDateTimeField
                label="Fecha límite"
                required
                value={session.fechaEntrega ?? ""}
                onChange={(value) => patch({ fechaEntrega: value })}
              />
              <Field
                label="Puntos máximos"
                type="number"
                min="1"
                max="10000"
                value={session.puntosMaximos ?? 100}
                onChange={(e) => patch({ puntosMaximos: Number(e.target.value) })}
              />
              <Field
                label="Ponderación (%)"
                type="number"
                min="0"
                max="100"
                value={session.ponderacion ?? 20}
                onChange={(e) => patch({ ponderacion: Number(e.target.value) })}
              />
            </div>
            <Field
              label="Formato de entrega"
              maxLength={255}
              value={session.formatoEntrega ?? ""}
              onChange={(e) => patch({ formatoEntrega: e.target.value })}
            />
            {session.archivoGuiaUrl && (
              <ResourceLink
                url={fileHref(aulaId, session.archivoGuiaUrl)}
                title={session.archivoGuiaNombre || "Archivo guía"}
                className="block break-words text-sm text-[#9d2449] underline"
              />
            )}
            <FileUpload
              aulaId={aulaId}
              category="tarea"
              label="Adjuntar o reemplazar guía de la tarea"
              onBusy={setBusy}
              onUploaded={(f) => patch({ archivoGuiaUrl: f.url, archivoGuiaNombre: f.filename })}
            />
            {session.archivoGuiaUrl && (
              <ActionButton onClick={() => patch({ archivoGuiaUrl: "", archivoGuiaNombre: "" })}>
                Quitar guía
              </ActionButton>
            )}
          </>
        )}
        {examination && (
          <>
            <div className="grid gap-4 sm:grid-cols-2">
              <SelectField
                label="Tipo"
                value={session.tipo}
                onChange={(e) => patch({ tipo: e.target.value as "examen" | "evaluacion" })}
              >
                <option value="evaluacion">Evaluación</option>
                <option value="examen">Examen</option>
              </SelectField>
              <SelectField
                label="Tipo de examen"
                value={session.tipoExamen ?? "parcial"}
                onChange={(e) =>
                  patch({ tipoExamen: e.target.value as CourseSession["tipoExamen"] })
                }
              >
                <option value="diagnostico">Diagnóstico</option>
                <option value="parcial">Parcial</option>
                <option value="final">Final</option>
              </SelectField>
              <DurationField
                label="Tiempo límite"
                maxSeconds={86400}
                value={session.tiempoLimiteMinutos ?? 30}
                onChange={(minutes) => patch({ tiempoLimiteMinutos: minutes })}
              />
              <Field
                label="Calificación mínima (%)"
                type="number"
                min="0"
                max="100"
                value={session.calificacionMinima ?? 80}
                onChange={(e) => patch({ calificacionMinima: Number(e.target.value) })}
              />
            </div>
            <SelectField
              label="Momento de aplicación"
              value={session.momentoEvaluacion ?? "modular"}
              onChange={(e) =>
                patch({ momentoEvaluacion: e.target.value as CourseSession["momentoEvaluacion"] })
              }
            >
              <option value="modular">Evaluación modular</option>
              <option value="inicio_video">Al inicio del video</option>
              <option value="mitad_video">A mitad del video</option>
              <option value="final_video">Al final del video</option>
            </SelectField>
            <QuestionListEditor
              questions={questions}
              activeId={activeQuestionId}
              onActiveChange={setActiveQuestionId}
              onChange={updateQuestions}
            />
          </>
        )}
        {error && (
          <SystemAlert status="danger" title="Revisa la información">
            {error}
          </SystemAlert>
        )}
        <div className="flex flex-wrap gap-3 border-t border-zinc-100 pt-4">
          <ActionButton
            type="submit"
            primary
            disabled={busy || importing || (session.tipo === "video" && !videoValidated)}
          >
            Aplicar cambios
          </ActionButton>
          <ActionButton
            onClick={() => {
              draft.clear();
              onCancel();
            }}
            disabled={busy || importing}
          >
            Cancelar
          </ActionButton>
        </div>
      </form>
    </Panel>
  );
}
