/* view_report.jsx — end-to-end session report */

const PHASES = [
  { name: "Soundcheck", t: "09:02", w: 14, health: "low",  note: "Levels set, CH 11 noisy initially" },
  { name: "Praise",     t: "09:18", w: 22, health: "good", note: "Stable, balanced mix" },
  { name: "Worship",    t: "09:46", w: 24, health: "warn", note: "Loudness ran hot near peak" },
  { name: "Prayer",     t: "10:18", w: 16, health: "good", note: "Clean, spoken-word clarity good" },
  { name: "Sermon",     t: "10:40", w: 18, health: "good", note: "Steady, low noise floor" },
  { name: "Close",      t: "11:02", w: 6,  health: "good", note: "Smooth fade-out" },
];
const PHASE_COLOR = { good: "var(--grade-good)", low: "var(--grade-low)", warn: "var(--grade-warn)", high: "var(--grade-high)" };
const TL_EVENTS = [
  { at: 9,  grade: "high", label: "CH 11 clip" },
  { at: 52, grade: "warn", label: "Loudness +2dB" },
  { at: 60, grade: "high", label: "Master clip" },
  { at: 78, grade: "warn", label: "Isy mic low" },
];

function cleanPdfText(value) {
  return String(value == null ? "" : value).replace(/[—–·]/g, "-");
}

function pdfGradeText(cell) {
  if (!cell) return "-";
  const parts = [String(cell.grade || "").toUpperCase()];
  if (cell.value != null) parts.push(`${cell.value} ${cell.unit || ""}`.trim());
  if (cell.note) parts.push(cell.note);
  return cleanPdfText(parts.filter(Boolean).join(" - "));
}

