"use client";
// app/editor/[id]/page.jsx — review and refine an assignment, then export it.
import { useEffect, useRef, useState } from "react";
import { useParams, useRouter } from "next/navigation";
import QuestionCard from "@/components/QuestionCard";
import CanvasExportDialog from "@/components/CanvasExportDialog";
import { QUESTION_TYPES, blankQuestion, totalPoints } from "@/lib/schema";
import { exportTxt, exportDoc, exportClipboard, exportPrint } from "@/lib/exporter";

export default function EditorPage() {
  const { id } = useParams();
  const router = useRouter();

  const [a, setA] = useState(null);
  const [loadErr, setLoadErr] = useState("");
  const [dirty, setDirty] = useState(false);
  const [saving, setSaving] = useState(false);
  const [toast, setToast] = useState("");
  const [busyQ, setBusyQ] = useState(null);
  const [verifying, setVerifying] = useState(false);
  const [addOpen, setAddOpen] = useState(false);
  const [exportOpen, setExportOpen] = useState(false);
  const [canvasOpen, setCanvasOpen] = useState(false);
  const [error, setError] = useState("");
  const [profile, setProfile] = useState({});
  const toastTimer = useRef(null);

  useEffect(() => {
    fetch("/api/assignments/" + id)
      .then(async (r) => {
        const data = await r.json();
        if (!r.ok) throw new Error(data.error || "Could not load this assignment.");
        setA(data);
      })
      .catch((e) => setLoadErr(String(e.message || e)));
    fetch("/api/settings")
      .then((r) => r.json())
      .then((s) => setProfile(s?.profile || {}))
      .catch(() => {});
  }, [id]);

  useEffect(() => {
    function onBeforeUnload(e) {
      if (dirty) { e.preventDefault(); e.returnValue = ""; }
    }
    window.addEventListener("beforeunload", onBeforeUnload);
    return () => window.removeEventListener("beforeunload", onBeforeUnload);
  }, [dirty]);

  function showToast(msg) {
    setToast(msg);
    clearTimeout(toastTimer.current);
    toastTimer.current = setTimeout(() => setToast(""), 2400);
  }

  function patch(p) {
    setA((cur) => ({ ...cur, ...p }));
    setDirty(true);
  }

  function setQuestion(i, q) {
    setA((cur) => {
      const questions = [...cur.questions];
      questions[i] = q;
      return { ...cur, questions };
    });
    setDirty(true);
  }

  function moveQuestion(i, dir) {
    setA((cur) => {
      const questions = [...cur.questions];
      const j = i + dir;
      if (j < 0 || j >= questions.length) return cur;
      [questions[i], questions[j]] = [questions[j], questions[i]];
      return { ...cur, questions };
    });
    setDirty(true);
  }

  function deleteQuestion(i) {
    if (!confirm("Delete question " + (i + 1) + "?")) return;
    setA((cur) => ({ ...cur, questions: cur.questions.filter((_, j) => j !== i) }));
    setDirty(true);
  }

  async function save(silent) {
    setSaving(true);
    setError("");
    try {
      const res = await fetch("/api/assignments/" + id, {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(a),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Save failed.");
      setA(data);
      setDirty(false);
      if (!silent) showToast("Saved");
    } catch (e) {
      setError(String(e.message || e));
    } finally {
      setSaving(false);
    }
  }

  async function regenerateQuestion(i, note) {
    const q = a.questions[i];
    setBusyQ(q.id);
    setError("");
    try {
      const data = await postJson("/api/generate", {
        stage: "question",
        source: a.source?.text || "",
        config: a.config || { assignmentType: a.assignmentType, gradeLevel: a.gradeLevel, subject: a.subject, difficulty: a.difficulty },
        type: q.type,
        note,
        replacing: { question: q.question },
        existingQuestions: a.questions.filter((_, j) => j !== i).map((x) => ({ question: x.question })),
      });
      const next = { ...data.question, points: q.points };
      setQuestion(i, next);
      showToast("Question " + (i + 1) + " regenerated");
    } catch (e) {
      setError(String(e.message || e));
    } finally {
      setBusyQ(null);
    }
  }

  async function addQuestion(type, withAI) {
    setAddOpen(false);
    if (!withAI) {
      setA((cur) => ({ ...cur, questions: [...cur.questions, blankQuestion(type)] }));
      setDirty(true);
      return;
    }
    setBusyQ("__new__");
    setError("");
    try {
      const data = await postJson("/api/generate", {
        stage: "question",
        source: a.source?.text || "",
        config: a.config || { assignmentType: a.assignmentType, gradeLevel: a.gradeLevel, subject: a.subject, difficulty: a.difficulty },
        type,
        existingQuestions: a.questions.map((x) => ({ question: x.question })),
      });
      setA((cur) => ({ ...cur, questions: [...cur.questions, data.question] }));
      setDirty(true);
      showToast("Question added");
    } catch (e) {
      setError(String(e.message || e));
    } finally {
      setBusyQ(null);
    }
  }

  async function reverify() {
    setVerifying(true);
    setError("");
    try {
      const data = await postJson("/api/generate", {
        stage: "verify",
        source: a.source?.text || "",
        config: a.config || { assignmentType: a.assignmentType, gradeLevel: a.gradeLevel, subject: a.subject, difficulty: a.difficulty },
        questions: a.questions,
      });
      setA((cur) => ({
        ...cur,
        questions: cur.questions.map((q) =>
          data.verifications[q.id]
            ? { ...q, verification: data.verifications[q.id] }
            : { ...q, verification: { status: "unchecked", note: "" } }
        ),
      }));
      setDirty(true);
      const warns = Object.values(data.verifications).filter((v) => v.status === "warn").length;
      showToast(warns
        ? `Accuracy check done — ${warns} question${warns === 1 ? "" : "s"} flagged`
        : "Accuracy check done — all clear"
      );
    } catch (e) {
      setError(String(e.message || e));
    } finally {
      setVerifying(false);
    }
  }

  function doExport(kind, who) {
    setExportOpen(false);
    const opts = who === "packet" ? { packet: true, profile } : { teacher: who === true, profile };
    try {
      if (kind === "txt")   { exportTxt(a, opts); showToast("Downloaded .txt"); }
      if (kind === "doc")   { exportDoc(a, opts); showToast("Downloaded Word file"); }
      if (kind === "print") { exportPrint(a, opts); }
      if (kind === "copy")  { exportClipboard(a, opts).then(() => showToast("Copied to clipboard")); }
    } catch (e) {
      setError(String(e.message || e));
    }
  }

  if (loadErr) {
    return (
      <div className="empty">
        <h3>Couldn&rsquo;t open that assignment</h3>
        <p>{loadErr}</p>
        <button className="btn btn-primary" style={{ marginTop: 12 }} onClick={() => router.push("/library")}>Go to Library</button>
      </div>
    );
  }

  if (!a) {
    return (
      <div style={{ padding: "40px 0" }}>
        <div className="card skeleton-card" style={{ marginBottom: 16 }}>
          <div className="skeleton-line" style={{ width: "60%", height: 28, borderRadius: 6, marginBottom: 12 }} />
          <div className="skeleton-line short" />
        </div>
        {[0, 1, 2].map((i) => (
          <div key={i} className="card skeleton-card" style={{ marginBottom: 14, animationDelay: `${i * 0.15}s` }}>
            <div className="skeleton-chip" />
            <div className="skeleton-line full" />
            <div className="skeleton-line medium" />
          </div>
        ))}
      </div>
    );
  }

  const warnCount = a.questions.filter((q) => q.verification?.status === "warn").length;
  const uncheckedCount = a.questions.filter((q) => !q.verification || q.verification.status === "unchecked").length;

  return (
    <div>
      <div className="page-head" style={{ display: "flex", alignItems: "flex-start", gap: 12, flexWrap: "wrap" }}>
        <div style={{ flex: 1, minWidth: 260 }}>
          <input
            type="text"
            value={a.title}
            onChange={(e) => patch({ title: e.target.value })}
            aria-label="Assignment title"
            style={{
              fontFamily: "var(--font-display)", fontSize: "1.6rem", fontWeight: 700,
              border: "1.5px solid transparent", background: "transparent",
              padding: "4px 8px", marginLeft: -8, borderRadius: 8, width: "100%",
              transition: "border-color 0.15s, background 0.15s",
            }}
            onFocus={(e) => { e.target.style.borderColor = "var(--line-strong)"; e.target.style.background = "var(--field-bg)"; }}
            onBlur={(e) => { e.target.style.borderColor = "transparent"; e.target.style.background = "transparent"; }}
          />
          <p className="muted small" style={{ margin: "4px 0 0 2px" }}>
            {[a.assignmentType?.replace("_", " "), a.gradeLevel, a.subject].filter(Boolean).join(" · ")} · {a.questions.length} questions · {totalPoints(a.questions)} points
            {a.source?.name ? <> · from <i>{a.source.name}</i></> : null}
          </p>
        </div>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
          <div style={{ position: "relative" }}>
            <button className="btn" onClick={() => { setExportOpen((o) => !o); setAddOpen(false); }}>Export ▾</button>
            {exportOpen && (
              <div className="card" style={{ position: "absolute", right: 0, top: "calc(100% + 6px)", zIndex: 30, width: 295, padding: 16, animation: "fade-in-up 0.18s ease" }}>
                <div className="field-label">Student version</div>
                <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 12 }}>
                  <button className="btn btn-sm" onClick={() => doExport("print", false)}>Print / PDF</button>
                  <button className="btn btn-sm" onClick={() => doExport("doc", false)}>Word</button>
                  <button className="btn btn-sm" onClick={() => doExport("txt", false)}>Text</button>
                  <button className="btn btn-sm" onClick={() => doExport("copy", false)}>Copy</button>
                </div>
                <div className="field-label" style={{ color: "var(--redpen)" }}>Teacher version (answer key)</div>
                <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 12 }}>
                  <button className="btn btn-sm" onClick={() => doExport("print", true)}>Print / PDF</button>
                  <button className="btn btn-sm" onClick={() => doExport("doc", true)}>Word</button>
                  <button className="btn btn-sm" onClick={() => doExport("txt", true)}>Text</button>
                  <button className="btn btn-sm" onClick={() => doExport("copy", true)}>Copy</button>
                </div>
                <div className="field-label">Complete packet — student + answer key</div>
                <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 12 }}>
                  <button className="btn btn-sm" onClick={() => doExport("print", "packet")}>Print / PDF</button>
                  <button className="btn btn-sm" onClick={() => doExport("doc", "packet")}>Word</button>
                </div>
                <div className="field-label">Canvas (LMS)</div>
                <button className="btn btn-sm" onClick={() => { setExportOpen(false); setCanvasOpen(true); }}>
                  Set up &amp; download .zip…
                </button>
              </div>
            )}
          </div>
          <button className="btn" onClick={reverify} disabled={verifying || !a.source?.text}>
            {verifying ? <><span className="spinner" /> Checking…</> : "Re-run accuracy check"}
          </button>
          <button className="btn btn-primary" onClick={() => save(false)} disabled={saving || !dirty}>
            {saving ? <><span className="spinner" /> Saving…</> : dirty ? "Save" : "Saved ✓"}
          </button>
        </div>
      </div>

      {error && <div className="alert alert-error">{error}</div>}
      {warnCount > 0 && (
        <div className="alert alert-warn">
          <b>{warnCount} question{warnCount === 1 ? "" : "s"} flagged by the accuracy check.</b> Look for the ⚠ stamps below — each has a reviewer note. Edit or regenerate those questions, then re-run the check.
        </div>
      )}
      {warnCount === 0 && uncheckedCount === 0 && a.questions.length > 0 && (
        <div className="alert alert-info">✓ Every question passed the accuracy check against your source.</div>
      )}

      <label className="field">
        <span className="field-label">Student instructions</span>
        <textarea rows={2} value={a.instructions || ""} onChange={(e) => patch({ instructions: e.target.value })} placeholder="Instructions students see at the top…" />
      </label>

      {a.caseStudy ? (
        <label className="field">
          <span className="field-label">Case study scenario (students read this first)</span>
          <textarea rows={8} value={a.caseStudy} onChange={(e) => patch({ caseStudy: e.target.value })} />
        </label>
      ) : null}

      {a.questions.map((q, i) => (
        <QuestionCard
          key={q.id}
          q={q}
          index={i}
          count={a.questions.length}
          busy={busyQ === q.id}
          onChange={(next) => setQuestion(i, next)}
          onMove={(dir) => moveQuestion(i, dir)}
          onDelete={() => deleteQuestion(i)}
          onRegenerate={(note) => regenerateQuestion(i, note)}
        />
      ))}

      <div style={{ marginTop: 18, position: "relative", display: "flex", gap: 10 }}>
        <button className="btn" onClick={() => { setAddOpen((o) => !o); setExportOpen(false); }} disabled={busyQ === "__new__"}>
          {busyQ === "__new__" ? <><span className="spinner" /> Writing question…</> : "+ Add question ▾"}
        </button>
        {addOpen && (
          <div className="card" style={{ position: "absolute", left: 0, bottom: "calc(100% + 6px)", zIndex: 30, width: 324, padding: 16, animation: "fade-in-up 0.18s ease" }}>
            {[...QUESTION_TYPES, { id: "discussion", label: "Discussion prompt" }].map((t) => (
              <div key={t.id} style={{ display: "flex", alignItems: "center", gap: 8, padding: "5px 0", borderBottom: "1px solid var(--line)" }}>
                <span style={{ flex: 1, fontSize: "0.92rem", fontWeight: 600 }}>{t.label}</span>
                <button
                  className="btn btn-sm btn-primary"
                  onClick={() => addQuestion(t.id, true)}
                  disabled={!a.source?.text}
                  title={a.source?.text ? "Generate from your source" : "No source stored with this assignment"}
                >AI</button>
                <button className="btn btn-sm" onClick={() => addQuestion(t.id, false)}>Blank</button>
              </div>
            ))}
          </div>
        )}
        <span className="spacer" />
        <span className="muted small" style={{ alignSelf: "center" }}>
          Total: <b>{totalPoints(a.questions)}</b> points
        </span>
      </div>

      {canvasOpen && (
        <CanvasExportDialog
          assignment={a}
          onClose={() => setCanvasOpen(false)}
          onDone={() => { setCanvasOpen(false); showToast("Downloaded Canvas .zip"); }}
          onError={(msg) => { setCanvasOpen(false); setError(msg); }}
        />
      )}

      {toast && <div className="toast">{toast}</div>}
    </div>
  );
}

async function postJson(url, body) {
  const res = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  const data = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(data.error || `Request failed (${res.status}).`);
  return data;
}
