/* ==================================================================
   Online Submissions modal (KinetiX-typed tests) — teacher view.

   Replaces the Upload Sheets modal when test.type is set. Shows the
   roster with per-student submission status + auto-graded score, and
   opens a per-question detail report when "View report" is clicked.
   ================================================================== */

const KX_COBALT = "#2E5BFF";
const KX_EMERALD = "#10b981";
const KX_AMBER = "#FFB627";
const KX_MADDER = "#E63946";

const OnlineSubmissionsModal = ({ test, onClose }) => {
  const [roster, setRoster] = React.useState(null);
  const [detailFor, setDetailFor] = React.useState(null); // student row
  const [err, setErr] = React.useState("");

  React.useEffect(() => {
    if (!test) return;
    let cancelled = false;
    window.KXApi.get(`/tests/${test.id}/students`)
      .then(r => { if (!cancelled) setRoster(r); })
      .catch(e => { if (!cancelled) setErr(e?.message || "Failed to load roster"); });
    return () => { cancelled = true; };
  }, [test]);

  if (!test) return null;

  const submitted = (roster || []).filter(r => r.attempt?.status === "submitted" || r.attempt?.status === "reviewed").length;
  const inProgress = (roster || []).filter(r => r.attempt?.status === "in_progress").length;
  const notStarted = (roster || []).filter(r => !r.attempt).length;

  return (
    <div onClick={onClose} style={{ position:"fixed", inset:0, background:"rgba(0,0,0,0.78)", zIndex:200, display:"grid", placeItems:"center", padding:30 }}>
      <div onClick={e=>e.stopPropagation()} style={{ background:"var(--bg-1)", border:"1px solid var(--line-strong)", borderRadius:10, width:920, maxWidth:"100%", maxHeight:"86vh", display:"flex", flexDirection:"column" }}>
        <div style={{ padding:"14px 18px", borderBottom:"1px solid var(--line)", display:"flex", alignItems:"center", gap:10 }}>
          <div>
            <div style={{ fontSize:10, color:KX_COBALT, letterSpacing:".1em", textTransform:"uppercase", fontFamily:"monospace" }}>
              {test.id} · {test.type} · Submissions
            </div>
            <div style={{ color:"var(--ink-0)", fontSize:15, fontWeight:600 }}>{test.title}</div>
          </div>
          <span style={{ marginLeft:"auto", display:"flex", gap:8, alignItems:"center" }}>
            {roster && (
              <span className="muted" style={{ fontSize:11 }}>
                {submitted} submitted · {inProgress} in progress · {notStarted} not started
              </span>
            )}
            <button className="btn sm ghost" onClick={onClose}>✕</button>
          </span>
        </div>

        <div style={{ flex:1, overflow:"auto" }}>
          <table className="tests" style={{ width:"100%" }}>
            <thead>
              <tr>
                <th style={{ width:90 }}>Roll no.</th>
                <th>Name</th>
                <th style={{ width:140 }}>Submission</th>
                <th style={{ width:110 }}>Score</th>
                <th style={{ width:140 }}></th>
              </tr>
            </thead>
            <tbody>
              {(roster || []).map(r => {
                const att = r.attempt;
                const status = att?.status || "not_started";
                const score = att?.auto_score;
                const max = att?.max_marks;
                return (
                  <tr key={r.student_id}>
                    <td className="mono" style={{ fontSize:11.5 }}>{r.roll_no}</td>
                    <td>{r.name}</td>
                    <td><SubmissionPill status={status} submittedAt={att?.submitted_at}/></td>
                    <td>
                      {score != null && max != null ? (
                        <span className="mono" style={{ color: score === max ? "var(--green)" : score === 0 ? "var(--red)" : "var(--amber)", fontWeight: 600 }}>
                          {score}<span className="muted">/{max}</span>
                        </span>
                      ) : <span className="muted mono">—</span>}
                    </td>
                    <td>
                      <button className="btn sm primary"
                        disabled={status === "not_started" || status === "in_progress"}
                        style={{
                          background: (status === "not_started" || status === "in_progress") ? "var(--bg-3)" : KX_COBALT,
                          borderColor: (status === "not_started" || status === "in_progress") ? "var(--line)" : KX_COBALT,
                          opacity: (status === "not_started" || status === "in_progress") ? 0.5 : 1,
                        }}
                        onClick={() => setDetailFor(r)}>
                        View report
                      </button>
                    </td>
                  </tr>
                );
              })}
              {roster && roster.length === 0 && (
                <tr><td colSpan="5" style={{ padding:30, textAlign:"center", color:"var(--ink-3)", fontSize:13 }}>No students enrolled in this test.</td></tr>
              )}
              {!roster && !err && (
                <tr><td colSpan="5" style={{ padding:30, textAlign:"center", color:"var(--ink-3)", fontSize:13 }}>Loading…</td></tr>
              )}
              {err && (
                <tr><td colSpan="5" style={{ padding:30, textAlign:"center", color:"var(--red)", fontSize:13 }}>{err}</td></tr>
              )}
            </tbody>
          </table>
        </div>

        <div style={{ padding:12, borderTop:"1px solid var(--line)", display:"flex", gap:8 }}>
          <span className="muted" style={{ fontSize:11 }}>
            {test.type === "descriptive"
              ? "Open each submission to view the student's photo answers and score them. The score auto-totals across questions."
              : "MCQ answers are auto-graded the moment a student submits. No teacher action required."}
          </span>
          <span style={{ marginLeft:"auto" }}>
            <button className="btn sm" onClick={onClose}>Done</button>
          </span>
        </div>
      </div>

      {detailFor && (
        <OnlineSubmissionDetailModal test={test} student={detailFor} onClose={() => setDetailFor(null)}/>
      )}
    </div>
  );
};

