// project.jsx — Project detail with tabs
const { useState: useStateP } = React;

const STATUS_OPTIONS = ["Ascending", "Holding", "Camp", "Summited", "Abandoned"];

// Brief toast shown after clipboard copy
function Toast({ msg }) {
  return <div className="copy-toast">{msg}</div>;
}

function ProjectDetail({ project, allProjects, notes, receipts, campFiles, onBack, onSwitch, onMarkWorked, onAddNote, onSave, onUploadReceipt, onUploadCampFile, onDeleteCampFile, onDeleteNote, currentUser }) {
  const [tab, setTab] = useStateP("overview");
  const [switchOpen, setSwitchOpen] = useStateP(false);
  const [editingVision, setEditingVision] = useStateP(false);
  const [visionDraft, setVisionDraft] = useStateP(project.vision || "");
  const [editingStatus, setEditingStatus] = useStateP(false);
  const [editingProgress, setEditingProgress] = useStateP(false);
  const [progressDraft, setProgressDraft] = useStateP(Math.round((project.progress || 0) * 100));
  const [toast, setToast] = useStateP(null);

  const projectNotes = notes.filter(n => (n.project_id || n.projectId) === project.id);
  const projectReceipts = receipts.filter(r => (r.project_id || r.projectId) === project.id);
  const projectCampFiles = (campFiles || []).filter(f => f.project_id === project.id);

  const showToast = (msg) => {
    setToast(msg);
    setTimeout(() => setToast(null), 1500);
  };

  const copyFolder = () => {
    navigator.clipboard.writeText(project.folder || "").then(() => showToast("Copied!")).catch(() => {});
  };

  const saveVision = () => {
    onSave({ vision: visionDraft });
    setEditingVision(false);
  };

  const saveStatus = (s) => {
    onSave({ status: s });
    setEditingStatus(false);
  };

  const saveProgress = () => {
    onSave({ progress: progressDraft / 100 });
    setEditingProgress(false);
  };

  const TABS = [
    ["overview", "Overview"],
    ["docs", "Documents"],
    ["team", "Rope team"],
    ["timeline", "Route"],
    ["receipts", "Cache"],
    ["notes", "Field notes"],
    ["files", "Files"],
  ];

  return (
    <>
      {toast && <Toast msg={toast} />}
      <button className="back-link" onClick={onBack}>← Back to Base Camp</button>

      <section className="proj-hero">
        <div>
          <div className="codename">{project.codename}</div>
          <h1>{project.name}</h1>

          {/* Vision — inline editor */}
          {editingVision ? (
            <div className="inline-editor" style={{ marginTop: 10 }}>
              <textarea
                value={visionDraft}
                onChange={e => setVisionDraft(e.target.value)}
                placeholder="Where is this expedition headed?"
                autoFocus
              />
              <div className="inline-editor-actions">
                <button className="btn primary tiny" onClick={saveVision}>Save</button>
                <button className="btn tiny" onClick={() => { setVisionDraft(project.vision || ""); setEditingVision(false); }}>Cancel</button>
              </div>
            </div>
          ) : (
            <div className="vision-row" style={{ marginTop: 10 }}>
              {project.vision ? (
                <div className="vision">"{project.vision}"</div>
              ) : (
                <div className="vision" style={{ color: 'var(--ink-3)' }}>No vision statement yet.</div>
              )}
              <button className="edit-icon-btn" onClick={() => { setVisionDraft(project.vision || ""); setEditingVision(true); }} title="Edit vision">✎</button>
            </div>
          )}

          <div className="proj-switch" style={{ marginTop: 22 }}>
            <button className="proj-switch-btn" onClick={() => setSwitchOpen(v => !v)}>⇄  Switch expedition</button>
            {switchOpen && (
              <div className="proj-switch-menu" onMouseLeave={() => setSwitchOpen(false)}>
                {allProjects.filter(p => p.id !== project.id).map(p => (
                  <button key={p.id} onClick={() => { onSwitch(p.id); setSwitchOpen(false); setTab("overview"); }}>
                    <span className="cn">{p.codename.split('·')[0].trim()}</span>
                    {p.name}
                  </button>
                ))}
              </div>
            )}
          </div>
        </div>

        <div className="stats">
          <div className="stat">
            <span className="eyebrow">Elevation</span>
            <div className="v">{project.elevation} <span style={{ fontSize: 12, color: 'var(--ink-3)', fontFamily: 'var(--font-mono)' }}>FT</span></div>
            <div className="sub">{project.coords}</div>
          </div>

          {/* Status — click to pick */}
          <div className="stat" style={{ position: 'relative' }}>
            <span className="eyebrow">Status</span>
            <div className="v clickable-stat" onClick={() => setEditingStatus(v => !v)}>{project.status} ✎</div>
            <div className="sub">{Math.round((project.progress || 0) * 100)}% to summit</div>
            {editingStatus && (
              <div className="status-picker">
                {STATUS_OPTIONS.map(s => (
                  <button key={s} className={"status-opt" + (project.status === s ? " active" : "")} onClick={() => saveStatus(s)}>{s}</button>
                ))}
              </div>
            )}
          </div>

          <div className="stat">
            <span className="eyebrow">Last ascended</span>
            <div className="v" style={{ fontSize: 18 }}>{project.lastWorked}</div>
            <div className="sub">
              <button className="btn tiny" style={{ marginTop: 6 }} onClick={() => onMarkWorked(project.id)}>
                {project.lastWorked === "Worked today" ? "✓ Worked today" : "Mark today"}
              </button>
            </div>
          </div>

          {/* Progress — click to edit */}
          <div className="stat" style={{ position: 'relative' }}>
            <span className="eyebrow">Progress</span>
            {editingProgress ? (
              <div className="inline-editor" style={{ marginTop: 4 }}>
                <input
                  type="range"
                  min="0" max="100"
                  value={progressDraft}
                  onChange={e => setProgressDraft(Number(e.target.value))}
                  style={{ width: '100%' }}
                />
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, marginBottom: 4 }}>{progressDraft}%</div>
                <div className="inline-editor-actions">
                  <button className="btn primary tiny" onClick={saveProgress}>Save</button>
                  <button className="btn tiny" onClick={() => setEditingProgress(false)}>Cancel</button>
                </div>
              </div>
            ) : (
              <div className="v clickable-stat" onClick={() => { setProgressDraft(Math.round((project.progress || 0) * 100)); setEditingProgress(true); }}>
                {Math.round((project.progress || 0) * 100)}% ✎
              </div>
            )}
          </div>

          <div className="stat">
            <span className="eyebrow">Project folder</span>
            <div className="v" style={{ fontSize: 14, fontFamily: 'var(--font-mono)' }}>{project.folder}</div>
            <div className="sub">
              <button className="btn tiny ghost" style={{ marginTop: 4 }} onClick={copyFolder}>↗ Copy path</button>
            </div>
          </div>
        </div>
      </section>

      <div className="tabs">
        {TABS.map(([k, label]) => {
          const count = {
            docs: (project.docs || []).length,
            team: (project.team || []).length,
            receipts: projectReceipts.length,
            notes: projectNotes.length,
            files: projectCampFiles.length,
          }[k];
          return (
            <button key={k} className={"tab" + (tab === k ? " active" : "")} onClick={() => setTab(k)}>
              {label}
              {count != null && <span className="num">{String(count).padStart(2, "0")}</span>}
            </button>
          );
        })}
      </div>

      <div>
        {tab === "overview" && <OverviewTab project={project} onSave={onSave} />}
        {tab === "docs" && <DocsTab project={project} onSave={onSave} />}
        {tab === "team" && <TeamTab project={project} onSave={onSave} projectId={project.id} currentUser={currentUser} />}
        {tab === "timeline" && <TimelineTab project={project} onSave={onSave} />}
        {tab === "receipts" && <ReceiptsTab project={project} receipts={projectReceipts} onUploadReceipt={onUploadReceipt} />}
        {tab === "notes" && <NotesTab project={project} notes={projectNotes} onAdd={(t) => onAddNote(t, project.id)} onDelete={onDeleteNote} />}
        {tab === "files" && <FilesTab project={project} campFiles={projectCampFiles} onUpload={onUploadCampFile} onDelete={onDeleteCampFile} />}
      </div>
    </>
  );
}

