"use client";
// components/CanvasExportDialog.jsx — configure and download a Canvas QTI .zip for one
// assignment. Auto-fills everything derivable; exposes the optional Canvas quiz settings
// a teacher may want to set. Pure client-side (no upload) — see lib/canvas/export.js.
import { useEffect, useMemo, useState } from "react";
import { IconX } from "@tabler/icons-react";
import { mapAssignmentToCanvas } from "@/lib/canvas/map";
import { exportCanvasZip } from "@/lib/canvas/export";

const QUIZ_TYPES = [
  { id: "assignment", label: "Graded quiz" },
  { id: "practice_quiz", label: "Practice quiz (ungraded)" },
  { id: "graded_survey", label: "Graded survey" },
  { id: "survey", label: "Ungraded survey" },
];

const TYPE_LABEL = {
  multiple_choice_question: "Multiple choice",
  true_false_question: "True / False",
  essay_question: "Essay (manually graded)",
  fill_in_multiple_blanks_question: "Fill in the blank",
  matching_question: "Matching",
  text_only_question: "Intro text (case study)",
};

// datetime-local "2026-06-25T14:30" -> ISO-8601, or "" if blank/invalid.
function toIso(v) {
  if (!v) return "";
  const d = new Date(v);
  return Number.isNaN(d.getTime()) ? "" : d.toISOString();
}