const SubmissionPill = ({ status, submittedAt }) => {
  if (status === "submitted" || status === "reviewed") {
    return (
      <span className="pill green" title={submittedAt ? new Date(submittedAt).toLocaleString() : ""}>
        <span className="swatch" style={{ background:"var(--green)" }}></span>Submitted
      </span>
    );
  }
  if (status === "in_progress") {
    return <span className="pill amber"><span className="swatch" style={{ background:"var(--amber)" }}></span>In progress</span>;
  }
  return <span className="pill"><span className="swatch"></span>Not started</span>;
};

/* ──────────────────────────────────────────────────────────────────
   Per-student submission detail — per-question correct/wrong view.
   Fetches GET /tests/:display_id/students/:student_id/attempt.
   ────────────────────────────────────────────────────────────────── */

const OnlineSubmissionDetailModal = ({ test, student, onClose }) => {
  const [data, setData] = React.useState(null);
  const [err, setErr] = React.useState("");

  React.useEffect(() => {
    if (!test || !student) return;
    let cancelled = false;
    window.KXApi.get(`/tests/${test.id}/students/${student.student_id}/attempt`)
      .then(r => { if (!cancelled) setData(r); })
      .catch(e => { if (!cancelled) setErr(e?.message || "Failed to load submission"); });
    return () => { cancelled = true; };
  }, [test, student]);

  const score = data?.attempt.teacherScore ?? data?.attempt.autoScore ?? 0;
  const max = data?.attempt.maxMarks ?? 0;
  const pct = max > 0 ? Math.round((Number(score) / max) * 100) : 0;

  return (
    <div onClick={onClose} style={{ position:"fixed", inset:0, background:"rgba(0,0,0,0.85)", zIndex:220, display:"grid", placeItems:"center", padding:30 }}>
      <div onClick={e=>e.stopPropagation()} style={{ background:"var(--bg-1)", border:"1px solid var(--line-strong)", borderRadius:10, width:880, maxWidth:"100%", maxHeight:"92vh", display:"flex", flexDirection:"column" }}>
        <div style={{ padding:"14px 18px", borderBottom:"1px solid var(--line)", display:"flex", alignItems:"flex-start", gap:12 }}>
          <div>
            <div style={{ fontSize:10, color:KX_COBALT, letterSpacing:".1em", textTransform:"uppercase", fontFamily:"monospace" }}>
              {test.id} · Submission report
            </div>
            <div style={{ color:"var(--ink-0)", fontSize:15, fontWeight:600 }}>
              {student.name} <span className="mono muted" style={{ fontSize:12, marginLeft:6 }}>{student.roll_no}</span>
            </div>
          </div>
          <span style={{ marginLeft:"auto", display:"flex", alignItems:"center", gap:10 }}>
            {data && (
              <span className="mono" style={{ fontSize:13, color: pct >= 60 ? "var(--green)" : pct >= 40 ? "var(--amber)" : "var(--red)" }}>
                {score}/{max} · {pct}%
              </span>
            )}
            <button className="btn sm ghost" onClick={onClose}>✕</button>
          </span>
        </div>

        <div style={{ flex:1, overflow:"auto", padding:18, display:"flex", flexDirection:"column", gap:10 }}>
          {!data && !err && <div style={{ color:"var(--ink-3)", fontSize:13 }}>Loading…</div>}
          {err && <div style={{ color:"var(--red)", fontSize:13 }}>{err}</div>}
          {data && data.sections.flatMap(sec =>
            sec.questions.map(q => {
              const resp = data.responses[q.id];
              const isObjective = q.type === "mcq" || q.type === "tf";
              const picked = resp?.selectedOptionId
                ? q.options.find(o => o.id === resp.selectedOptionId)
                : null;
              const correctOpt = q.options.find(o => o.is_correct);
              const photos = Array.isArray(resp?.responseImages) ? resp.responseImages : [];
              const skipped = isObjective ? !picked : photos.length === 0;
              const isCorrect = isObjective && picked?.id === correctOpt?.id;
              const teacherScore = resp?.teacherScore;

              return (
                <div key={q.id} style={{
                  border:"1px solid var(--line)", borderRadius:8, padding:12,
                  background: skipped
                    ? "var(--bg-0)"
                    : isObjective
                      ? (isCorrect ? "rgba(16,185,129,0.05)" : "rgba(230,57,70,0.05)")
                      : (teacherScore != null
                          ? (Number(teacherScore) >= Number(q.marks) ? "rgba(16,185,129,0.05)" : "rgba(255,182,39,0.05)")
                          : "rgba(255,182,39,0.04)"),
                }}>
                  <div style={{ display:"flex", alignItems:"center", gap:8, marginBottom:6 }}>
                    <span className="mono" style={{ fontSize:10, color:"var(--ink-3)", letterSpacing:".1em", textTransform:"uppercase" }}>
                      Q{q.q_no} · {q.marks} mark{Number(q.marks) === 1 ? "" : "s"}
                    </span>
                    {skipped ? (
                      <span style={{ fontSize:10, color:"var(--ink-3)", fontFamily:"monospace" }}>Skipped</span>
                    ) : isObjective ? (
                      isCorrect
                        ? <span style={{ fontSize:10, color:KX_EMERALD, fontFamily:"monospace" }}>✓ Correct</span>
                        : <span style={{ fontSize:10, color:KX_MADDER, fontFamily:"monospace" }}>✗ Wrong</span>
                    ) : teacherScore != null ? (
                      <span style={{ fontSize:10, color:KX_EMERALD, fontFamily:"monospace" }}>
                        Graded {teacherScore}/{q.marks}
                      </span>
                    ) : (
                      <span style={{ fontSize:10, color:KX_AMBER, fontFamily:"monospace" }}>Needs grading</span>
                    )}
                  </div>
                  <div style={{ color:"var(--ink-0)", fontSize:13, marginBottom:8 }}>{q.text}</div>
                  {q.images?.question?.length ? (
                    <div style={{ display:"flex", flexWrap:"wrap", gap:6, marginBottom:8 }}>
                      {q.images.question.map((src, i) => (
                        <img key={i} src={src} alt={`Question figure ${i+1}`}
                             style={{ maxHeight:140, borderRadius:6, border:"1px solid var(--line)", background:"#fff" }}
                             loading="lazy"/>
                      ))}
                    </div>
                  ) : null}

                  {isObjective ? (
                    <div style={{ display:"grid", gap:4 }}>
                      {q.options.map(o => {
                        const isPicked = picked?.id === o.id;
                        const correctish = o.is_correct;
                        let bg = "var(--bg-0)", border = "var(--line)", color = "var(--ink-2)";
                        if (correctish) { bg = "rgba(16,185,129,0.12)"; border = "rgba(16,185,129,0.4)"; color = "#a7f3d0"; }
                        if (isPicked && !correctish) { bg = "rgba(230,57,70,0.12)"; border = "rgba(230,57,70,0.4)"; color = "#fda4af"; }
                        return (
                          <div key={o.id} style={{
                            fontSize:12, padding:"6px 10px", borderRadius:5,
                            background: bg, border: `1px solid ${border}`, color,
                            display:"flex", alignItems:"center", gap:8,
                          }}>
                            <span className="mono" style={{ fontSize:10, width:14 }}>{o.letter}.</span>
                            <span style={{ flex:1 }}>{o.text}</span>
                            {o.image && (
                              <img src={o.image} alt={`Option ${o.letter}`}
                                   style={{ maxHeight:32, borderRadius:4, border:"1px solid var(--line)", background:"#fff" }}
                                   loading="lazy"/>
                            )}
                            {isPicked && <span className="mono" style={{ fontSize:9, opacity:0.7 }}>STUDENT</span>}
                            {correctish && <span className="mono" style={{ fontSize:9, opacity:0.7 }}>CORRECT</span>}
                          </div>
                        );
                      })}
                    </div>
                  ) : (
                    /* Descriptive: photo answers from the student + a manual
                       score input below. The score patch hits the same teacher
                       endpoint the mobile uses (online-tests/attempts/:id/responses/:qid/score). */
                    <DescriptiveResponseBlock
                      attemptId={data.attempt.id}
                      questionId={q.id}
                      maxMarks={Number(q.marks)}
                      photos={photos}
                      textAnswer={resp?.textAnswer}
                      teacherScore={teacherScore}
                      teacherFeedback={resp?.teacherFeedback}
                      onSaved={() => {
                        // Re-fetch the detail so the score chip updates.
                        window.KXApi.get(`/tests/${test.id}/students/${student.student_id}/attempt`)
                          .then(setData).catch(() => {});
                      }}
                    />
                  )}

                  {q.images?.solution?.length ? (
                    <div style={{ marginTop:10, paddingTop:10, borderTop:"1px dashed var(--line)" }}>
                      <div style={{ fontSize:10, color:"var(--ink-3)", fontFamily:"monospace",
                                    letterSpacing:".1em", textTransform:"uppercase", marginBottom:6 }}>
                        Solution figures
                      </div>
                      <div style={{ display:"flex", flexWrap:"wrap", gap:6 }}>
                        {q.images.solution.map((src, i) => (
                          <img key={i} src={src} alt={`Solution figure ${i+1}`}
                               style={{ maxHeight:160, borderRadius:6, border:"1px solid var(--line)", background:"#fff" }}
                               loading="lazy"/>
                        ))}
                      </div>
                    </div>
                  ) : null}
                </div>
              );
            })
          )}
        </div>

        <div style={{ padding:12, borderTop:"1px solid var(--line)", display:"flex", gap:8, justifyContent:"flex-end" }}>
          <button className="btn sm" onClick={onClose}>Close</button>
        </div>
      </div>
    </div>
  );
};