function OverviewTab({ project, onSave }) {
  const [editingVision, setEditingVision] = useStateP(false);
  const [visionDraft, setVisionDraft] = useStateP(project.vision || "");
  const [editingGoal, setEditingGoal] = useStateP(false);
  const [goalDraft, setGoalDraft] = useStateP(project.goal || "");

  const saveVision = () => {
    onSave({ vision: visionDraft });
    setEditingVision(false);
  };

  const saveGoal = () => {
    onSave({ goal: goalDraft });
    setEditingGoal(false);
  };

  return (
    <div className="overview-grid">
      <div>
        <div className="field">
          <div className="lbl">Vision · True North</div>
          {editingVision ? (
            <div className="inline-editor">
              <textarea
                value={visionDraft}
                onChange={e => setVisionDraft(e.target.value)}
                placeholder="Where is this expedition headed?"
                autoFocus
                rows={3}
              />
              <div className="inline-editor-actions">
                <button className="btn primary tiny" onClick={saveVision}>Save</button>
                <button className="btn tiny" onClick={() => { setVisionDraft(project.vision || ""); setEditingVision(false); }}>Cancel</button>
              </div>
            </div>
          ) : project.vision ? (
            <div className="val big" style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
              <span>"{project.vision}"</span>
              <button className="edit-icon-btn" onClick={() => { setVisionDraft(project.vision); setEditingVision(true); }}>✎</button>
            </div>
          ) : (
            <EmptyState
              title="No vision set."
              sub="Where is this expedition headed? Two or three sentences. Set the line on the map before you start climbing."
              action={<button className="btn primary tiny" onClick={() => setEditingVision(true)}>Set vision</button>}
            />
          )}
        </div>

        <div className="field">
          <div className="lbl">Summit goal</div>
          {editingGoal ? (
            <div className="inline-editor">
              <textarea
                value={goalDraft}
                onChange={e => setGoalDraft(e.target.value)}
                placeholder="What does 'done' look like?"
                autoFocus
                rows={2}
              />
              <div className="inline-editor-actions">
                <button className="btn primary tiny" onClick={saveGoal}>Save</button>
                <button className="btn tiny" onClick={() => { setGoalDraft(project.goal || ""); setEditingGoal(false); }}>Cancel</button>
              </div>
            </div>
          ) : project.goal ? (
            <div className="val" style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}>
              <span>{project.goal}</span>
              <button className="edit-icon-btn" onClick={() => { setGoalDraft(project.goal); setEditingGoal(true); }}>✎</button>
            </div>
          ) : (
            <EmptyState
              title="No summit defined."
              sub="What does 'done' look like? A measurable, dated outcome works best."
              action={<button className="btn tiny" onClick={() => setEditingGoal(true)}>Define summit</button>}
            />
          )}
        </div>

        <div className="field">
          <div className="lbl">Project images</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10, marginTop: 6 }}>
            {(project.images && project.images.length > 0 ? project.images : [null, null, null]).map((img, i) => (
              img ? (
                <img key={i} src={img} style={{ aspectRatio: '4/3', objectFit: 'cover', borderRadius: 8, width: '100%' }} alt="" />
              ) : (
                <div key={i} style={{
                  aspectRatio: '4/3', border: '1px dashed var(--rule)', borderRadius: 8,
                  display: 'grid', placeItems: 'center', color: 'var(--ink-3)', fontSize: 12,
                  fontFamily: 'var(--font-mono)', letterSpacing: '0.08em',
                  background: 'color-mix(in oklab, var(--paper-3) 50%, transparent)',
                }}>+ IMAGE</div>
              )
            ))}
          </div>
        </div>
      </div>

      <div>
        <div className="field">
          <div className="lbl">Bearings</div>
          <div style={{ display: 'grid', gap: 10, marginTop: 8 }}>
            <div className="link-row">
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--ink-3)' }}>↗</span>
              <span>{project.folder}</span>
              <span className="arrow">↗</span>
            </div>
          </div>
        </div>

        <div className="field">
          <div className="lbl">Recent activity</div>
          <div style={{ marginTop: 8 }}>
            {(project.activity || []).map((a, i) => (
              <div className="activity-item" key={i}>
                <div className="when">{a.when}</div>
                {/* SECURITY: dangerouslySetInnerHTML is safe here ONLY because
                    a.what is populated exclusively from server-controlled seed data.
                    NEVER bind user-supplied content here without sanitizing through
                    DOMPurify first — doing so would introduce stored XSS. */}
                <div className="what" dangerouslySetInnerHTML={{ __html: a.what }} />
              </div>
            ))}
          </div>
        </div>

        <div className="field">
          <div className="lbl">Quick stats</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 12, marginTop: 10 }}>
            <div style={{ padding: 14, background: 'var(--paper-3)', border: '1px solid var(--rule-soft)', borderRadius: 8 }}>
              <div style={{ fontSize: 24, fontFamily: 'var(--font-display)' }}>{(project.docs || []).length}</div>
              <div className="eyebrow" style={{ marginTop: 2 }}>Documents</div>
            </div>
            <div style={{ padding: 14, background: 'var(--paper-3)', border: '1px solid var(--rule-soft)', borderRadius: 8 }}>
              <div style={{ fontSize: 24, fontFamily: 'var(--font-display)' }}>{(project.team || []).length}</div>
              <div className="eyebrow" style={{ marginTop: 2 }}>Rope team</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function DocsTab({ project, onSave }) {
  const [showPanel, setShowPanel] = useStateP(false);
  const [kindPreset, setKindPreset] = useStateP("PRD");
  const [docName, setDocName] = useStateP("");
  const [docKind, setDocKind] = useStateP("PRD");
  const [docUrl, setDocUrl] = useStateP("");
  const [docDesc, setDocDesc] = useStateP("");

  const docs = project.docs || [];

  const openPanel = (kind) => {
    setKindPreset(kind);
    setDocKind(kind);
    setDocName(kind === "Other" ? "" : kind);
    setDocUrl("");
    setDocDesc("");
    setShowPanel(true);
  };

  const saveDoc = () => {
    if (!docName.trim()) return;
    const newDoc = {
      name: docName.trim(),
      kind: docKind,
      url: docUrl.trim(),
      desc: docDesc.trim(),
      updated: new Date().toLocaleDateString(),
    };
    onSave({ docs: [...docs, newDoc] });
    setShowPanel(false);
  };

  const removeDoc = (i) => {
    onSave({ docs: docs.filter((_, idx) => idx !== i) });
  };

  if (docs.length === 0 && !showPanel) {
    return (
      <>
        <EmptyState
          large
          title="The manifest is empty."
          sub="No PRD, TRD, or other docs attached yet. Drop a file or link to start the paper trail."
          action={
            <div style={{ display: 'flex', gap: 8, justifyContent: 'center' }}>
              <button className="btn primary tiny" onClick={() => openPanel("PRD")}>+ Attach PRD</button>
              <button className="btn tiny" onClick={() => openPanel("TRD")}>+ Attach TRD</button>
              <button className="btn tiny" onClick={() => openPanel("Other")}>+ Other document</button>
            </div>
          }
        />
      </>
    );
  }

  return (
    <div>
      {docs.length > 0 && (
        <div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 10 }}>
          <button className="btn tiny" onClick={() => openPanel("Other")}>+ Add document</button>
        </div>
      )}
      {docs.map((d, i) => (
        <div className="doc-row" key={i}>
          <div className="ic">{d.kind}</div>
          <div style={{ flex: 1 }}>
            <div className="name">{d.name}</div>
            <div className="desc">{d.desc}</div>
          </div>
          <div className="date">{d.updated}</div>
          {d.url ? (
            <button className="btn tiny ghost" onClick={() => window.open(d.url, '_blank')}>Open ↗</button>
          ) : (
            <span className="btn tiny ghost" style={{ opacity: 0.4, cursor: 'default' }}>No URL</span>
          )}
          <button className="remove-btn" onClick={() => removeDoc(i)} title="Remove">×</button>
        </div>
      ))}
      {(showPanel || docs.length === 0) && (
        <div className="slide-panel">
          <div className="slide-panel-title">Add document</div>
          <div className="slide-panel-row">
            <label>Kind</label>
            <select value={docKind} onChange={e => setDocKind(e.target.value)}>
              {["PRD","TRD","RFC","Other"].map(k => <option key={k} value={k}>{k}</option>)}
            </select>
          </div>
          <div className="slide-panel-row">
            <label>Name</label>
            <input type="text" value={docName} onChange={e => setDocName(e.target.value)} placeholder="Document name" />
          </div>
          <div className="slide-panel-row">
            <label>URL</label>
            <input type="url" value={docUrl} onChange={e => setDocUrl(e.target.value)} placeholder="https://…" />
          </div>
          <div className="slide-panel-row">
            <label>Description</label>
            <input type="text" value={docDesc} onChange={e => setDocDesc(e.target.value)} placeholder="Optional" />
          </div>
          <div className="inline-editor-actions" style={{ marginTop: 12 }}>
            <button className="btn primary tiny" onClick={saveDoc}>Add</button>
            <button className="btn tiny" onClick={() => setShowPanel(false)}>Cancel</button>
          </div>
        </div>
      )}
    </div>
  );
}

