// STEP 4 — Live Progress Monitor
const { useState: useState4, useEffect: useEffect4, useMemo: useMemo4, useRef: useRef4, useCallback: useCallback4 } = React;

// Map DB section state strings → UI display states
function mapSectionState(dbState) {
  if (!dbState) return "queued";
  const s = dbState.toString().toUpperCase();
  if (s === "COMPLETED" || s === "SKIPPED") return "done";
  if (s === "RUNNING" || s === "RETRYING") return "generating";
  if (s === "FAILED" || s === "CANCELLED") return "error";
  return "queued"; // READY, PENDING
}

function Step4Progress({ title, sections, sectionStates, initialPdfUrl, onNewReport, onBackToIndex, onOpenDiagrams, reportVersionId, onGeneratePdf, onStartGeneration, onGetSectionContent, onDeleteSection, onSync }) {
  const [statuses, setStatuses] = useState4(() =>
    sections.map((s) => sectionStates?.[s.id] ? mapSectionState(sectionStates[s.id]) : "queued")
  );
  const [elapsed, setElapsed] = useState4(0);
  const [running, setRunning] = useState4(true);
  const startedAt = useRef4(Date.now());
  const [pdfUrl, setPdfUrl] = useState4(initialPdfUrl || null);
  const [pdfGenerating, setPdfGenerating] = useState4(false);
  const [startingGeneration, setStartingGeneration] = useState4(false);

  // Content viewer state
  const [contentModal, setContentModal] = useState4(null); // { section, markdown, loading }

  // Update statuses whenever poll data arrives.
  // Sections with no job entry in sectionStates are parent chapters → treat as done.
  useEffect4(() => {
    if (!sectionStates || Object.keys(sectionStates).length === 0) return;
    setStatuses(sections.map((s) => {
      if (sectionStates[s.id]) return mapSectionState(sectionStates[s.id]);
      return "done"; // parent section with no workflow job
    }));
  }, [sectionStates]);

  // Reset PDF URL whenever the report changes
  useEffect4(() => {
    setPdfUrl(initialPdfUrl || null);
  }, [reportVersionId, initialPdfUrl]);

  const handleDownloadPdf = async () => {
    if (pdfUrl) { window.open(pdfUrl, "_blank"); return; }
    if (!onGeneratePdf || !reportVersionId) return;
    setPdfGenerating(true);
    try {
      const result = await onGeneratePdf(reportVersionId);
      const data = result?.data || result;
      const url = data?.download_url || data?.pdf_download_url || data?.sample_pdf_download_url;
      if (url) { setPdfUrl(url); window.open(url, "_blank"); }
    } catch (_) {}
    finally { setPdfGenerating(false); }
  };

  const handleStartGeneration = async () => {
    if (!onStartGeneration || !reportVersionId) return;
    setStartingGeneration(true);
    try {
      await onStartGeneration(reportVersionId);
    } catch (_) {}
    finally { setStartingGeneration(false); }
  };

  const handleSectionClick = useCallback4(async (section, status) => {
    if (status !== "done" || !onGetSectionContent || !reportVersionId || !section.id) return;
    setContentModal({ section, markdown: null, loading: true });
    try {
      const data = await onGetSectionContent(reportVersionId, section.id);
      setContentModal({ section, markdown: data.content_markdown, loading: false });
    } catch (_) {
      setContentModal({ section, markdown: null, loading: false, error: true });
    }
  }, [onGetSectionContent, reportVersionId]);

  // Tick clock while generating
  useEffect4(() => {
    if (!running) return;
    const id = setInterval(() => setElapsed(Math.floor((Date.now() - startedAt.current) / 1000)), 1000);
    return () => clearInterval(id);
  }, [running]);

  const stats = useMemo4(() => {
    const total = sections.length;
    const complete = statuses.filter(s => s === "done").length;
    const errored = statuses.filter(s => s === "error").length;
    const inFlight = statuses.filter(s => s === "generating").length;
    const isComplete = complete + errored === total;
    if (isComplete && running) setRunning(false);
    const words = Math.round(complete * 380 * 0.95 + inFlight * 200);
    const eta = inFlight + (total - complete - inFlight - errored) > 0
      ? Math.max(1, Math.round((total - complete - errored) * 0.85))
      : 0;
    return { total, complete, errored, inFlight, isComplete, words, eta };
  }, [statuses, sections.length]);

  const pct = stats.total > 0 ? Math.round((stats.complete / stats.total) * 100) : 0;

  const shortVersionId = reportVersionId ? reportVersionId.slice(0, 8) : "—";

  return (
    <div className="max-w-[1180px] mx-auto px-8 pb-10 fade-up relative">
      {stats.isComplete && <Confetti/>}

      {/* Content viewer modal */}
      {contentModal && (
        <ContentModal
          section={contentModal.section}
          markdown={contentModal.markdown}
          loading={contentModal.loading}
          error={contentModal.error}
          onClose={() => setContentModal(null)}/>
      )}

      {/* Header */}
      <div className="flex items-start justify-between gap-6 mb-5">
        <div className="min-w-0">
          <div className="mono text-[11px] uppercase tracking-[0.18em] text-teal-700 mb-2 flex items-center gap-2">
            Step 04 / Generation
            <span className="mono text-[10px] px-1.5 py-0.5 rounded bg-ink-100 text-ink-600 border border-ink-200">v1.0</span>
            {stats.isComplete ? (
              <span className="mono text-[10px] px-1.5 py-0.5 rounded bg-emerald-50 text-emerald-700 border border-emerald-200 inline-flex items-center gap-1">
                <span className="h-1 w-1 rounded-full bg-emerald-500"/> Complete
              </span>
            ) : (
              <span className="mono text-[10px] px-1.5 py-0.5 rounded bg-teal-50 text-teal-700 border border-teal-100 inline-flex items-center gap-1">
                <span className="h-1 w-1 rounded-full bg-teal-500 animate-pulse"/> Live
              </span>
            )}
          </div>
          <h1 className="text-[22px] font-semibold tracking-tight text-ink-900 truncate">{title}</h1>
          <div className="mono text-[11px] text-ink-400 mt-1">
            version_id <span className="text-ink-700">{shortVersionId}</span> · started <span className="text-ink-700">{fmtTimeAgo(elapsed)}</span> ago
          </div>
        </div>

        <div className="shrink-0 flex items-center gap-2">
          {onOpenDiagrams && (
            <button onClick={onOpenDiagrams} className="h-9 px-3 inline-flex items-center gap-1.5 text-[12.5px] text-ink-700 border border-ink-200 rounded-md hover:bg-teal-50/40 hover:border-teal-400">
              <Icons.Image size={13} className="text-teal-600"/> Diagrams
            </button>
          )}
          <button onClick={onSync} className="h-9 px-3 inline-flex items-center gap-1.5 text-[12.5px] text-ink-600 border border-ink-200 rounded-md hover:bg-ink-50">
            <Icons.Refresh size={13}/> Sync
          </button>
          <button onClick={onBackToIndex} className="h-9 px-3 inline-flex items-center gap-1.5 text-[12.5px] text-ink-600 border border-ink-200 rounded-md hover:bg-ink-50">
            <Icons.ArrowLeft size={13}/> Back to Index
          </button>
        </div>
      </div>

      {/* Overall progress */}
      <div className="bg-white border border-ink-100 rounded-xl shadow-card p-5 mb-4">
        <div className="flex items-end justify-between mb-3">
          <div>
            <div className="mono text-[10px] uppercase tracking-wider text-ink-500">Overall progress</div>
            <div className="flex items-baseline gap-2 mt-1">
              <span className="mono text-[34px] font-semibold tabular-nums text-ink-900 leading-none">{pct}%</span>
              <span className="mono text-[13px] text-ink-400 tabular-nums">{stats.complete} / {stats.total} sections</span>
            </div>
          </div>
          <div className="flex items-center gap-5">
            <MiniStat label="Elapsed" value={fmtClock(elapsed)} icon={<Icons.Clock size={11}/>}/>
            <MiniStat label="ETA" value={stats.isComplete ? "—" : `~${stats.eta} min`} icon={<Icons.Hourglass size={11}/>}/>
            <MiniStat label="In flight" value={stats.inFlight} icon={<Icons.Loader size={11} className={stats.inFlight > 0 ? "spin-slow" : ""}/>}/>
          </div>
        </div>

        {/* Segmented progress bar */}
        <div className="flex items-center gap-[2px] h-2.5">
          {statuses.map((s, i) => (
            <div key={i} className={`flex-1 rounded-sm transition-colors duration-500
              ${s === "done" ? "bg-teal-500" : ""}
              ${s === "generating" ? "bg-teal-300 animate-pulse" : ""}
              ${s === "queued" ? "bg-ink-100" : ""}
              ${s === "error" ? "bg-red-400" : ""}`}/>
          ))}
        </div>
      </div>

      <div className="grid grid-cols-[1fr_320px] gap-4">
        {/* Section list */}
        <div className="bg-white border border-ink-100 rounded-xl shadow-card overflow-hidden">
          <div className="px-4 py-2.5 border-b border-ink-100 flex items-center justify-between bg-ink-50/40">
            <div className="mono text-[11px] uppercase tracking-wider text-ink-500">Sections</div>
            <div className="flex items-center gap-3">
              <LegendDot color="bg-teal-500" label="Done"/>
              <LegendDot color="bg-teal-300" label="Generating" pulse/>
              <LegendDot color="bg-ink-200" label="Queued"/>
              <LegendDot color="bg-red-400" label="Error"/>
            </div>
          </div>
          <div className="max-h-[520px] overflow-y-auto nice-scroll">
            {sections.map((s, i) => (
              <SectionRow
                key={s.num}
                section={s}
                status={statuses[i]}
                onClick={() => handleSectionClick(s, statuses[i])}
                onDelete={onDeleteSection ? () => onDeleteSection(s.id) : null}/>
            ))}
          </div>
        </div>

        {/* Right stats */}
        <div className="space-y-3.5">
          <div className="bg-white border border-ink-100 rounded-xl shadow-card p-4">
            <div className="mono text-[10px] uppercase tracking-wider text-ink-500 mb-3">Live stats</div>
            <BigStat label="Sections complete" value={`${stats.complete} / ${stats.total}`}/>
            <Divider/>
            <BigStat label="Words generated" value={`~${stats.words.toLocaleString()}`}/>
            <Divider/>
            <BigStat label="Time elapsed" value={fmtClock(elapsed)} mono/>
            <Divider/>
            <BigStat label="Estimated remaining" value={stats.isComplete ? "—" : `~${stats.eta} min`} mono/>
          </div>

          {stats.errored > 0 && (
            <div className="bg-red-50 border border-red-200 rounded-xl p-4">
              <div className="flex items-center gap-2 text-red-700 text-[12.5px] font-medium mb-1">
                <Icons.CircleAlert size={14}/> {stats.errored} section failed
              </div>
              <div className="text-[12px] text-red-700/80 leading-relaxed">
                We'll retry automatically. You can also <button className="underline underline-offset-2 font-medium">retry now</button>.
              </div>
            </div>
          )}

          {stats.isComplete ? (
            <div className="bg-gradient-to-br from-emerald-500 to-teal-600 rounded-xl p-4 text-white">
              <div className="mono text-[10px] uppercase tracking-wider opacity-80 mb-1">Generation complete</div>
              <div className="text-[14px] mb-3 leading-snug">Your report is ready. {stats.errored > 0 && `${stats.errored} section${stats.errored>1?"s":""} failed and ${stats.errored>1?"were":"was"} marked for retry.`}</div>
              <div className="flex flex-col gap-2">
                <button onClick={handleDownloadPdf} disabled={pdfGenerating} className="h-9 inline-flex items-center justify-center gap-2 bg-white text-emerald-700 text-[12.5px] font-medium rounded-md hover:bg-emerald-50 disabled:opacity-60">
                  {pdfGenerating ? <Icons.Loader size={14} className="spin-slow"/> : <Icons.Download size={14}/>}
                  {pdfGenerating ? "Generating…" : "Download PDF"}
                </button>
                <button onClick={() => pdfUrl && window.open(pdfUrl, "_blank")} disabled={!pdfUrl} className="h-9 inline-flex items-center justify-center gap-2 bg-white/15 hover:bg-white/25 text-white text-[12.5px] font-medium rounded-md ring-1 ring-inset ring-white/20 disabled:opacity-50">
                  <Icons.Eye size={14}/> View report
                </button>
              </div>
            </div>
          ) : (
            <div className="bg-white border border-ink-100 rounded-xl p-4">
              <div className="mono text-[10px] uppercase tracking-wider text-ink-500 mb-2">Agents</div>
              <div className="space-y-2">
                {["Research Analyst", "Market Sizing", "Competitive", "Forecasting"].map((a, i) => (
                  <div key={a} className="flex items-center gap-2.5">
                    <div className={`h-6 w-6 rounded-md grid place-items-center text-[10px] mono font-semibold ${i < stats.inFlight ? "bg-teal-100 text-teal-700" : "bg-ink-100 text-ink-400"}`}>
                      A{i + 1}
                    </div>
                    <div className="flex-1 text-[12px] text-ink-700">{a}</div>
                    <div className={`mono text-[10px] ${i < stats.inFlight ? "text-teal-700" : "text-ink-400"}`}>
                      {i < stats.inFlight ? "working" : "idle"}
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}

          <button
            onClick={handleStartGeneration}
            disabled={startingGeneration || stats.isComplete}
            className="w-full h-9 text-[12px] font-medium text-white bg-teal-600 hover:bg-teal-700 disabled:opacity-50 rounded-lg inline-flex items-center justify-center gap-1.5">
            {startingGeneration ? <Icons.Loader size={12} className="spin-slow"/> : <Icons.Sparkles size={12}/>}
            {startingGeneration ? "Starting…" : "Start Content Generation"}
          </button>

          <button onClick={onNewReport} className="w-full h-9 text-[12px] text-ink-500 hover:text-ink-800 inline-flex items-center justify-center gap-1.5">
            <Icons.Plus size={12}/> Start a new report
          </button>
        </div>
      </div>
    </div>
  );
}

function ContentModal({ section, markdown, loading, error, onClose }) {
  const lines = markdown ? markdown.split("\n") : [];

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-ink-900/50 backdrop-blur-sm" onClick={onClose}>
      <div className="bg-white rounded-2xl shadow-2xl w-full max-w-[760px] max-h-[80vh] flex flex-col mx-4" onClick={e => e.stopPropagation()}>
        {/* Modal header */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-ink-100">
          <div>
            <div className="mono text-[10px] uppercase tracking-wider text-ink-400 mb-0.5">{section.num}</div>
            <div className="text-[15px] font-semibold text-ink-900">{section.title}</div>
          </div>
          <button onClick={onClose} className="h-8 w-8 rounded-lg hover:bg-ink-100 grid place-items-center text-ink-400 hover:text-ink-700">
            <Icons.X size={15}/>
          </button>
        </div>

        {/* Modal body */}
        <div className="flex-1 overflow-y-auto nice-scroll px-6 py-5">
          {loading && (
            <div className="flex items-center justify-center py-12 gap-2 text-ink-400">
              <Icons.Loader size={16} className="spin-slow"/> Loading content…
            </div>
          )}
          {error && !loading && (
            <div className="text-center py-12 text-ink-400 text-[13px]">
              Content not yet generated for this section.
            </div>
          )}
          {!loading && !error && markdown && (
            <div className="prose-content text-[13.5px] leading-relaxed text-ink-800">
              {lines.map((line, i) => {
                if (line.startsWith("### ")) return <h3 key={i} className="text-[14px] font-semibold text-ink-900 mt-4 mb-1">{line.slice(4)}</h3>;
                if (line.startsWith("## ")) return <h2 key={i} className="text-[15px] font-bold text-ink-900 mt-5 mb-1.5">{line.slice(3)}</h2>;
                if (line.startsWith("# ")) return <h1 key={i} className="text-[17px] font-bold text-ink-900 mt-6 mb-2">{line.slice(2)}</h1>;
                if (line.startsWith("- ") || line.startsWith("* ")) return <li key={i} className="ml-4 list-disc">{line.slice(2)}</li>;
                if (line.trim() === "") return <div key={i} className="h-3"/>;
                return <p key={i} className="mb-2">{line}</p>;
              })}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function SectionRow({ section, status, onClick, onDelete }) {
  const [hov, setHov] = useState4(false);
  const [confirmDel, setConfirmDel] = useState4(false);
  const isChapter = !section.num.includes(".");
  const rowCls = status === "generating" ? "active-row" : "";
  const clickable = status === "done" && !isChapter;
  return (
    <div
      className={`px-4 py-2 flex items-center gap-3 border-b border-ink-100 last:border-b-0 ${rowCls} ${clickable && !confirmDel ? "cursor-pointer hover:bg-teal-50/40" : ""}`}
      onClick={clickable && !confirmDel ? onClick : undefined}
      onMouseEnter={() => setHov(true)}
      onMouseLeave={() => { setHov(false); setConfirmDel(false); }}>
      <StatusGlyph status={status}/>
      <span className={`mono text-[11px] tabular-nums w-12 ${isChapter ? "text-teal-700 font-semibold" : "text-ink-400"}`}>{section.num}</span>
      <span className={`flex-1 truncate ${isChapter ? "text-[13px] font-semibold text-ink-900" : "text-[12.5px] text-ink-700"}`}>{section.title}</span>
      {hov && onDelete ? (
        confirmDel ? (
          <div className="flex items-center gap-1 shrink-0" onClick={e => e.stopPropagation()}>
            <button onClick={() => onDelete()} className="h-5 px-1.5 text-[10px] font-medium bg-red-500 hover:bg-red-600 text-white rounded">Delete</button>
            <button onClick={() => setConfirmDel(false)} className="h-5 px-1.5 text-[10px] text-ink-500 hover:bg-ink-100 rounded">Cancel</button>
          </div>
        ) : (
          <button onClick={e => { e.stopPropagation(); setConfirmDel(true); }} className="h-5 w-5 grid place-items-center text-ink-300 hover:text-red-500 shrink-0">
            <Icons.Trash2 size={11}/>
          </button>
        )
      ) : (
        <>
          {clickable && <Icons.ChevronRight size={12} className="text-ink-300 shrink-0"/>}
          <span className="mono text-[10.5px] text-ink-400 tabular-nums w-12 text-right">
            {status === "done" ? `${section.est}p` : status === "generating" ? <span className="text-teal-600">…</span> : status === "error" ? <span className="text-red-500">retry</span> : `${section.est}p`}
          </span>
        </>
      )}
    </div>
  );
}

function StatusGlyph({ status }) {
  if (status === "done")
    return <span className="h-5 w-5 rounded-full bg-teal-500 grid place-items-center text-white"><Icons.Check size={12} strokeWidth={3}/></span>;
  if (status === "generating")
    return <span className="h-5 w-5 rounded-full bg-teal-100 grid place-items-center text-teal-700"><Icons.Loader size={11} className="spin-slow"/></span>;
  if (status === "error")
    return <span className="h-5 w-5 rounded-full bg-red-100 grid place-items-center text-red-600"><Icons.X size={11} strokeWidth={2.5}/></span>;
  return <span className="h-5 w-5 rounded-full bg-ink-100 grid place-items-center text-ink-400"><Icons.Hourglass size={11}/></span>;
}

function LegendDot({ color, label, pulse }) {
  return (
    <span className="inline-flex items-center gap-1.5 text-[10.5px] mono uppercase tracking-wider text-ink-500">
      <span className={`h-1.5 w-1.5 rounded-full ${color} ${pulse ? "animate-pulse" : ""}`}/>{label}
    </span>
  );
}

function MiniStat({ label, value, icon }) {
  return (
    <div className="text-right">
      <div className="mono text-[10px] uppercase tracking-wider text-ink-400 inline-flex items-center gap-1 justify-end">{icon} {label}</div>
      <div className="mono text-[13px] font-semibold text-ink-900 tabular-nums">{value}</div>
    </div>
  );
}

function BigStat({ label, value, mono: useMono }) {
  return (
    <div className="py-1">
      <div className="text-[11px] text-ink-500">{label}</div>
      <div className={`text-[17px] font-semibold text-ink-900 tabular-nums leading-tight mt-0.5 ${useMono ? "mono" : "mono"}`}>{value}</div>
    </div>
  );
}

function Divider() { return <div className="h-px bg-ink-100 my-1.5"/>; }

function fmtClock(s) {
  const m = Math.floor(s / 60), sec = s % 60;
  return `${m}:${String(sec).padStart(2, "0")}`;
}
function fmtTimeAgo(s) {
  if (s < 60) return `${s}s`;
  const m = Math.floor(s / 60), sec = s % 60;
  return `${m}m ${sec}s`;
}

// Confetti — colorful pieces falling once
function Confetti() {
  const pieces = useMemo4(() => {
    const colors = ["#17a2b8", "#34b8c9", "#10b981", "#f59e0b", "#ec4899", "#8b5cf6"];
    return Array.from({ length: 70 }, (_, i) => ({
      left: Math.random() * 100,
      delay: Math.random() * 0.4,
      dur: 2.2 + Math.random() * 1.6,
      color: colors[i % colors.length],
      rot: Math.random() * 360,
      w: 6 + Math.random() * 5,
      h: 10 + Math.random() * 8,
    }));
  }, []);
  return (
    <div className="pointer-events-none absolute inset-0 overflow-hidden -m-8">
      {pieces.map((p, i) => (
        <span key={i} className="confetti-piece"
          style={{
            left: `${p.left}%`, background: p.color,
            animationDelay: `${p.delay}s`, animationDuration: `${p.dur}s`,
            width: p.w, height: p.h, transform: `rotate(${p.rot}deg)`,
          }}/>
      ))}
    </div>
  );
}

window.Step4Progress = Step4Progress;