function exportReportPdf(report) {
  const jsPDF = window.jspdf && window.jspdf.jsPDF;
  if (!jsPDF) {
    alert("PDF export is still loading. Please try again in a few seconds.");
    return;
  }

  const { D, stats, results, operator, viewDate, currentSession, analysisInputLabel } = report;
  const doc = new jsPDF({ orientation: "landscape", unit: "pt", format: "a4" });
  const margin = 36;
  const pageWidth = doc.internal.pageSize.getWidth();
  const title = `${currentSession.name || D.session.name} - ${window.fmtDate(viewDate, { weekday: "long", month: "long", day: "numeric" })}`;
  const fileDate = viewDate || new Date().toISOString().slice(0, 10);
  let y = 42;

  doc.setFont("helvetica", "bold");
  doc.setFontSize(20);
  doc.text(cleanPdfText("RLWC Live Audio Test Report"), margin, y);
  y += 24;
  doc.setFont("helvetica", "normal");
  doc.setFontSize(11);
  doc.text(cleanPdfText(title), margin, y);
  y += 22;

  doc.autoTable({
    startY: y,
    margin: { left: margin, right: margin },
    theme: "grid",
    styles: { font: "helvetica", fontSize: 9, cellPadding: 6, overflow: "linebreak" },
    headStyles: { fillColor: [30, 64, 175], textColor: 255 },
    head: [["Operator", "Tests Complete", "Pass Rate", "Health", "Clips", "Issues", "Analysis Input", "Sample Rate"]],
    body: [[
      operator || currentSession.operator || "Unassigned",
      `${stats.done} / ${stats.total}`,
      `${stats.passRate}%`,
      `${stats.health}%`,
      String(stats.high),
      String(stats.issues.length),
      analysisInputLabel || "No input selected",
      D.session.sampleRate || "",
    ].map(cleanPdfText)],
  });
  y = doc.lastAutoTable.finalY + 18;

  doc.setFont("helvetica", "bold");
  doc.setFontSize(13);
  doc.text("Issues Found", margin, y);
  y += 8;
  const issueRows = stats.issues.length
    ? stats.issues.map(iss => [
        String(iss.grade || "").toUpperCase(),
        iss.group,
        iss.item,
        iss.crit,
        iss.note,
        `${iss.value || ""} ${iss.unit || ""}`.trim(),
      ].map(cleanPdfText))
    : [["-", "-", "No issues recorded", "-", "-", "-"]];
  doc.autoTable({
    startY: y,
    margin: { left: margin, right: margin },
    theme: "striped",
    styles: { font: "helvetica", fontSize: 8.5, cellPadding: 5, overflow: "linebreak" },
    headStyles: { fillColor: [17, 24, 39], textColor: 255 },
    head: [["Severity", "Group", "Item", "Criterion", "Note", "Value"]],
    body: issueRows,
    columnStyles: { 0: { cellWidth: 60 }, 1: { cellWidth: 105 }, 2: { cellWidth: 170 }, 3: { cellWidth: 100 }, 5: { cellWidth: 75 } },
  });
  y = doc.lastAutoTable.finalY + 20;

  D.groups.forEach(group => {
    if (y > doc.internal.pageSize.getHeight() - 110) {
      doc.addPage();
      y = 42;
    }
    doc.setFont("helvetica", "bold");
    doc.setFontSize(13);
    doc.text(cleanPdfText(group.title), margin, y);
    y += 8;

    const criteria = group.items[0]?.criteria || [];
    let head;
    let body;
    if (group.kind === "matrix") {
      head = [["Item", "Song"].concat(criteria)];
      body = [];
      group.items.forEach(item => {
        item.songs.forEach(song => {
          const r = results[runKey(item, song)];
          body.push([item.name, song].concat(criteria.map(c => pdfGradeText(r && r.cells && r.cells[c]))).map(cleanPdfText));
        });
      });
    } else {
      head = [["Item"].concat(criteria)];
      body = group.items.map(item => {
        const r = results[runKey(item, null)];
        return [item.name].concat(criteria.map(c => pdfGradeText(r && r.cells && r.cells[c]))).map(cleanPdfText);
      });
    }

    doc.autoTable({
      startY: y,
      margin: { left: margin, right: margin },
      theme: "grid",
      styles: { font: "helvetica", fontSize: 7.5, cellPadding: 4, overflow: "linebreak" },
      headStyles: { fillColor: [30, 41, 59], textColor: 255 },
      alternateRowStyles: { fillColor: [248, 250, 252] },
      head,
      body,
      didDrawPage: data => {
        const page = doc.internal.getNumberOfPages();
        doc.setFont("helvetica", "normal");
        doc.setFontSize(8);
        doc.text(`RLWC Live Audio Test - Page ${page}`, pageWidth - margin, doc.internal.pageSize.getHeight() - 18, { align: "right" });
      },
    });
    y = doc.lastAutoTable.finalY + 20;
  });

  doc.save(`RLWC-Audio-Test-Report-${fileDate}.pdf`);
}