function TeamTab({ project, onSave, projectId, currentUser }) {
  const [members, setMembers] = useStateP([]);
  const [email, setEmail] = useStateP("");
  const [role, setRole] = useStateP("member");
  const [error, setError] = useStateP(null);
  const [loading, setLoading] = useStateP(false);

  React.useEffect(() => {
    if (!projectId) return;
    fetch(`/api/v1/projects/${projectId}/members`)
      .then(r => r.ok ? r.json() : [])
      .then(setMembers)
      .catch(() => {});
  }, [projectId]);

  async function addMember(e) {
    e.preventDefault();
    setError(null);
    setLoading(true);
    try {
      const res = await fetch(`/api/v1/projects/${projectId}/members`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email, role }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.detail || "Failed to add member");
      setMembers(prev => [...prev, data]);
      setEmail("");
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }

  async function removeMember(userId) {
    await fetch(`/api/v1/projects/${projectId}/members/${userId}`, { method: "DELETE" });
    setMembers(prev => prev.filter(m => m.user_id !== userId));
  }

  return (
    <div className="team-tab">
      <h3 className="section-title">Team members</h3>
      <ul className="member-list">
        {members.map(m => (
          <li key={m.user_id} className="member-row">
            <span className="member-name">{m.name || m.email}</span>
            <span className="member-email">{m.email}</span>
            <span className={`member-role member-role--${m.role}`}>{m.role}</span>
            <button
              className="member-remove-btn"
              onClick={() => removeMember(m.user_id)}
              title="Remove member"
            >×</button>
          </li>
        ))}
        {members.length === 0 && <li className="member-empty">No members yet</li>}
      </ul>
      <form onSubmit={addMember} className="add-member-form">
        <input
          className="login-input"
          type="email"
          placeholder="Email address"
          value={email}
          onChange={e => setEmail(e.target.value)}
          required
        />
        <select
          className="member-role-select"
          value={role}
          onChange={e => setRole(e.target.value)}
        >
          <option value="member">Member</option>
          <option value="owner">Owner</option>
        </select>
        <button className="login-btn" type="submit" disabled={loading}>
          {loading ? "Adding…" : "Invite"}
        </button>
        {error && <p className="login-error">{error}</p>}
      </form>
    </div>
  );
}

