// PortalTable — Client Portal app shell: top-nav routing, state for the
// client's actions (approve, pay, message, comment), dialogs, the free-plan
// badge, toasts, and mount. Loaded LAST.

const { useState: useStateApp, useEffect: useEffectApp, useRef: useRefApp } = React;

const CP_ROUTES = ["home", "projects", "approvals", "invoices", "files", "messages"];
const CP_TITLES = { home: "Home", projects: "Projects", approvals: "Approvals", invoices: "Invoices", files: "Files", messages: "Messages" };
const CP_ICONS = { home: "gauge", projects: "grid", approvals: "checklist", invoices: "card", files: "file", messages: "message" };

/* ── Pay invoice dialog (mock card form) ───────────────────────────────────── */
function PayDialog({ invoice, onClose, onConfirm }) {
  const [num, setNum] = useStateApp("");
  const [exp, setExp] = useStateApp("");
  const [cvc, setCvc] = useStateApp("");
  const [busy, setBusy] = useStateApp(false);
  useEffectApp(() => { if (invoice) { setNum(""); setExp(""); setCvc(""); setBusy(false); } }, [invoice]);
  if (!invoice) return null;
  function pay() {
    setBusy(true);
    setTimeout(() => { onConfirm(invoice); }, 900);
  }
  const fld = { height: 40, padding: "0 12px", borderRadius: 8, border: "1px solid var(--line-3)", background: "var(--ink-950)", color: "var(--fg-1)", fontSize: 14, fontFamily: "inherit", outline: "none", width: "100%", boxSizing: "border-box" };
  return (
    <Dialog open={!!invoice} onClose={onClose} eyebrow="PAYMENT" title={`Pay ${invoice.id}`} width={440}
      footer={<React.Fragment>
        <Button variant="ghost" size="md" onClick={onClose}>Cancel</Button>
        <Button variant="primary" size="md" icon={busy ? undefined : "card"} disabled={busy} onClick={pay}>{busy ? "Processing…" : `Pay ${cpMoney(invoice.amount)}`}</Button>
      </React.Fragment>}>
      <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 14px", borderRadius: 10, background: "var(--ink-950)", border: "1px solid var(--line-2)" }}>
          <span style={{ fontSize: 13, color: "var(--fg-2)" }}>{invoice.desc}</span>
          <span style={{ fontSize: 16, fontWeight: 600, color: "var(--fg-1)", fontVariantNumeric: "tabular-nums" }}>{cpMoney(invoice.amount)}</span>
        </div>
        <label style={{ display: "flex", flexDirection: "column", gap: 7 }}>
          <span style={{ fontSize: 12.5, color: "var(--fg-2)", fontWeight: 500 }}>Card number</span>
          <input value={num} onChange={(e) => setNum(e.target.value)} inputMode="numeric" placeholder="4242 4242 4242 4242" style={fld} />
        </label>
        <div style={{ display: "flex", gap: 12 }}>
          <label style={{ display: "flex", flexDirection: "column", gap: 7, flex: 1 }}>
            <span style={{ fontSize: 12.5, color: "var(--fg-2)", fontWeight: 500 }}>Expiry</span>
            <input value={exp} onChange={(e) => setExp(e.target.value)} placeholder="MM / YY" style={fld} />
          </label>
          <label style={{ display: "flex", flexDirection: "column", gap: 7, flex: 1 }}>
            <span style={{ fontSize: 12.5, color: "var(--fg-2)", fontWeight: 500 }}>CVC</span>
            <input value={cvc} onChange={(e) => setCvc(e.target.value)} placeholder="123" style={fld} />
          </label>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 9, fontSize: 11.5, color: "var(--fg-3)" }}>
          <Ic name="shieldCheck" size={15} style={{ color: "var(--green)" }} />Payments are secured and processed by Studio Northstar.
        </div>
      </div>
    </Dialog>
  );
}