function ReportTimeline() {
  return (
    <div className="timeline">
      <div className="tl-track">
        {PHASES.map((p, i) => (
          <div className="tl-seg" key={i} style={{ flex: p.w, background: `linear-gradient(180deg, ${PHASE_COLOR[p.health]}22, ${PHASE_COLOR[p.health]}0c)` }}>
            <div style={{ position: "absolute", top: 6, left: 0, right: 0, height: 3, background: PHASE_COLOR[p.health], opacity: .9 }} />
            <div style={{ padding: "12px 10px 0", fontSize: 11.5, fontWeight: 700, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{p.name}</div>
            <div style={{ padding: "1px 10px", fontSize: 10, color: "var(--fg-3)", fontFamily: "var(--mono)" }}>{p.t}</div>
          </div>
        ))}
        {TL_EVENTS.map((e, i) => (
          <div key={i} className="tl-marker" style={{ left: `${e.at}%`, background: PHASE_COLOR[e.grade] }} title={e.label}>
            <span style={{ position: "absolute", top: -2, left: -3, width: 8, height: 8, borderRadius: 999, background: PHASE_COLOR[e.grade] }} />
          </div>
        ))}
      </div>
      <div className="tl-axis">
        <span className="dim mono">09:02 · start</span>
        <span className="dim">Initial → End · how the system behaved through the service</span>
        <span className="dim mono">11:08 · end</span>
      </div>
      <div className="grid" style={{ gridTemplateColumns: "repeat(auto-fit, minmax(150px,1fr))", marginTop: 16 }}>
        {PHASES.map((p, i) => (
          <div key={i} style={{ display: "flex", gap: 9, alignItems: "flex-start" }}>
            <span style={{ width: 8, height: 8, borderRadius: 999, marginTop: 5, flex: "0 0 auto", background: PHASE_COLOR[p.health] }} />
            <div>
              <div style={{ fontSize: 12.5, fontWeight: 700 }}>{p.name}</div>
              <div className="dim" style={{ fontSize: 11.5, lineHeight: 1.4 }}>{p.note}</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function ReportGroup({ group }) {
  const { results } = useQA();
  const crit = group.items[0].criteria;
  if (group.kind === "matrix") {
    return (
      <div className="dev-grid">
        {group.items.map(item => {
          const tested = item.songs.filter(s => results[runKey(item, s)]);
          return (
            <div className="dev-card" key={item.id}>
              <div className="dev-head">
                <div className="dev-name">{item.name}</div>
                <span className="dim mono" style={{ fontSize: 12 }}>{tested.length}/{item.songs.length} songs</span>
              </div>
              <div className="matrix" style={{ gridTemplateColumns: `minmax(110px,1.2fr) repeat(${item.songs.length}, 1fr)` }}>
                <div className="thead corner">Criteria</div>
                {item.songs.map(s => <div className="thead song" key={s}>{s}</div>)}
                {item.criteria.map(c => (
                  <React.Fragment key={c}>
                    <div className="crit-label">{c}</div>
                    {item.songs.map(s => {
                      const r = results[runKey(item, s)];
                      return <div className="tcell" key={s}>{r ? <GradeChip grade={r.cells[c].grade} /> : <span className="dim mono">—</span>}</div>;
                    })}
                  </React.Fragment>
                ))}
              </div>
            </div>
          );
        })}
      </div>
    );
  }
  return (
    <div className="rowtable-wrap">
      <div className="report-table" style={{ gridTemplateColumns: `minmax(180px,1.6fr) repeat(${crit.length}, 1fr)` }}>
        <div className="thead">{group.title}</div>
        {crit.map(c => <div className="thead" key={c} style={{ borderLeft: "1px solid var(--line)" }}>{c}</div>)}
        {group.items.map(item => {
          const r = results[runKey(item, null)];
          return (
            <React.Fragment key={item.id}>
              <div className="rt-name">
                {r && <GradeChip grade={r.overall} />}
                <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{item.name}</span>
              </div>
              {crit.map(c => (
                <div className="rt-cell" key={c}>
                  {r ? <GradeChip grade={r.cells[c].grade} /> : <span className="dim mono">—</span>}
                  {r && (r.cells[c].grade === "warn" || r.cells[c].grade === "high") && <span className="cell-note">{r.cells[c].note}</span>}
                </div>
              ))}
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}

function ReportView() {
  const D = window.QA_DATA;
  const { stats, runAll, queue, operator, viewDate, currentSession, analysisInputLabel, results } = useQA();
  const empty = stats.done === 0;
  const shownOperator = operator || currentSession.operator || "Unassigned";
  const exportPdf = () => exportReportPdf({ D, stats, results, operator, viewDate, currentSession, analysisInputLabel });

  return (
    <div className="page fade-up">
      <div className="page-head">
        <div>
          <div className="eyebrow">End-to-end session report</div>
          <h2>{currentSession.name || D.session.name} · {window.fmtDate(viewDate, { weekday: "long", month: "long", day: "numeric" })}</h2>
          <p>Auto-compiled from every test run during the service.</p>
        </div>
        <div className="row gap-sm">
          <button className="btn ghost" onClick={exportPdf}><Icon name="download" size={15} />Export PDF</button>
          {empty && (
            <button className="btn primary" onClick={() => runAll(true)} disabled={!!queue}>
              <Icon name="play" size={15} fill="currentColor" />
              {queue ? `Simulating ${queue.done}/${queue.total}…` : "Simulate full session"}
            </button>
          )}
        </div>
      </div>

      {empty ? (
        <Panel style={{ textAlign: "center", padding: "60px 20px" }}>
          <div style={{ color: "var(--fg-3)", marginBottom: 14 }}><Icon name="report" size={42} /></div>
          <h3 style={{ margin: "0 0 6px" }}>No tests recorded yet</h3>
          <p className="dim" style={{ maxWidth: 420, margin: "0 auto" }}>Run items from the Test Checklist for this Sunday and person.</p>
        </Panel>
      ) : (
        <React.Fragment>
          <div className="grid" style={{ gridTemplateColumns: "1fr", marginBottom: 16 }}>
            <Panel>
              <div className="report-hero">
                <RingGauge value={stats.health} size={150} sub="Health" />
                <div className="report-meta">
                  {[
                    ["Operator",       shownOperator],
                    ["Duration",       "02:06:14"],
                    ["Tests complete", `${stats.done} / ${stats.total}`],
                    ["Pass rate",      `${stats.passRate}%`],
                    ["Clips detected", String(stats.high)],
                    ["Issues flagged", String(stats.issues.length)],
                    ["Analysis input", analysisInputLabel || "No input selected"],
                    ["Sample rate",    D.session.sampleRate],
                  ].map(([l, v]) => (
                    <div key={l}><div className="rm-label">{l}</div><div className="rm-val">{v}</div></div>
                  ))}
                </div>
              </div>
            </Panel>
          </div>

          <Panel title="Service Timeline" icon="trend" info style={{ marginBottom: 16 }}>
            <ReportTimeline />
          </Panel>

          <div className="grid" style={{ gridTemplateColumns: "1fr 1fr", marginBottom: 16 }}>
            <Panel title="Issues Found" icon="alert">
              {stats.issues.length === 0 ? <p className="dim">No issues — clean session.</p> : (
                <div>
                  {stats.issues.slice(0, 8).map((iss, i) => (
                    <div className="issue-row" key={i}>
                      <GradeChip grade={iss.grade} />
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div className="issue-name">{iss.item}</div>
                        <div className="issue-sub">{iss.group} · {iss.crit} — {iss.note}</div>
                      </div>
                      <span className="mono dim" style={{ fontSize: 12 }}>{iss.value} {iss.unit}</span>
                    </div>
                  ))}
                </div>
              )}
            </Panel>
            <Panel title="Auto Summary" icon="report">
              <p style={{ marginTop: 0, lineHeight: 1.7 }}>
                The system graded <b>{stats.cells}</b> measurements across <b>{stats.done}</b> tests.
                <b style={{ color: "var(--grade-good)" }}> {stats.passRate}%</b> passed in range.
                {stats.high > 0 && <span> <b style={{ color: "var(--grade-high)" }}>{stats.high}</b> ran hot / clipped — concentrated early in soundcheck and during worship peaks.</span>}
                {stats.low > 0 && <span> <b style={{ color: "var(--grade-low)" }}>{stats.low}</b> read low and would benefit from a few dB of gain.</span>}
              </p>
              <div className="readout">
                <div className="readout-row"><span className="rlabel">Strongest section</span><span className="rval" style={{ color: "var(--grade-good)", fontSize: 14 }}>Prayer / Sermon</span></div>
                <div className="readout-row"><span className="rlabel">Weakest section</span><span className="rval" style={{ color: "var(--grade-warn)", fontSize: 14 }}>Worship peaks</span></div>
                <div className="readout-row"><span className="rlabel">Recommended next time</span><span className="rval" style={{ fontSize: 13, color: "var(--fg-1)" }}>Ride CH 11 gain</span></div>
              </div>
            </Panel>
          </div>

          {D.groups.map(g => (
            <div className="grp" key={g.id}>
              <div className="grp-head"><h3 className="grp-title">{g.title}</h3><span className="dim">{g.desc}</span></div>
              <ReportGroup group={g} />
            </div>
          ))}
        </React.Fragment>
      )}
    </div>
  );
}

Object.assign(window, { ReportView });