/* ──────────────────────────────────────────────────────────────────
   Descriptive answer block — shown inside the detail modal for any
   non-MCQ question. Renders the student's photo uploads and a manual
   scoring form. PATCHes the same teacher scoring endpoint the mobile
   uses, then triggers onSaved so the parent can refresh.
   ────────────────────────────────────────────────────────────────── */

const DescriptiveResponseBlock = ({
  attemptId, questionId, maxMarks, photos, textAnswer,
  teacherScore, teacherFeedback, onSaved,
}) => {
  const [score, setScore] = React.useState(teacherScore != null ? String(teacherScore) : "");
  const [feedback, setFeedback] = React.useState(teacherFeedback || "");
  const [saving, setSaving] = React.useState(false);
  const [savedAt, setSavedAt] = React.useState(0);
  const [err, setErr] = React.useState("");

  const save = async () => {
    const n = Number(score);
    if (!Number.isFinite(n) || n < 0 || n > maxMarks) {
      setErr(`Score must be between 0 and ${maxMarks}`);
      return;
    }
    setErr(""); setSaving(true);
    try {
      await window.KXApi.patch(
        `/online-tests/attempts/${attemptId}/responses/${questionId}/score`,
        { teacher_score: n, teacher_feedback: feedback || null },
      );
      setSavedAt(Date.now());
      onSaved && onSaved();
    } catch (e) {
      setErr(e?.message || "Save failed");
    } finally {
      setSaving(false);
    }
  };

  return (
    <div style={{ display:"flex", flexDirection:"column", gap:10 }}>
      <div>
        <div style={{ fontSize:10, color:"var(--ink-3)", fontFamily:"monospace",
                      letterSpacing:".1em", textTransform:"uppercase", marginBottom:6 }}>
          Student submission
        </div>
        {photos.length === 0 && !textAnswer ? (
          <div style={{ fontSize:12, color:"var(--ink-3)", fontStyle:"italic" }}>No answer submitted.</div>
        ) : (
          <>
            {photos.length > 0 && (
              <div style={{ display:"grid", gridTemplateColumns:"repeat(auto-fill,minmax(160px,1fr))", gap:6 }}>
                {photos.map((src, i) => (
                  <a key={i} href={src} target="_blank" rel="noopener noreferrer"
                     style={{ display:"block", borderRadius:6, overflow:"hidden",
                              border:"1px solid var(--line)", background:"#000" }}>
                    <img src={src} alt={`Answer photo ${i+1}`}
                         style={{ width:"100%", height:160, objectFit:"contain", display:"block" }}/>
                  </a>
                ))}
              </div>
            )}
            {textAnswer && (
              <div style={{ marginTop:6, padding:"6px 10px", border:"1px solid var(--line)",
                            borderRadius:5, background:"var(--bg-0)", fontSize:12, color:"var(--ink-1)",
                            whiteSpace:"pre-wrap" }}>
                {textAnswer}
              </div>
            )}
          </>
        )}
      </div>

      <div style={{ display:"grid", gridTemplateColumns:"110px 1fr 110px", gap:8, alignItems:"flex-end" }}>
        <label style={{ display:"flex", flexDirection:"column", gap:4 }}>
          <span style={{ fontSize:10, color:"var(--ink-3)", letterSpacing:".08em",
                         textTransform:"uppercase", fontFamily:"monospace" }}>Score</span>
          <input type="number" step={0.5} min={0} max={maxMarks} value={score}
                 onChange={(e) => setScore(e.target.value)}
                 placeholder={`/${maxMarks}`}
                 style={{ background:"var(--bg-0)", border:"1px solid var(--line)",
                          borderRadius:5, padding:"6px 8px", color:"var(--ink-0)", fontSize:12, width:"100%", boxSizing:"border-box" }}/>
        </label>
        <label style={{ display:"flex", flexDirection:"column", gap:4 }}>
          <span style={{ fontSize:10, color:"var(--ink-3)", letterSpacing:".08em",
                         textTransform:"uppercase", fontFamily:"monospace" }}>Feedback (optional)</span>
          <input type="text" value={feedback} onChange={(e) => setFeedback(e.target.value)}
                 style={{ background:"var(--bg-0)", border:"1px solid var(--line)",
                          borderRadius:5, padding:"6px 8px", color:"var(--ink-0)", fontSize:12, width:"100%", boxSizing:"border-box" }}/>
        </label>
        <button className="btn sm primary" disabled={saving || score === ""}
                onClick={save}
                style={{ background: KX_COBALT, borderColor: KX_COBALT, opacity: (saving || score === "") ? 0.5 : 1 }}>
          {saving ? "Saving…" : Date.now() - savedAt < 1500 ? "Saved" : "Save score"}
        </button>
      </div>
      {err && <div style={{ fontSize:11, color:"var(--red)" }}>{err}</div>}
    </div>
  );
};

window.OnlineSubmissionsModal = OnlineSubmissionsModal;
window.OnlineSubmissionDetailModal = OnlineSubmissionDetailModal;