function TimelineTab({ project, onSave }) {
  const [editDeparture, setEditDeparture] = useStateP(false);
  const [departureDraft, setDepartureDraft] = useStateP(project.start_date || "");
  const [editEta, setEditEta] = useStateP(false);
  const [etaDraft, setEtaDraft] = useStateP(project.end_date || "");
  const [editStatus, setEditStatus] = useStateP(false);
  const [editProgress, setEditProgress] = useStateP(false);
  const [progressDraft, setProgressDraft] = useStateP(Math.round((project.progress || 0) * 100));

  const hasDates = project.startDate || project.start_date;
  const hasEndDate = project.endDate || project.end_date;

  if (!hasDates && !hasEndDate && !editDeparture && !editEta) {
    return (
      <EmptyState
        large
        title="Pitch your tent."
        sub="No start or summit date set yet. A route without dates is just a wish."
        action={
          <div style={{ display: 'flex', gap: 8, justifyContent: 'center' }}>
            <button className="btn primary tiny" onClick={() => setEditDeparture(true)}>Set departure</button>
            <button className="btn tiny" onClick={() => setEditEta(true)}>Set summit ETA</button>
          </div>
        }
      />
    );
  }

  const pct = Math.round((project.progress || 0) * 100);
  const startDisplay = project.startDate || project.start_date || "–";
  const endDisplay = project.endDate || project.end_date || "–";

  return (
    <div>
      <div className="overview-grid">
        <div>
          <div className="field">
            <div className="lbl">Departed Base Camp</div>
            {editDeparture ? (
              <div className="inline-editor">
                <input type="date" value={departureDraft} onChange={e => setDepartureDraft(e.target.value)} autoFocus />
                <div className="inline-editor-actions">
                  <button className="btn primary tiny" onClick={() => { onSave({ start_date: departureDraft }); setEditDeparture(false); }}>Save</button>
                  <button className="btn tiny" onClick={() => setEditDeparture(false)}>Cancel</button>
                </div>
              </div>
            ) : (
              <div className="val big" style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                {startDisplay}
                <button className="edit-icon-btn" onClick={() => { setDepartureDraft(project.start_date || ""); setEditDeparture(true); }}>✎</button>
              </div>
            )}
          </div>
          <div className="field">
            <div className="lbl">Summit ETA</div>
            {editEta ? (
              <div className="inline-editor">
                <input type="date" value={etaDraft} onChange={e => setEtaDraft(e.target.value)} autoFocus />
                <div className="inline-editor-actions">
                  <button className="btn primary tiny" onClick={() => { onSave({ end_date: etaDraft }); setEditEta(false); }}>Save</button>
                  <button className="btn tiny" onClick={() => setEditEta(false)}>Cancel</button>
                </div>
              </div>
            ) : (
              <div className="val big" style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                {endDisplay}
                <button className="edit-icon-btn" onClick={() => { setEtaDraft(project.end_date || ""); setEditEta(true); }}>✎</button>
              </div>
            )}
          </div>
        </div>
        <div>
          <div className="field">
            <div className="lbl">Progress</div>
            {editProgress ? (
              <div className="inline-editor">
                <input type="range" min="0" max="100" value={progressDraft}
                  onChange={e => setProgressDraft(Number(e.target.value))} style={{ width: '100%' }} />
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, marginBottom: 4 }}>{progressDraft}%</div>
                <div className="inline-editor-actions">
                  <button className="btn primary tiny" onClick={() => { onSave({ progress: progressDraft / 100 }); setEditProgress(false); }}>Save</button>
                  <button className="btn tiny" onClick={() => setEditProgress(false)}>Cancel</button>
                </div>
              </div>
            ) : (
              <div className="val big" style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                {pct}%
                <button className="edit-icon-btn" onClick={() => { setProgressDraft(pct); setEditProgress(true); }}>✎</button>
              </div>
            )}
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--ink-3)', marginTop: 4 }}>to summit</div>
          </div>
          <div className="field" style={{ position: 'relative' }}>
            <div className="lbl">Status</div>
            <div className="val big" style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              {project.status}
              <button className="edit-icon-btn" onClick={() => setEditStatus(v => !v)}>✎</button>
            </div>
            {editStatus && (
              <div className="status-picker">
                {STATUS_OPTIONS.map(s => (
                  <button key={s} className={"status-opt" + (project.status === s ? " active" : "")}
                    onClick={() => { onSave({ status: s }); setEditStatus(false); }}>{s}</button>
                ))}
              </div>
            )}
          </div>
        </div>
      </div>

      {(hasDates || hasEndDate) && (
        <div className="timeline-rail">
          <div className="bar"><div className="fill" style={{ width: pct + "%" }}></div></div>
          <div className="marker start"></div>
          <div className="marker now" style={{ left: pct + "%" }}></div>
          <div className="marker end"></div>
          <div className="lbl" style={{ left: 0 }}>DEPARTED<br/><b>{startDisplay}</b></div>
          <div className="lbl" style={{ left: pct + "%" }}>YOU ARE HERE</div>
          <div className="lbl" style={{ left: '100%' }}>SUMMIT<br/><b>{endDisplay}</b></div>
        </div>
      )}
    </div>
  );
}