export default function CanvasExportDialog({ assignment, onClose, onDone, onError }) {
  const [form, setForm] = useState({
    quizType: "assignment",
    timeLimit: "",
    allowedAttempts: "1",
    scoringPolicy: "keep_highest",
    shuffleAnswers: false,
    showCorrectAnswers: true,
    oneQuestionAtATime: false,
    cantGoBack: false,
    dueAt: "",
    unlockAt: "",
    lockAt: "",
    accessCode: "",
    includeExplanations: true,
  });
  const [busy, setBusy] = useState(false);

  // Direct Canvas push (only offered when credentials are saved in Settings).
  const [canvasReady, setCanvasReady] = useState(null); // null = unknown/loading
  const [courses, setCourses] = useState(null);         // null = not loaded yet
  const [courseId, setCourseId] = useState("");
  const [coursesErr, setCoursesErr] = useState("");
  const [loadingCourses, setLoadingCourses] = useState(false);
  const [sending, setSending] = useState(false);
  const [sent, setSent] = useState(null);               // { url, added }
  const [sendErr, setSendErr] = useState("");

  useEffect(() => {
    fetch("/api/settings")
      .then((r) => r.json())
      .then((s) => setCanvasReady(!!(s?.canvas?.baseUrl && s?.canvas?.token)))
      .catch(() => setCanvasReady(false));
  }, []);

  const set = (k, v) => setForm((f) => ({ ...f, [k]: v }));

  const opts = useMemo(() => ({
    quizType: form.quizType,
    timeLimit: form.timeLimit === "" ? "" : Math.max(0, parseInt(form.timeLimit, 10) || 0),
    allowedAttempts: parseInt(form.allowedAttempts, 10),
    scoringPolicy: form.scoringPolicy,
    shuffleAnswers: form.shuffleAnswers,
    showCorrectAnswers: form.showCorrectAnswers,
    oneQuestionAtATime: form.oneQuestionAtATime,
    cantGoBack: form.oneQuestionAtATime && form.cantGoBack,
    dueAt: toIso(form.dueAt),
    unlockAt: toIso(form.unlockAt),
    lockAt: toIso(form.lockAt),
    accessCode: form.accessCode.trim(),
    includeExplanations: form.includeExplanations,
  }), [form]);

  // Preview what will be in the package (counts + anything left out).
  const ir = useMemo(() => mapAssignmentToCanvas(assignment, opts), [assignment, opts]);

  const breakdown = useMemo(() => {
    const counts = {};
    for (const it of ir.items) counts[it.canvasType] = (counts[it.canvasType] || 0) + 1;
    return counts;
  }, [ir]);

  const skippedDiscussion = ir.skipped.filter((s) => s.type === "discussion").length;
  const skippedOther = ir.skipped.length - skippedDiscussion;
  const nothingToExport = ir.gradedCount === 0;

  function doExport() {
    setBusy(true);
    try {
      exportCanvasZip(assignment, opts);
      onDone?.();
    } catch (e) {
      onError?.(String(e?.message || e));
    } finally {
      setBusy(false);
    }
  }

  async function loadCourses() {
    setLoadingCourses(true);
    setCoursesErr("");
    try {
      const res = await fetch("/api/canvas", {
        method: "POST", headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action: "courses" }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Could not load courses.");
      setCourses(data.courses || []);
      if (data.courses?.length) setCourseId(String(data.courses[0].id));
    } catch (e) {
      setCoursesErr(String(e.message || e));
    } finally {
      setLoadingCourses(false);
    }
  }

  async function sendToCanvas() {
    setSending(true);
    setSendErr("");
    try {
      const res = await fetch("/api/canvas", {
        method: "POST", headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action: "push", assignment, opts, courseId: Number(courseId) }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Send failed.");
      setSent({ url: data.url, added: data.added });
    } catch (e) {
      setSendErr(String(e.message || e));
    } finally {
      setSending(false);
    }
  }

  return (
    <div className="modal-scrim" onClick={onClose}>
      <div
        onClick={(e) => e.stopPropagation()}
        className="modal"
        style={{ width: 560, maxWidth: "100%", padding: 24 }}
      >
        <div style={{ display: "flex", alignItems: "flex-start", gap: 12 }}>
          <div style={{ flex: 1 }}>
            <h2 style={{ fontFamily: "var(--font-display)", fontSize: "1.4rem", margin: 0 }}>Export to Canvas</h2>
            <p className="muted small" style={{ margin: "4px 0 0" }}>
              Downloads a QTI <code>.zip</code>. In Canvas: <b>Settings → Import Course Content → QTI .zip file</b>.
            </p>
          </div>
          <button className="icon-btn" onClick={onClose} aria-label="Close"><IconX size={16} /></button>
        </div>

        {/* Summary of what will be exported */}
        <div className="alert alert-info" style={{ marginTop: 16 }}>
          {nothingToExport ? (
            <b>Nothing to export — this assignment has no Canvas-compatible questions.</b>
          ) : (
            <>
              <b>{ir.gradedCount} question{ir.gradedCount === 1 ? "" : "s"}</b> → one Canvas quiz
              {" "}({ir.quiz.pointsPossible} pts).
              <div className="small" style={{ marginTop: 6 }}>
                {Object.entries(breakdown).map(([t, n]) => (
                  <span key={t} style={{ marginRight: 12, whiteSpace: "nowrap" }}>{TYPE_LABEL[t] || t}: {n}</span>
                ))}
              </div>
            </>
          )}
        </div>

        {skippedDiscussion > 0 && (
          <div className="alert alert-warn">
            {skippedDiscussion} discussion question{skippedDiscussion === 1 ? "" : "s"} left out — Canvas quizzes have no discussion type.
          </div>
        )}
        {skippedOther > 0 && (
          <div className="alert alert-warn">
            {skippedOther} question{skippedOther === 1 ? "" : "s"} couldn&rsquo;t be converted and were left out.
          </div>
        )}

        {/* Optional Canvas settings — auto-filled with sensible defaults */}
        <div className="field-label" style={{ marginTop: 8 }}>Quiz settings (optional — change in Canvas later too)</div>

        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <label className="field" style={{ marginBottom: 0 }}>
            <span className="field-label">Quiz type</span>
            <select value={form.quizType} onChange={(e) => set("quizType", e.target.value)}>
              {QUIZ_TYPES.map((t) => <option key={t.id} value={t.id}>{t.label}</option>)}
            </select>
          </label>
          <label className="field" style={{ marginBottom: 0 }}>
            <span className="field-label">Time limit (minutes)</span>
            <input type="number" min="0" value={form.timeLimit} placeholder="No limit"
              onChange={(e) => set("timeLimit", e.target.value)} />
          </label>
          <label className="field" style={{ marginBottom: 0 }}>
            <span className="field-label">Allowed attempts</span>
            <select value={form.allowedAttempts} onChange={(e) => set("allowedAttempts", e.target.value)}>
              <option value="1">1</option>
              <option value="2">2</option>
              <option value="3">3</option>
              <option value="-1">Unlimited</option>
            </select>
          </label>
          <label className="field" style={{ marginBottom: 0 }}>
            <span className="field-label">Keep which score</span>
            <select value={form.scoringPolicy} onChange={(e) => set("scoringPolicy", e.target.value)}
              disabled={form.allowedAttempts === "1"}>
              <option value="keep_highest">Highest</option>
              <option value="keep_latest">Latest</option>
            </select>
          </label>
          <label className="field" style={{ marginBottom: 0 }}>
            <span className="field-label">Available from</span>
            <input type="datetime-local" value={form.unlockAt} onChange={(e) => set("unlockAt", e.target.value)} />
          </label>
          <label className="field" style={{ marginBottom: 0 }}>
            <span className="field-label">Due</span>
            <input type="datetime-local" value={form.dueAt} onChange={(e) => set("dueAt", e.target.value)} />
          </label>
          <label className="field" style={{ marginBottom: 0 }}>
            <span className="field-label">Until (locks)</span>
            <input type="datetime-local" value={form.lockAt} onChange={(e) => set("lockAt", e.target.value)} />
          </label>
          <label className="field" style={{ marginBottom: 0 }}>
            <span className="field-label">Access code</span>
            <input type="text" value={form.accessCode} placeholder="None"
              onChange={(e) => set("accessCode", e.target.value)} />
          </label>
        </div>

        <div style={{ display: "flex", flexDirection: "column", gap: 8, marginTop: 14 }}>
          <Toggle checked={form.shuffleAnswers} onChange={(v) => set("shuffleAnswers", v)} label="Shuffle answer order" />
          <Toggle checked={form.showCorrectAnswers} onChange={(v) => set("showCorrectAnswers", v)} label="Show correct answers after submission" />
          <Toggle checked={form.oneQuestionAtATime} onChange={(v) => set("oneQuestionAtATime", v)} label="One question at a time" />
          {form.oneQuestionAtATime && (
            <Toggle checked={form.cantGoBack} onChange={(v) => set("cantGoBack", v)} label="Lock questions after answering" indent />
          )}
          <Toggle checked={form.includeExplanations} onChange={(v) => set("includeExplanations", v)} label="Include explanations as student feedback" />
        </div>

        {/* Optional: push straight into a Canvas course (needs credentials in Settings) */}
        {!nothingToExport && canvasReady && (
          <div style={{ marginTop: 18, paddingTop: 16, borderTop: "1px solid var(--line)" }}>
            <div className="field-label">Or send directly to a Canvas course</div>
            {sent ? (
              <div className="alert alert-info" style={{ marginTop: 8 }}>
                ✓ Created a quiz with <b>{sent.added}</b> question{sent.added === 1 ? "" : "s"} (unpublished).{" "}
                <a href={sent.url} target="_blank" rel="noreferrer">Open in Canvas ↗</a>
              </div>
            ) : courses === null ? (
              <div style={{ display: "flex", alignItems: "center", gap: 10, marginTop: 8 }}>
                <button className="btn btn-sm" onClick={loadCourses} disabled={loadingCourses}>
                  {loadingCourses ? <><span className="spinner" /> Loading…</> : "Load my courses"}
                </button>
                {coursesErr && <span className="small redpen" style={{ fontWeight: 600 }}>{coursesErr}</span>}
              </div>
            ) : courses.length === 0 ? (
              <p className="small muted" style={{ marginTop: 8 }}>No teachable courses found on this Canvas account.</p>
            ) : (
              <div style={{ display: "flex", gap: 8, alignItems: "center", marginTop: 8, flexWrap: "wrap" }}>
                <select value={courseId} onChange={(e) => setCourseId(e.target.value)} style={{ flex: 1, minWidth: 200 }}>
                  {courses.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
                </select>
                <button className="btn btn-primary btn-sm" onClick={sendToCanvas} disabled={sending || !courseId}>
                  {sending ? <><span className="spinner" /> Sending…</> : "Send to Canvas"}
                </button>
              </div>
            )}
            {sendErr && <div className="alert alert-warn" style={{ marginTop: 10 }}>{sendErr}</div>}
          </div>
        )}
        {!nothingToExport && canvasReady === false && (
          <p className="small muted" style={{ marginTop: 16, paddingTop: 14, borderTop: "1px solid var(--line)" }}>
            Want one-click publishing? Add your Canvas address &amp; access token in <b>Settings → Canvas (LMS) integration</b>.
          </p>
        )}

        <div style={{ display: "flex", justifyContent: "flex-end", gap: 10, marginTop: 22 }}>
          <button className="btn" onClick={onClose}>Cancel</button>
          <button className="btn btn-primary" onClick={doExport} disabled={busy || nothingToExport}>
            {busy ? <><span className="spinner" /> Building…</> : "Download .zip"}
          </button>
        </div>
      </div>
    </div>
  );
}

function Toggle({ checked, onChange, label, indent }) {
  return (
    <label style={{ display: "flex", alignItems: "center", gap: 9, cursor: "pointer", marginLeft: indent ? 22 : 0 }}>
      <input type="checkbox" checked={checked} onChange={(e) => onChange(e.target.checked)} />
      <span style={{ fontSize: "0.9rem" }}>{label}</span>
    </label>
  );
}
