// Main App — orchestrates the 4-step wizard
const API_BASE = window.API_BASE || "https://generation-console.integermarket.com";

const flattenSections = (nodes, parentNum = "") => {
  const out = [];
  nodes.forEach((n, i) => {
    const num = parentNum ? `${parentNum}.${n.order ?? i + 1}` : String(n.order ?? i + 1);
    out.push({ num, title: n.title, est: Math.max(2, (n.level || 1) * 3), id: n.id });
    if (n.children?.length) out.push(...flattenSections(n.children, num));
  });
  return out;
};

const api = {
  async listReports() {
    const r = await fetch(`${API_BASE}/reports/list`);
    if (!r.ok) throw new Error(await r.text());
    return r.json();
  },
  async suggestTitles(body) {
    const r = await fetch(`${API_BASE}/reports`, {
      method: "POST", headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ topic: body.topic, geography: body.geography, time_period: body.period, depth: body.depth }),
    });
    if (!r.ok) throw new Error(await r.text());
    const data = await r.json();
    return {
      titles: (data.title_options || []).map((t, i) => ({
        title: typeof t === "string" ? t : t.title,
        description: typeof t === "object" ? (t.description || "") : "",
        tag: ["Most Comprehensive", "Sizing-Focused", "Tech Deep-Dive", "Competitive"][i] || "Option",
      })),
    };
  },
  async confirmTitle(body) {
    const r = await fetch(`${API_BASE}/reports/confirm-title`, {
      method: "POST", headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ selected_title: body.title, topic: body.topic }),
    });
    if (!r.ok) throw new Error(await r.text());
    const data = await r.json();
    return { report_version_id: data.report_version_id, report_id: data.report_id, workflow_id: data.workflow_id };
  },
  async getSections(report_version_id) {
    const r = await fetch(`${API_BASE}/reports/version/${report_version_id}/sections`);
    if (!r.ok) throw new Error(await r.text());
    return r.json();
  },
  async startWorkflow(report_version_id) {
    const r = await fetch(`${API_BASE}/workflows/run`, {
      method: "POST", headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ report_version_id }),
    });
    if (!r.ok) throw new Error(await r.text());
    return r.json();
  },
  async getStatus(report_version_id) {
    const r = await fetch(`${API_BASE}/workflows/status/${report_version_id}`);
    if (!r.ok) throw new Error(await r.text());
    return r.json();
  },
  async generatePdf(report_version_id) {
    const r = await fetch(`${API_BASE}/reports/versions/${report_version_id}/generate-pdf`, {
      method: "POST",
    });
    if (!r.ok) throw new Error(await r.text());
    return r.json();
  },
  async getPdfUrl(report_version_id) {
    const r = await fetch(`${API_BASE}/reports/versions/${report_version_id}/download-pdf`);
    if (!r.ok) return null;
    const data = await r.json();
    return data.download_url || null;
  },
  async getSectionContent(report_version_id, section_id) {
    const r = await fetch(`${API_BASE}/reports/versions/${report_version_id}/sections/${section_id}/content`);
    if (!r.ok) throw new Error(await r.text());
    return r.json();
  },
};

const { useState, useEffect, useCallback } = React;

function Toast({ toasts, onDismiss }) {
  return (
    <div className="fixed bottom-5 right-5 z-50 flex flex-col gap-2 w-[320px]">
      {toasts.map((t) => (
        <div key={t.id}
          className={`fade-up px-3.5 py-3 rounded-lg shadow-card-lg flex items-start gap-2.5
            ${t.kind === "error" ? "bg-red-600 text-white" : ""}
            ${t.kind === "success" ? "bg-emerald-600 text-white" : ""}
            ${t.kind === "info" ? "bg-ink-900 text-white" : ""}`}>
          {t.kind === "error"   && <Icons.CircleAlert size={15} className="mt-0.5 shrink-0"/>}
          {t.kind === "success" && <Icons.CircleCheck size={15} className="mt-0.5 shrink-0"/>}
          {t.kind === "info"    && <Icons.Sparkles size={15} className="mt-0.5 shrink-0"/>}
          <div className="flex-1 text-[12.5px] leading-snug">{t.msg}</div>
          <button onClick={() => onDismiss(t.id)} className="opacity-80 hover:opacity-100"><Icons.X size={13}/></button>
        </div>
      ))}
    </div>
  );
}