function ReceiptsTab({ project, receipts, onUploadReceipt }) {
  const fileInputRef = { current: null };

  const handleDrop = () => {
    if (fileInputRef.current) fileInputRef.current.click();
  };

  const handleFileChange = (e) => {
    const file = e.target.files && e.target.files[0];
    if (file && onUploadReceipt) onUploadReceipt(file, project.id);
    e.target.value = "";
  };

  const hiddenInput = (
    <input
      type="file"
      accept="image/jpeg,image/png,image/webp,application/pdf"
      style={{ display: 'none' }}
      ref={el => fileInputRef.current = el}
      onChange={handleFileChange}
    />
  );

  if (receipts.length === 0) {
    return (
      <>
        {hiddenInput}
        <EmptyState
          large
          title="No supplies logged."
          sub="Receipts dropped on the dashboard and classified to this expedition show up here."
          action={<button className="btn primary tiny" onClick={handleDrop}>Drop receipt</button>}
        />
      </>
    );
  }
  return (
    <div>
      {hiddenInput}
      <div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 10 }}>
        <button className="btn tiny" onClick={handleDrop}>+ Drop receipt</button>
      </div>
      {receipts.map((r) => (
        <div className="doc-row" key={r.id}>
          <div className="ic">RCT</div>
          <div style={{ flex: 1 }}>
            <div className="name">{r.fname}</div>
            <div className="desc">{(r.size / 1024).toFixed(1)} KB · {new Date(r.created_at || r.when).toLocaleString()}</div>
          </div>
          <div className="date">Unprocessed</div>
          <button className="btn tiny ghost" onClick={() => window.open(`/api/v1/receipts/${r.id}/download`, '_blank')}>View ↗</button>
        </div>
      ))}
    </div>
  );
}