/* ── Request-changes dialog ────────────────────────────────────────────────── */
function ChangesDialog({ approval, onClose, onConfirm }) {
  const [note, setNote] = useStateApp("");
  useEffectApp(() => { if (approval) setNote(""); }, [approval]);
  if (!approval) return null;
  return (
    <Dialog open={!!approval} onClose={onClose} eyebrow="REQUEST CHANGES" title={approval.title} width={460}
      footer={<React.Fragment>
        <Button variant="ghost" size="md" onClick={onClose}>Cancel</Button>
        <Button variant="primary" size="md" icon="send" onClick={() => onConfirm(approval, note)}>Send to team</Button>
      </React.Fragment>}>
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        <span style={{ fontSize: 12.5, color: "var(--fg-2)", fontWeight: 500 }}>What should change?</span>
        <textarea value={note} onChange={(e) => setNote(e.target.value)} autoFocus rows={4} placeholder="Share what you'd like the team to revise…"
          style={{ padding: "11px 13px", borderRadius: 9, border: "1px solid var(--line-3)", background: "var(--ink-950)", color: "var(--fg-1)", fontSize: 14, fontFamily: "inherit", outline: "none", resize: "vertical", lineHeight: 1.5 }} />
      </div>
    </Dialog>
  );
}

/* ── Project detail sheet (with comment composer) ──────────────────────────── */
function ProjectSheet({ project, onClose, onComment }) {
  const [comment, setComment] = useStateApp("");
  useEffectApp(() => { if (project) setComment(""); }, [project]);
  if (!project) return null;
  const lead = CP_TEAM[project.lead];
  const files = CP_FILES.filter((f) => f.project === project.name);
  function send() {
    const t = comment.trim();
    if (!t) return;
    onComment(project, t);
    setComment("");
  }
  return (
    <Sheet open={!!project} onClose={onClose} eyebrow="PROJECT" title={project.name} width={520}
      footer={<React.Fragment>
        <Button variant="secondary" size="md" onClick={onClose}>Close</Button>
        <Button variant="primary" size="md" icon="message" onClick={() => window.pdNavigateCP && window.pdNavigateCP("messages")}>Message team</Button>
      </React.Fragment>}>
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 18 }}>
        <StatusPill map={CP_PROJECT_STATUS} value={project.status} />
        <span style={{ fontSize: 12.5, color: "var(--fg-3)", display: "inline-flex", alignItems: "center", gap: 6 }}><Ic name="calendar" size={14} />{project.status === "done" ? "Delivered " + project.due : "Due " + project.due}</span>
        <span style={{ marginLeft: "auto", display: "inline-flex", alignItems: "center", gap: 8 }}>
          <CPAvatar initials={lead.initials} color={lead.color} size={26} />
          <span style={{ fontSize: 12.5, color: "var(--fg-2)" }}>{lead.name}</span>
        </span>
      </div>

      <p style={{ fontSize: 14, color: "var(--fg-2)", lineHeight: 1.6, margin: "0 0 18px" }}>{project.summary}</p>

      <div style={{ marginBottom: 8, display: "flex", justifyContent: "space-between", fontSize: 12.5, color: "var(--fg-3)" }}>
        <span>{project.tasksDone} / {project.tasksTotal} tasks complete</span>
        <span style={{ fontWeight: 600, color: "var(--fg-1)" }}>{project.progress}%</span>
      </div>
      <Progress value={project.progress} tone={CP_STATUS_TONE[project.status]} />

      {/* milestones */}
      <h4 style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-1)", margin: "24px 0 12px" }}>Milestones</h4>
      <div style={{ display: "flex", flexDirection: "column", gap: 0 }}>
        {project.milestones.map((m, i) => (
          <div key={i} style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
            <div style={{ display: "flex", flexDirection: "column", alignItems: "center", alignSelf: "stretch" }}>
              <span style={{ width: 18, height: 18, borderRadius: 999, flexShrink: 0, display: "grid", placeItems: "center", background: m.done ? "var(--accent)" : m.current ? "var(--ink-900)" : "var(--ink-900)", border: `1px solid ${m.done ? "var(--accent-press)" : m.current ? "var(--accent-press)" : "var(--line-3)"}`, color: "var(--fg-inverse)" }}>
                {m.done && <Ic name="check" size={11} strokeWidth={2.8} />}
              </span>
              {i < project.milestones.length - 1 && <span style={{ width: 2, flex: 1, minHeight: 22, background: "var(--line-2)" }} />}
            </div>
            <div style={{ paddingBottom: 16 }}>
              <div style={{ fontSize: 13.5, fontWeight: m.current ? 600 : 500, color: m.done || m.current ? "var(--fg-1)" : "var(--fg-3)" }}>{m.label}</div>
              <div style={{ fontSize: 11.5, color: "var(--fg-4)", marginTop: 2, fontFamily: "var(--font-mono)" }}>{m.date}{m.current ? " · in progress" : m.done ? " · done" : ""}</div>
            </div>
          </div>
        ))}
      </div>

      {/* files */}
      {files.length > 0 && (
        <React.Fragment>
          <h4 style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-1)", margin: "12px 0 12px" }}>Files</h4>
          <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
            {files.map((f) => {
              const fi = CP_FILE_ICON[f.kind] || CP_FILE_ICON.doc;
              return (
                <div key={f.id} style={{ display: "flex", alignItems: "center", gap: 12, padding: "10px 12px", borderRadius: 10, border: "1px solid var(--line-2)", background: "var(--ink-900)" }}>
                  <span style={{ width: 32, height: 32, borderRadius: 8, display: "grid", placeItems: "center", background: "var(--ink-800)", color: fi.color, flexShrink: 0 }}><Ic name={fi.icon} size={16} /></span>
                  <span style={{ flex: 1, minWidth: 0, fontSize: 13, fontWeight: 500, color: "var(--fg-1)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{f.name}</span>
                  <span style={{ fontSize: 11, color: "var(--fg-4)", fontFamily: "var(--font-mono)" }}>{f.size}</span>
                  <IconButton icon="download" label="Download" onClick={() => window.pdToast({ tone: "info", title: "Downloading…", body: f.name })} />
                </div>
              );
            })}
          </div>
        </React.Fragment>
      )}

      {/* comment */}
      <h4 style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-1)", margin: "24px 0 10px" }}>Leave a comment</h4>
      <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
        <textarea value={comment} onChange={(e) => setComment(e.target.value)} rows={3} placeholder="Ask a question or leave feedback for the team…"
          style={{ padding: "11px 13px", borderRadius: 9, border: "1px solid var(--line-3)", background: "var(--ink-950)", color: "var(--fg-1)", fontSize: 14, fontFamily: "inherit", outline: "none", resize: "vertical", lineHeight: 1.5 }} />
        <Button variant="primary" size="md" icon="send" onClick={send} style={{ alignSelf: "flex-end" }}>Post comment</Button>
      </div>
    </Sheet>
  );
}