function App() {
  const [view, setView] = useState("reports");
  const [step, setStep] = useState(0);
  const [topicForm, setTopicForm] = useState(null);
  const [titles, setTitles] = useState([]);
  const [chosenTitle, setChosenTitle] = useState("");
  const [sections, setSections] = useState([]);
  const [reportVersionId, setReportVersionId] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [toasts, setToasts] = useState([]);
  const [activeReportId, setActiveReportId] = useState(null);
  const [reports, setReports] = useState([]);
  const [sectionStates, setSectionStates] = useState({});
  const [knownPdfUrl, setKnownPdfUrl] = useState(null);

  // Load real reports on mount
  useEffect(() => {
    api.listReports()
      .then((data) => setReports(data.reports || []))
      .catch(() => setReports([]));
  }, []);

  const pushToast = useCallback((msg, kind = "info") => {
    const id = Math.random().toString(36).slice(2, 7);
    setToasts((t) => [...t, { id, msg, kind }]);
    setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 4500);
  }, []);

  const handleNewReport = () => {
    setView("reports");
    setStep(0);
    setTopicForm(null);
    setTitles([]);
    setChosenTitle("");
    setSections([]);
    setReportVersionId(null);
    setError(null);
    setActiveReportId(null);
    setSectionStates({});
    setKnownPdfUrl(null);
  };

  const handleTopicSubmit = async (form) => {
    setTopicForm(form);
    setLoading(true);
    setError(null);
    try {
      const res = await api.suggestTitles(form);
      setTitles(res.titles);
      setStep(1);
      pushToast(`${res.titles.length} candidate titles ready`, "success");
    } catch (e) {
      setError("Couldn't reach our research agents. Check your connection and try again.");
      pushToast("Failed to generate titles", "error");
    } finally {
      setLoading(false);
    }
  };

  const handleTitleConfirm = async (title) => {
    setChosenTitle(title);
    setLoading(true);
    try {
      const confirm = await api.confirmTitle({ title, topic: topicForm.topic });
      setReportVersionId(confirm.report_version_id);
      const secRes = await api.getSections(confirm.report_version_id);
      const normalized = flattenSections(secRes.sections || []);
      setSections(normalized);
      setStep(2);
      pushToast(`Index generated · ${normalized.length} sections`, "success");
    } catch (e) {
      pushToast("Couldn't structure the index. Try again.", "error");
    } finally {
      setLoading(false);
    }
  };

  const handleStartGeneration = async () => {
    setLoading(true);
    setSectionStates({});
    setKnownPdfUrl(null);
    try {
      await api.startWorkflow(reportVersionId);
      setStep(3);
      setActiveReportId(reportVersionId);
      setReports((rs) => [
        { id: reportVersionId, title: chosenTitle, date: "Just now", status: "generating", progress: 0.0 },
        ...rs.filter((r) => r.id !== reportVersionId),
      ]);
      pushToast("Generation started · monitoring progress", "info");
    } catch (e) {
      pushToast("Workflow failed to start. Retry?", "error");
    } finally {
      setLoading(false);
    }
  };

  // Fetch and apply current status immediately (used on sync + when opening existing reports)
  const fetchAndApplyStatus = useCallback(async (versionId, currentActiveId) => {
    try {
      const status = await api.getStatus(versionId);
      if (status.section_states) setSectionStates(status.section_states);
      const pct = status.sections_total > 0
        ? (status.sections_complete || 0) / status.sections_total : 0;
      setReports((rs) => rs.map((r) =>
        r.id === (currentActiveId || versionId)
          ? { ...r, progress: pct, status: status.status === "complete" ? "complete" : "generating" }
          : r
      ));
      return status;
    } catch (_) { return null; }
  }, []);

  const handleSync = useCallback(() => {
    if (reportVersionId) fetchAndApplyStatus(reportVersionId, activeReportId);
  }, [reportVersionId, activeReportId, fetchAndApplyStatus]);

  // Poll workflow status while on step 4
  useEffect(() => {
    if (step !== 3 || !reportVersionId) return;
    const poll = setInterval(() => fetchAndApplyStatus(reportVersionId, activeReportId), 5000);
    return () => clearInterval(poll);
  }, [step, reportVersionId, activeReportId, fetchAndApplyStatus]);

  const pickPastReport = async (r) => {
    if (r.status !== "generating" && r.status !== "complete") {
      pushToast(`"${r.title}" has no generated content yet`, "info");
      return;
    }

    setActiveReportId(r.id);
    setChosenTitle(r.title);
    setReportVersionId(r.id);
    setSectionStates({});
    setKnownPdfUrl(null);

    // Fetch sections, current status, and existing PDF URL in parallel
    const [secResult, statusResult, pdfResult] = await Promise.allSettled([
      api.getSections(r.id),
      api.getStatus(r.id),
      api.getPdfUrl(r.id),
    ]);

    if (secResult.status === "fulfilled") {
      const normalized = flattenSections(secResult.value.sections || []);
      setSections(normalized);
    } else {
      setSections([]);
      pushToast("Couldn't load sections for this report", "error");
    }

    if (statusResult.status === "fulfilled" && statusResult.value?.section_states) {
      setSectionStates(statusResult.value.section_states);
    }

    if (pdfResult.status === "fulfilled" && pdfResult.value) {
      setKnownPdfUrl(pdfResult.value);
    }

    setStep(3);
  };

  const currentTopic = topicForm?.topic || chosenTitle;

  return (
    <div className="h-screen flex flex-col bg-ink-50">
      <Shell.Navbar onNewReport={handleNewReport} currentTopic={currentTopic} step={step}/>
      <div className="flex-1 flex min-h-0">
        <Shell.Sidebar
          reports={reports}
          onPick={pickPastReport}
          onNew={handleNewReport}
          activeId={activeReportId}
          view={view}
          onChangeView={setView}/>
        <main className="flex-1 overflow-y-auto nice-scroll canvas-bg">
          {view === "reports" && <Shell.Stepper step={step}/>}
          <div className={view === "reports" ? "pt-2" : "pt-6"}>
            {view === "diagrams" ? (
              <DiagramManager
                reports={reports}
                preselectVersionId={reportVersionId || activeReportId}
                preselectTitle={chosenTitle}
                onBack={reportVersionId ? () => setView("reports") : null}
                pushToast={pushToast}/>
            ) : (
              <>
                {step === 0 && (
                  <Step1Topic
                    initial={topicForm}
                    error={error}
                    loading={loading}
                    onSubmit={handleTopicSubmit}/>
                )}
                {step === 1 && (
                  <Step2Title
                    topic={topicForm?.topic || ""}
                    titles={titles}
                    loading={loading}
                    onBack={() => setStep(0)}
                    onConfirm={handleTitleConfirm}/>
                )}
                {step === 2 && (
                  <Step3Index
                    title={chosenTitle}
                    sections={sections}
                    loading={loading}
                    onBack={() => setStep(1)}
                    onStart={handleStartGeneration}
                    onOpenDiagrams={() => setView("diagrams")}/>
                )}
                {step === 3 && (
                  <Step4Progress
                    title={chosenTitle}
                    sections={sections}
                    sectionStates={sectionStates}
                    initialPdfUrl={knownPdfUrl}
                    reportVersionId={reportVersionId}
                    onGeneratePdf={api.generatePdf}
                    onStartGeneration={api.startWorkflow}
                    onGetSectionContent={api.getSectionContent}
                    onSync={handleSync}
                    onNewReport={handleNewReport}
                    onBackToIndex={() => setStep(2)}
                    onOpenDiagrams={() => setView("diagrams")}/>
                )}
              </>
            )}
          </div>
        </main>
      </div>
      <Toast toasts={toasts} onDismiss={(id) => setToasts((t) => t.filter((x) => x.id !== id))}/>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App/>);