function NotesTab({ project, notes, onAdd, onDelete }) {
  const [text, setText] = useStateP("");
  const submit = () => {
    const t = text.trim();
    if (!t) return;
    onAdd(t);
    setText("");
  };
  return (
    <div>
      <div className="notes-input">
        <textarea
          placeholder={`Note for ${project.name} — observations, decisions, snags…`}
          value={text}
          onChange={(e) => setText(e.target.value)}
          onKeyDown={(e) => {
            if ((e.metaKey || e.ctrlKey) && e.key === "Enter") submit();
          }}
        />
        <button className="btn primary" onClick={submit}>Log entry</button>
      </div>
      {notes.length === 0 ? (
        <EmptyState
          title="No field notes for this expedition."
          sub="Notes here are scoped to this project. ⌘↵ to log."
        />
      ) : (
        <div className="notes-list">
          {notes.map((n) => (
            <div className="note-entry" key={n.id}>
              <div className="ts">
                {new Date(n.created_at).toLocaleString()}
              </div>
              <div className="body">{n.text}</div>
              {onDelete && (
                <button className="remove-btn note-delete" onClick={() => onDelete(n.id)} title="Delete note">×</button>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function mimeLabel(mime) {
  const map = {
    "application/pdf": "PDF",
    "text/plain": "TXT",
    "text/markdown": "MD",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "DOC",
  };
  return map[mime] || "FILE";
}

function FilesTab({ project, campFiles, onUpload, onDelete }) {
  const fileInputRef = React.useRef(null);
  const accept = [
    "text/plain",
    "application/pdf",
    "text/markdown",
    ".md",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    ".docx",
  ].join(",");

  const handleFileChange = (e) => {
    const file = e.target.files && e.target.files[0];
    if (file && onUpload) onUpload(file, project.id);
    e.target.value = "";
  };

  const hiddenInput = (
    <input
      type="file"
      accept={accept}
      style={{ display: "none" }}
      ref={fileInputRef}
      onChange={handleFileChange}
    />
  );

  if (campFiles.length === 0) {
    return (
      <>
        {hiddenInput}
        <EmptyState
          large
          title="No files attached to this camp."
          sub="Attach a PDF, doc, or text file — stored securely with the project."
          action={
            <button className="btn primary tiny" onClick={() => fileInputRef.current && fileInputRef.current.click()}>
              Attach file
            </button>
          }
        />
      </>
    );
  }

  return (
    <div>
      {hiddenInput}
      <div style={{ display: "flex", justifyContent: "flex-end", marginBottom: 10 }}>
        <button className="btn tiny" onClick={() => fileInputRef.current && fileInputRef.current.click()}>
          + Attach
        </button>
      </div>
      {campFiles.map((f) => (
        <div className="doc-row" key={f.id}>
          <div className="ic">{mimeLabel(f.mime_type)}</div>
          <div style={{ flex: 1 }}>
            <div className="name">{f.fname}</div>
            <div className="desc">
              {(f.size / 1024).toFixed(1)} KB · {f.created_at ? new Date(f.created_at).toLocaleString() : ""}
            </div>
          </div>
          <button
            className="btn tiny ghost"
            onClick={() => window.open(`/api/v1/camp-files/${f.id}/download`, "_blank")}
          >
            Download ↗
          </button>
          <button className="remove-btn" onClick={() => onDelete && onDelete(f.id)} title="Remove">×</button>
        </div>
      ))}
    </div>
  );
}

Object.assign(window, { ProjectDetail });