/* ── App ───────────────────────────────────────────────────────────────────── */
function ClientPortalApp() {
  const [route, setRoute] = useStateApp(() => { const h = location.hash.replace("#", ""); return CP_ROUTES.includes(h) ? h : "home"; });
  const [approvals, setApprovals] = useStateApp(CP_APPROVALS);
  const [invoices, setInvoices] = useStateApp(CP_INVOICES);
  const [messages, setMessages] = useStateApp(CP_MESSAGES);
  const [payInv, setPayInv] = useStateApp(null);
  const [changesAp, setChangesAp] = useStateApp(null);
  const [project, setProject] = useStateApp(null);
  const [navOpen, setNavOpen] = useStateApp(false);
  const scrollRef = useRefApp(null);

  function navigate(r) { setRoute(r); location.hash = r; setNavOpen(false); window.scrollTo(0, 0); }
  useEffectApp(() => { window.pdNavigateCP = navigate; }, []);
  useEffectApp(() => {
    const onHash = () => { const h = location.hash.replace("#", ""); if (CP_ROUTES.includes(h)) setRoute(h); };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);

  // actions
  function approve(id) {
    setApprovals((xs) => xs.map((a) => a.id === id ? { ...a, status: "approved" } : a));
    window.pdToast({ tone: "success", title: "Approved", body: "The team has been notified." });
  }
  function requestChanges(ap, note) {
    setApprovals((xs) => xs.map((a) => a.id === ap.id ? { ...a, status: "changes" } : a));
    setChangesAp(null);
    window.pdToast({ tone: "success", title: "Changes requested", body: "Your notes were sent to the team." });
  }
  function payConfirm(inv) {
    setInvoices((xs) => xs.map((i) => i.id === inv.id ? { ...i, status: "paid" } : i));
    setPayInv(null);
    window.pdToast({ tone: "success", title: "Payment received", body: `${inv.id} · ${cpMoney(inv.amount)} paid. Thank you!` });
  }
  function download(f) { window.pdToast({ tone: "info", title: "Downloading…", body: f.name }); }
  function send(text) {
    setMessages((xs) => [...xs, { id: "m" + Date.now(), from: "me", text, time: "Just now" }]);
    setTimeout(() => {
      setMessages((xs) => [...xs, { id: "r" + Date.now(), from: "alex", text: "Thanks Maya — got it. I'll get back to you shortly.", time: "Just now" }]);
    }, 1400);
  }
  function comment(p, text) { window.pdToast({ tone: "success", title: "Comment posted", body: `On ${p.name}` }); }

  const pendingCount = approvals.filter((a) => a.status === "pending").length;
  const dueCount = invoices.filter((i) => i.status === "due" || i.status === "overdue").length;
  const nav = CP_ROUTES.map((id) => ({
    id, label: CP_TITLES[id], icon: CP_ICONS[id],
    badge: id === "approvals" ? (pendingCount || undefined) : id === "invoices" ? (dueCount || undefined) : undefined,
  }));

  function renderView() {
    switch (route) {
      case "projects": return <ProjectsView projects={CP_PROJECTS} onOpenProject={setProject} />;
      case "approvals": return <ApprovalsView approvals={approvals} onApprove={approve} onRequestChanges={setChangesAp} />;
      case "invoices": return <InvoicesView invoices={invoices} onPay={setPayInv} />;
      case "files": return <FilesView files={CP_FILES} onDownload={download} />;
      case "messages": return <MessagesView messages={messages} onSend={send} />;
      default: return <HomeView navigate={navigate} approvals={approvals} invoices={invoices} projects={CP_PROJECTS} onOpenProject={setProject} />;
    }
  }

  return (
    <div style={{ display: "flex", minHeight: "100vh", background: "var(--ink-950)" }}>
      <CPSidebar route={route} navigate={navigate} nav={nav} open={navOpen} onClose={() => setNavOpen(false)} />
      {navOpen && <div className="cp-nav-backdrop" onClick={() => setNavOpen(false)}
        style={{ position: "fixed", inset: 0, background: "rgba(16,18,22,0.42)", backdropFilter: "blur(2px)", zIndex: 70, animation: "pdFade 160ms var(--ease-out)" }} />}
      <div style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }}>
        <CPTopbar title={CP_TITLES[route]} onOpenNav={() => setNavOpen(true)} />
        <main ref={scrollRef} style={{ flex: 1 }}>
          <div style={{ maxWidth: 1100, margin: "0 auto", padding: "28px 26px 96px" }} key={route}>
            <div style={{ animation: "viewIn 280ms var(--ease-out)" }}>{renderView()}</div>
          </div>
        </main>
      </div>

      {/* free-plan attribution badge */}
      <div style={{ position: "fixed", right: 20, bottom: 20, zIndex: 50 }}><FreeBadge /></div>

      <PayDialog invoice={payInv} onClose={() => setPayInv(null)} onConfirm={payConfirm} />
      <ChangesDialog approval={changesAp} onClose={() => setChangesAp(null)} onConfirm={requestChanges} />
      <ProjectSheet project={project} onClose={() => setProject(null)} onComment={comment} />
      <ToastHost />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("cp-root")).render(<ClientPortalApp />);
