// Atlas · Step 1 — Brief
const { useState, useRef, useEffect } = React;

const stripHtml = (html) => (html || "").replace(/<[^>]+>/g, "").replace(/&nbsp;/g, " ").trim();

function StepIntake({ state, setState, goNext, goHome, goForward, loading, error, readOnly }) {
  const { REPORT_TYPES, FORMATS, AUDIENCES } = window.ATLAS_DATA;
  const briefRef = useRef(null);
  const fileInputRef = useRef(null);
  const [urlInput, setUrlInput] = useState("");
  const [urlLoading, setUrlLoading] = useState(false);
  const [attErrors, setAttErrors] = useState({});   // key: name|url → error string
  const [attUploading, setAttUploading] = useState(new Set());

  const setAttError = (key, msg) => setAttErrors(prev => ({ ...prev, [key]: msg }));
  const clearAttError = (key) => setAttErrors(prev => { const n = { ...prev }; delete n[key]; return n; });

  const attachments = state.attachments || [];
  const pdfCount   = attachments.filter(a => a.type === "pdf").length;
  const imageCount = attachments.filter(a => a.type === "image").length;
  const urlCount   = attachments.filter(a => a.type === "url").length;
  const pdfAtLimit   = pdfCount >= 1;
  const imageAtLimit = imageCount >= 2;
  const urlAtLimit   = urlCount >= 2;

  const handleFileUpload = async (files) => {
    for (const file of Array.from(files)) {
      const key = file.name;
      clearAttError(key);
      // Client-side size pre-check
      const isImage = /\.(jpg|jpeg|png|gif|webp)$/i.test(file.name);
      const cap = isImage ? 5 * 1024 * 1024 : 10 * 1024 * 1024;
      if (isImage && imageAtLimit) {
        setAttError(key, "Image limit reached (2 max). Remove one to add another.");
        continue;
      }
      if (!isImage && pdfAtLimit) {
        setAttError(key, "Only 1 PDF supported per report.");
        continue;
      }
      const allowedExt = /\.(pdf|jpg|jpeg|png|gif|webp)$/i.test(file.name);
      if (!allowedExt) {
        setAttError(key, "Unsupported file type. Accepted: PDF, JPG, PNG, GIF, WebP.");
        continue;
      }
      if (file.size > cap) {
        const limitMb = cap / (1024 * 1024);
        setAttError(key, isImage
          ? `Image too large — max ${limitMb} MB per image.`
          : `File too large — PDFs and documents are capped at ${limitMb} MB. Try splitting the file or pasting the key section into the brief.`
        );
        continue;
      }
      setAttUploading(prev => new Set(prev).add(key));
      try {
        const form = new FormData();
        form.append("file", file);
        const resp = await fetch("/api/upload", { method: "POST", body: form });
        if (!resp.ok) {
          const data = await resp.json().catch(() => ({}));
          setAttError(key, data.detail || "Upload failed. Please try again.");
          continue;
        }
        const data = await resp.json();
        const att = {
          name: data.filename,
          path: data.path,
          type: data.type,
          ...(data.media_type ? { media_type: data.media_type } : {}),
          ...(data.truncated_pages ? { truncated_pages: true, total_pages: data.total_pages } : {}),
        };
        setState(prev => ({ ...prev, attachments: [...(prev.attachments || []), att] }));
      } catch {
        setAttError(key, "Upload failed. Please try again.");
      } finally {
        setAttUploading(prev => { const n = new Set(prev); n.delete(key); return n; });
      }
    }
    if (fileInputRef.current) fileInputRef.current.value = "";
  };

  const handleAddUrl = async () => {
    const url = urlInput.trim();
    if (!url) return;
    if (urlAtLimit) return;
    const key = url;
    clearAttError(key);
    if (!/^https?:\/\//i.test(url)) {
      setAttError(key, "This URL can't be accessed — only public web addresses are supported.");
      return;
    }
    setUrlLoading(true);
    try {
      const resp = await fetch("/api/fetch-url", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ url }),
      });
      const data = await resp.json();
      if (!data.ok) {
        setAttError(key, "This URL can't be accessed — only public web addresses are supported.");
        return;
      }
      const att = { name: new URL(url).hostname, url, type: "url", extracted_text: data.extracted_text };
      setState(prev => ({ ...prev, attachments: [...(prev.attachments || []), att] }));
      setUrlInput("");
    } catch {
      setAttError(key, "Couldn't retrieve this URL. Check that it's publicly accessible and try again.");
    } finally {
      setUrlLoading(false);
    }
  };

  const removeAttachment = (idx) => {
    setState(prev => {
      const next = (prev.attachments || []).filter((_, i) => i !== idx);
      return { ...prev, attachments: next };
    });
  };

  useEffect(() => {
    if (briefRef.current) briefRef.current.innerHTML = state.brief || "";
  }, []); // run only on mount — restores brief when navigating back

  const briefPlain = stripHtml(state.brief);

  const wordCount = briefPlain.split(/\s+/).filter(Boolean).length;

  const valid =
    state.title.trim().length > 2 &&
    state.reportType &&
    state.format &&
    briefPlain.length > 40 &&
    wordCount <= 750 &&
    state.audience &&
    (state.reportType !== "position" || (state.anchorEntity || "").trim().length > 1);

  const execBriefCmd = (cmd) => {
    document.execCommand(cmd, false, null);
    briefRef.current?.focus();
    if (briefRef.current) setState({ ...state, brief: briefRef.current.innerHTML });
  };

  const formatSize = (bytes) => {
    if (bytes < 1024) return `${bytes} B`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
    return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  };

  return (
    <div className="canvas-inner">
      {readOnly && (
        <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "8px 14px", marginBottom: 12,
          background: "var(--ink-1)", border: "1px solid var(--ink-2)", borderRadius: "var(--radius)",
          fontSize: 12, color: "var(--ink-4)" }}>
          <Icon name="info" size={13} />
          This report has been researched. The brief is view-only.
        </div>
      )}
      <div className="intake-grid" style={readOnly ? { pointerEvents: "none", opacity: 0.72 } : undefined}>
        {/* — left column — */}
        <div>
          {/* Report type */}
          <div className="eyebrow" style={{ marginBottom: 10 }}>Report type</div>
          <div className="type-stack">
            {REPORT_TYPES.map((t) => (
              <button
                key={t.id}
                className={`type-card ${state.reportType === t.id ? "selected" : ""}`}
                onClick={() => setState({ ...state, reportType: t.id })}
              >
                <div className="tc-row">
                  <div className="tc-icon"><Icon name={t.icon} size={15} /></div>
                  <div className="tc-title">{t.title}</div>
                </div>
                <div className="tc-desc">{t.desc}</div>
              </button>
            ))}
          </div>

          {/* Report title */}
          <h2 className="section-h">Report title</h2>
          <input
            type="text"
            className="select"
            value={state.title}
            onChange={(e) => setState({ ...state, title: e.target.value })}
            placeholder="e.g. ASO & siRNA Technologies in Animal Health"
            style={{ width: "100%", marginBottom: 24, fontSize: 14, fontFamily: "var(--serif)", fontWeight: 500 }}
          />

          {/* Anchor entity — only shown for Competitive Position */}
          {state.reportType === "position" && (
            <div style={{ marginBottom: 24 }}>
              <h2 className="section-h">Your company or technology</h2>
              <p className="section-sub">Atlas will anchor the entire report on this entity and benchmark it against peers.</p>
              <input
                type="text"
                className="select"
                value={state.anchorEntity || ""}
                onChange={(e) => setState({ ...state, anchorEntity: e.target.value })}
                placeholder="e.g. Acme Bio — GalNAc-conjugated siRNA platform"
                style={{ width: "100%", fontSize: 14 }}
              />
            </div>
          )}

          {/* Brief composer */}
          <h2 className="section-h">The brief</h2>
          <p className="section-sub">
            Write freely. Include questions to answer, parameters every entry should
            capture, references to mirror, and anything that's out of scope. Atlas
            will structure it in the next step.
          </p>

          <div className="brief">
            <div className="brief-head">
              <span className="label">Brief</span>
              <div className="brief-toolbar">
                {[
                  { cmd: "bold",                 label: "B",  title: "Bold",           style: { fontWeight: 700 } },
                  { cmd: "italic",               label: "I",  title: "Italic",         style: { fontStyle: "italic" } },
                  { cmd: "underline",            label: "U",  title: "Underline",      style: { textDecoration: "underline" } },
                  { cmd: "insertUnorderedList",  label: "•",  title: "Bullet list",    style: {} },
                  { cmd: "insertOrderedList",    label: "1.", title: "Numbered list",  style: {} },
                ].map(({ cmd, label, title, style }) => (
                  <button
                    key={cmd}
                    type="button"
                    title={title}
                    className="toolbar-btn"
                    onMouseDown={(e) => { e.preventDefault(); execBriefCmd(cmd); }}
                    style={style}
                  >{label}</button>
                ))}
              </div>
              <span className="word-count" style={wordCount > 750 ? { color: "var(--red, #c0392b)", fontWeight: 600 } : wordCount > 500 ? { color: "var(--amber, #d97706)" } : {}}>
                {wordCount} / 750 words{wordCount > 750 ? " — too long" : wordCount > 500 ? " — getting long" : ""}
              </span>
            </div>
            <div
              ref={briefRef}
              contentEditable={readOnly ? "false" : "true"}
              suppressContentEditableWarning
              className="brief-editor"
              data-placeholder="Describe what you want investigated. The more context you provide here, the sharper the report."
              onInput={() => {
                if (briefRef.current) {
                  const html = briefRef.current.innerHTML;
                  setState(prev => ({ ...prev, brief: html }));
                }
              }}
            />
            <div className="brief-helper">
              Tip · the richer the brief, the more precise the agents can be.
              Atlas will pull out questions, parameters, and references automatically.
            </div>

          </div>

          {/* Reference Material */}
          <h2 className="section-h" style={{ marginTop: 28 }}>Reference material <span style={{ fontWeight: 400, color: "var(--ink-4)", fontSize: 12, marginLeft: 4 }}>optional</span></h2>
          <p className="section-sub">Attach PDFs, images, or URLs to give the scoping agent richer context. Content is read at brief-submission time and influences the questions and themes generated.</p>

          {!readOnly && (
            <div style={{ marginBottom: 16 }}>
              {/* File + URL inputs */}
              <div style={{ display: "flex", gap: 8, marginBottom: 8, flexWrap: "wrap" }}>
                <button
                  type="button"
                  className="btn ghost"
                  style={{ fontSize: 13, gap: 5 }}
                  disabled={pdfAtLimit && imageAtLimit}
                  onClick={() => fileInputRef.current?.click()}
                >
                  <Icon name="paperclip" size={13} /> Attach file
                </button>
                <input
                  ref={fileInputRef}
                  type="file"
                  multiple
                  accept=".pdf,.jpg,.jpeg,.png,.gif,.webp"
                  style={{ display: "none" }}
                  onChange={(e) => handleFileUpload(e.target.files)}
                />
                <input
                  type="url"
                  className="select"
                  style={{ flex: 1, minWidth: 180, fontSize: 13 }}
                  placeholder="https://example.com/article"
                  value={urlInput}
                  disabled={urlAtLimit}
                  onChange={(e) => { if (urlInput.trim()) clearAttError(urlInput.trim()); setUrlInput(e.target.value); }}
                  onKeyDown={(e) => e.key === "Enter" && !urlAtLimit && handleAddUrl()}
                />
                <button
                  type="button"
                  className="btn ghost"
                  style={{ fontSize: 13 }}
                  disabled={!urlInput.trim() || urlLoading || urlAtLimit}
                  onClick={handleAddUrl}
                >
                  {urlLoading ? "Fetching…" : "Add URL"}
                </button>
              </div>

              {/* Helper text */}
              <div style={{ fontSize: 11, color: "var(--ink-4)", lineHeight: 1.8, marginBottom: 10 }}>
                <div>· PDFs: first 10 pages extracted as text · max 10 MB · <strong>1 PDF max</strong></div>
                <div>· Images: uploaded as-is for visual context · max 5 MB · JPG, PNG, GIF, WebP · <strong>2 images max</strong></div>
                <div>· URLs: public pages only · ~4,000 tokens extracted · <strong>2 URLs max</strong></div>
                <div style={{ marginTop: 4 }}>· Tip: if your PDF is mostly charts or slides, export those pages as images and attach them. Image content is read visually, not as text.</div>
              </div>
              {/* Per-type limit messages */}
              {(pdfAtLimit || imageAtLimit || urlAtLimit) && (
                <div style={{ fontSize: 11, color: "var(--ink-4)", marginBottom: 8, lineHeight: 1.8 }}>
                  {pdfAtLimit   && <div>· Only 1 PDF supported per report.</div>}
                  {imageAtLimit && <div>· Image limit reached — remove one to upload another.</div>}
                  {urlAtLimit   && <div>· URL limit reached — remove one to add another.</div>}
                </div>
              )}

              {/* Pending uploads indicator */}
              {attUploading.size > 0 && (
                <div style={{ fontSize: 12, color: "var(--ink-4)", marginBottom: 6 }}>
                  Uploading {attUploading.size} file{attUploading.size > 1 ? "s" : ""}…
                </div>
              )}

              {/* File-level errors for rejected uploads (never made it into state.attachments) */}
              {Object.entries(attErrors)
                .filter(([key]) => !(state.attachments || []).some(a => (a.url || a.name) === key) && key !== urlInput.trim())
                .map(([key, msg]) => (
                  <div key={key} style={{
                    display: "flex", alignItems: "flex-start", gap: 8,
                    fontSize: 12, color: "var(--red, #c0392b)", marginBottom: 4,
                    padding: "6px 10px", borderRadius: "var(--radius)",
                    background: "rgba(192,57,43,0.06)", border: "1px solid rgba(192,57,43,0.18)",
                  }}>
                    <span style={{ flex: 1 }}><strong>{key}:</strong> {msg}</span>
                    <button
                      type="button"
                      onClick={() => clearAttError(key)}
                      style={{ background: "none", border: "none", cursor: "pointer", color: "inherit", padding: "0 2px", lineHeight: 1, flexShrink: 0 }}
                      title="Dismiss"
                    >×</button>
                  </div>
                ))
              }

              {/* URL-level errors (before attachment is added) */}
              {urlInput && attErrors[urlInput.trim()] && (
                <div style={{ fontSize: 12, color: "var(--red, #c0392b)", marginBottom: 6 }}>
                  {attErrors[urlInput.trim()]}
                </div>
              )}
            </div>
          )}

          {/* Attachment list */}
          {(state.attachments || []).length > 0 && (
            <div style={{ display: "flex", flexDirection: "column", gap: 6, marginBottom: 16 }}>
              {(state.attachments || []).map((att, idx) => {
                const key = att.url || att.name;
                const err = attErrors[key];
                return (
                  <div key={idx}>
                    <div style={{
                      display: "flex", alignItems: "center", gap: 8,
                      padding: "6px 10px", borderRadius: "var(--radius)",
                      background: "var(--ink-1)", border: "1px solid var(--ink-2)",
                      fontSize: 12,
                    }}>
                      <Icon name={att.type === "image" ? "image" : att.type === "url" ? "link" : "file"} size={12} />
                      <span style={{ flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                        {att.type === "url" ? att.url : att.name}
                      </span>
                      {att.type === "pdf" && att.truncated_pages && (
                        <span style={{ color: "var(--ink-4)", whiteSpace: "nowrap" }}>First 10 pages extracted</span>
                      )}
                      {att.type === "image" && (
                        <span style={{ color: "var(--ink-4)" }}>image</span>
                      )}
                      {att.type === "url" && (
                        <span style={{ color: "var(--ink-4)" }}>url</span>
                      )}
                      {!readOnly && (
                        <button
                          type="button"
                          onClick={() => removeAttachment(idx)}
                          style={{ background: "none", border: "none", cursor: "pointer", color: "var(--ink-4)", padding: "0 2px", lineHeight: 1 }}
                          title="Remove"
                        >×</button>
                      )}
                    </div>
                    {err && (
                      <div style={{ fontSize: 11, color: "var(--red, #c0392b)", marginTop: 3, paddingLeft: 4 }}>
                        {err}
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          )}

          {/* Parameters */}
          <h2 className="section-h" style={{ marginTop: 24 }}>Run parameters</h2>
          <p className="section-sub">Defaults that bound the search. Override at any step.</p>

          <div className="params-grid">
            <div>
              <div className="field-label">Audience</div>
              <select
                className="select"
                value={state.audience}
                onChange={(e) => setState({ ...state, audience: e.target.value })}
              >
                {AUDIENCES.map((a) => <option key={a} value={a}>{a}</option>)}
              </select>
            </div>
            <div>
              <div className="field-label">Output format</div>
              <div className="format-row">
                {FORMATS.map((f) => {
                  const selected = state.format === f.id;
                  return (
                    <button
                      key={f.id}
                      className={`format-pill ${selected ? "selected" : ""}`}
                      onClick={() => setState({ ...state, format: f.id })}
                    >
                      {f.label}
                      <span className="ext">{f.ext}</span>
                    </button>
                  );
                })}
              </div>
            </div>
            <div>
              <div className="field-label">Date range</div>
              <select
                className="select"
                value={state.dateRange}
                onChange={(e) => setState({ ...state, dateRange: e.target.value })}
              >
                <option>Last 10 years (2016–2026)</option>
                <option>Last 5 years (2021–2026)</option>
                <option>Last 3 years (2023–2026)</option>
              </select>
            </div>
            {state.reportType !== "lit" && (
              <div>
                <div className="field-label">Geographic scope</div>
                <select
                  className="select"
                  value={state.geo}
                  onChange={(e) => setState({ ...state, geo: e.target.value })}
                >
                  <option>Global</option>
                  <option>North America</option>
                  <option>Europe</option>
                  <option>Asia-Pacific</option>
                </select>
              </div>
            )}
          </div>
        </div>

        {/* — side rail — */}
        <div className="rail">
          <div className="rail-card">
            <div className="h">A good brief includes</div>
            <p className="b">The questions the report must answer.</p>
            <p className="b">Parameters every entry should capture (e.g. modality, stage, sponsor).</p>
            <p className="b">Prior reports or papers to mirror in tone and depth.</p>
            <p className="b">Anything that's explicitly out of scope.</p>
          </div>
          <div className="rail-card">
            <div className="h">Human-in-the-loop</div>
            <p className="b">
              Atlas pauses for sign-off at <strong style={{ color: "var(--ink)" }}>scope</strong>,
              <strong style={{ color: "var(--ink)" }}> outline</strong>, and
              <strong style={{ color: "var(--ink)" }}> draft review</strong> before continuing.
            </p>
          </div>
        </div>
      </div>

      <div className="actionbar">
        <div className="left">
          {readOnly ? <span style={{ color: "var(--ink-4)", fontSize: 12 }}>View only</span> : <>Saves automatically as <span className="kbd">brief.md</span></>}
        </div>
        <div className="right">
          {!readOnly && goHome && <button className="btn ghost" onClick={goHome}>Cancel</button>}
          {readOnly && <button className="btn ghost" onClick={goForward}>View scope <Icon name="arrowRight" size={14} /></button>}
          {!readOnly && (
            <button className="btn primary lg" disabled={!valid || loading} onClick={goNext}>
              {loading ? "Parsing brief…" : "Submit for scope review"}
              {!loading && <Icon name="arrowRight" size={14} />}
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

window.StepIntake = StepIntake;
