// Project Dashboard — KPI strip + filterable project table
const ProjectDashboard = ({ onOpenProject }) => {
  const [statusFilter, setStatusFilter] = React.useState("All");
  const [pmFilter, setPmFilter] = React.useState("All");
  const [riskFilter, setRiskFilter] = React.useState("All");
  const [search, setSearch] = React.useState("");
  const [timeRange, setTimeRange] = React.useState("This Quarter");
  const [savedView, setSavedView] = React.useState("All Active Projects");
  const [savedOpen, setSavedOpen] = React.useState(false);
  const [timeOpen, setTimeOpen] = React.useState(false);
  const [selected, setSelected] = React.useState(new Set());
  const [hoverRow, setHoverRow] = React.useState(null);

  const filtered = PROJECTS.filter(p => {
    if (statusFilter !== "All" && p.status !== statusFilter) return false;
    if (pmFilter !== "All" && p.pm.name !== pmFilter) return false;
    if (riskFilter !== "All" && p.risk !== riskFilter) return false;
    if (search && !p.name.toLowerCase().includes(search.toLowerCase()) && !p.customer.toLowerCase().includes(search.toLowerCase())) return false;
    return true;
  });

  // KPIs from the full dataset
  const active = PROJECTS.filter(p => p.status === "In Progress" || p.status === "At Risk").length;
  const totalContract = PROJECTS.filter(p => p.status !== "Completed").reduce((s, p) => s + p.contract, 0);
  const totalActual = PROJECTS.reduce((s, p) => s + p.budgetActual, 0);
  const totalPlan = PROJECTS.reduce((s, p) => s + p.budgetPlan, 0);
  const variance = totalActual - totalPlan;
  const atRisk = PROJECTS.filter(p => p.status === "At Risk").length;
  const pendingCO = PROJECTS.reduce((s, p) => s + p.changeOrders, 0);
  const pendingCOValue = PROJECTS.reduce((s, p) => s + p.coValue, 0);
  const billingReady = PROJECTS.filter(p => p.billing === "Ready").length;
  const billingReadyValue = PROJECTS.filter(p => p.billing === "Ready").reduce((s, p) => s + p.contract * 0.15, 0);

  const pms = ["All", ...Array.from(new Set(PROJECTS.map(p => p.pm.name)))];
  const statuses = ["All", "Planned", "In Progress", "At Risk", "On Hold", "Completed"];
  const risks = [{ k: "All", l: "All risk" }, { k: "high", l: "High risk" }, { k: "med", l: "Medium" }, { k: "low", l: "Low" }];

  const toggleRow = (id) => {
    const next = new Set(selected);
    if (next.has(id)) next.delete(id); else next.add(id);
    setSelected(next);
  };

  return (
    <div style={{ padding: "20px 24px 40px", display: "flex", flexDirection: "column", gap: 20 }}>
      {/* Page title row */}
      <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 16 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
          <div style={{ width: 40, height: 40, borderRadius: 10, background: "rgb(232,233,246)", display: "flex", alignItems: "center", justifyContent: "center" }}>
            <Icon name="briefcase" size={20} color="rgb(83,74,255)" />
          </div>
          <div>
            <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
              <h1 style={{ fontSize: 24, fontWeight: 700, margin: 0, letterSpacing: "-.015em" }}>Projects</h1>
              <Chip tone="neutral">{PROJECTS.length} total</Chip>
            </div>
            <div style={{ fontSize: 13, color: "rgb(106,115,131)", marginTop: 2 }}>
              Active portfolio across construction & manufacturing engagements
            </div>
          </div>
        </div>
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          {/* Time range dropdown */}
          <div style={{ position: "relative" }}>
            <Button kind="secondary" size="md" icon="calendar" iconRight="expandDown" onClick={() => { setTimeOpen(!timeOpen); setSavedOpen(false); }}>{timeRange}</Button>
            {timeOpen && (
              <div style={{ position: "absolute", top: 38, right: 0, background: "#fff", border: "1px solid rgb(227,229,232)", borderRadius: 8, padding: 4, minWidth: 180, boxShadow: "0 4px 12px rgba(43,46,83,.08), 0 1px 2px rgba(64,68,82,.10), 0 0 0 1px rgba(64,68,82,.04)", zIndex: 20 }}>
                {["This Month", "This Quarter", "This Year", "Year to Date", "Custom Range…"].map(t => (
                  <div key={t} onClick={() => { setTimeRange(t); setTimeOpen(false); }} style={{ padding: "8px 10px", borderRadius: 6, fontSize: 13, cursor: "pointer", color: t === timeRange ? "rgb(83,74,255)" : "rgb(26,27,37)", background: t === timeRange ? "rgb(232,233,246)" : "transparent" }}
                    onMouseEnter={e => { if (t !== timeRange) e.currentTarget.style.background = "rgb(248,248,251)"; }}
                    onMouseLeave={e => { if (t !== timeRange) e.currentTarget.style.background = "transparent"; }}>
                    {t}
                  </div>
                ))}
              </div>
            )}
          </div>
          {/* Saved views */}
          <div style={{ position: "relative" }}>
            <Button kind="secondary" size="md" icon="star" iconRight="expandDown" onClick={() => { setSavedOpen(!savedOpen); setTimeOpen(false); }}>{savedView}</Button>
            {savedOpen && (
              <div style={{ position: "absolute", top: 38, right: 0, background: "#fff", border: "1px solid rgb(227,229,232)", borderRadius: 8, padding: 4, minWidth: 220, boxShadow: "0 4px 12px rgba(43,46,83,.08), 0 1px 2px rgba(64,68,82,.10), 0 0 0 1px rgba(64,68,82,.04)", zIndex: 20 }}>
                <div style={{ fontSize: 11, color: "rgb(106,115,131)", padding: "6px 10px 4px", textTransform: "uppercase", letterSpacing: ".04em", fontWeight: 500 }}>My Views</div>
                {["All Active Projects", "My Projects", "At Risk Watch", "Ready to Bill", "Over Budget"].map(t => (
                  <div key={t} onClick={() => { setSavedView(t); setSavedOpen(false); }} style={{ padding: "8px 10px", borderRadius: 6, fontSize: 13, cursor: "pointer", color: t === savedView ? "rgb(83,74,255)" : "rgb(26,27,37)", background: t === savedView ? "rgb(232,233,246)" : "transparent", display: "flex", alignItems: "center", justifyContent: "space-between" }}
                    onMouseEnter={e => { if (t !== savedView) e.currentTarget.style.background = "rgb(248,248,251)"; }}
                    onMouseLeave={e => { if (t !== savedView) e.currentTarget.style.background = "transparent"; }}>
                    {t}
                    {t === savedView && <Icon name="check" size={14} color="rgb(83,74,255)" />}
                  </div>
                ))}
                <div style={{ borderTop: "1px solid rgb(239,240,242)", margin: "4px 0" }} />
                <div style={{ padding: "8px 10px", borderRadius: 6, fontSize: 13, cursor: "pointer", color: "rgb(106,115,131)", display: "flex", alignItems: "center", gap: 6 }}><Icon name="plus" size={13} /> Save current view</div>
              </div>
            )}
          </div>
          <Button kind="primary" size="md" icon="plus">Create Project</Button>
        </div>
      </div>

      {/* KPI strip */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gap: 12 }}>
        <KPICard label="Active Projects" value={active} sub={`of ${PROJECTS.length}`} delta="+2 vs last qtr" deltaTone="success" icon="briefcase" />
        <KPICard label="Contract Value" value={fmtMoney(totalContract)} sub="open contracts" delta="+8.4%" deltaTone="success" icon="dollar" />
        <KPICard
          label="Budget vs Actual"
          value={fmtMoney(totalActual)}
          sub={`of ${fmtMoney(totalPlan)}`}
          delta={`${variance >= 0 ? "+" : "−"}${fmtMoney(Math.abs(variance))}`}
          deltaTone={variance > 0 ? "danger" : "success"}
          icon="chartBar"
        />
        <KPICard label="Projects At Risk" value={atRisk} sub="needing attention" footer={`${Math.round(atRisk/PROJECTS.length*100)}% of portfolio`} icon="alert" accent="rgb(192,47,50)" />
        <KPICard label="Pending Change Orders" value={fmtMoney(pendingCOValue)} sub={`${pendingCO} open`} footer="Across 6 projects" icon="refresh" accent="rgb(178,121,26)" />
        <KPICard label="Billing Ready" value={fmtMoney(billingReadyValue)} sub={`${billingReady} projects`} footer="Ready to invoice" icon="receipt" accent="rgb(34,134,58)" />
      </div>

      {/* Toolbar + Table */}
      <div style={{ background: "#fff", border: "1px solid rgb(227,229,232)", borderRadius: 16, overflow: "hidden" }}>
        {/* Bulk action bar / toolbar */}
        {selected.size > 0 ? (
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "10px 16px", background: "rgb(232,233,246)", borderBottom: "1px solid rgb(227,229,232)" }}>
            <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
              <span style={{ fontSize: 13, fontWeight: 500, color: "rgb(83,74,255)" }}>{selected.size} selected</span>
              <span style={{ width: 1, height: 18, background: "rgba(83,74,255,.2)" }} />
              <Button kind="ghost" size="sm" icon="receipt">Generate Invoices</Button>
              <Button kind="ghost" size="sm" icon="user">Reassign PM</Button>
              <Button kind="ghost" size="sm" icon="download">Export</Button>
              <Button kind="ghost" size="sm" icon="archive">Archive</Button>
            </div>
            <Button kind="ghost" size="sm" icon="cross" onClick={() => setSelected(new Set())}>Clear</Button>
          </div>
        ) : (
          <div style={{ display: "flex", alignItems: "center", padding: "12px 16px", gap: 12, justifyContent: "space-between", borderBottom: "1px solid rgb(239,240,242)", flexWrap: "wrap" }}>
            <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", rowGap: 8 }}>
              <div style={{ position: "relative", width: 240, flexShrink: 0, marginRight: 4 }}>
                <span style={{ position: "absolute", left: 10, top: 8, opacity: 0.5 }}>
                  <Icon name="search" size={14} color="rgb(106,115,131)" />
                </span>
                <input value={search} onChange={e => setSearch(e.target.value)} placeholder="Search projects, customers…" style={{
                  width: "100%", boxSizing: "border-box", paddingLeft: 30, paddingRight: 10, height: 30, borderRadius: 9999,
                  border: "1px solid rgb(213,219,225)", fontSize: 13, fontFamily: "inherit", outline: "none", background: "#fff"
                }} />
              </div>
              <FilterPill label="Status" value={statusFilter} options={statuses} onChange={setStatusFilter} icon="flag" />
              <FilterPill label="PM" value={pmFilter} options={pms} onChange={setPmFilter} icon="user" />
              <FilterPill label="Risk" value={riskFilter} options={risks.map(r => r.k)} labelMap={Object.fromEntries(risks.map(r => [r.k, r.l]))} onChange={setRiskFilter} icon="alert" />
              <Button size="sm" kind="ghost" icon="filter">More filters</Button>
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
              <Button size="sm" kind="secondary" icon="columns">Columns</Button>
              <Button size="sm" kind="secondary" icon="download">Export</Button>
              <IconBtn icon="more" tone="outline" size={28} />
            </div>
          </div>
        )}

        {/* Table */}
        <div style={{ overflowX: "auto" }}>
          <div style={{ minWidth: 1280 }}>
            {/* Header row */}
            <div style={{
              display: "grid",
              gridTemplateColumns: "32px 2fr 1.4fr 1.2fr 0.9fr 1fr 1.1fr 1fr 1fr 1.2fr 0.7fr",
              padding: "10px 16px", fontSize: 11, fontWeight: 500, color: "rgb(106,115,131)",
              borderBottom: "1px solid rgb(239,240,242)", background: "rgb(252,252,253)", textTransform: "uppercase", letterSpacing: ".04em",
              alignItems: "center", gap: 12
            }}>
              <input type="checkbox" checked={selected.size === filtered.length && filtered.length > 0} onChange={e => setSelected(e.target.checked ? new Set(filtered.map(p => p.id)) : new Set())} style={{ accentColor: "rgb(83,74,255)" }} />
              <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>Project <Icon name="expandDown" size={11} /></span>
              <span>Customer</span>
              <span>Project Manager</span>
              <span>Status</span>
              <span style={{ textAlign: "right" }}>Contract</span>
              <span>Budget</span>
              <span>Progress</span>
              <span>Billing</span>
              <span>Next Milestone</span>
              <span style={{ textAlign: "right" }}>Updated</span>
            </div>

            {/* Rows */}
            {filtered.map((p, i) => (
              <ProjectRow key={p.id} p={p} idx={i} isLast={i === filtered.length - 1}
                checked={selected.has(p.id)}
                onToggle={() => toggleRow(p.id)}
                onClick={() => onOpenProject(p)}
                onHover={setHoverRow}
                hover={hoverRow === p.id}
              />
            ))}

            {filtered.length === 0 && (
              <div style={{ padding: "60px 16px", textAlign: "center", color: "rgb(106,115,131)", fontSize: 13 }}>
                No projects match these filters. <span style={{ color: "rgb(83,74,255)", cursor: "pointer" }} onClick={() => { setStatusFilter("All"); setPmFilter("All"); setRiskFilter("All"); setSearch(""); }}>Clear filters</span>
              </div>
            )}
          </div>
        </div>

        {/* Footer */}
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "10px 16px", borderTop: "1px solid rgb(239,240,242)", fontSize: 12, color: "rgb(106,115,131)" }}>
          <span>Showing {filtered.length} of {PROJECTS.length} projects</span>
          <div style={{ display: "flex", alignItems: "center", gap: 4 }}>
            <IconBtn icon="chevronLeft" size={28} />
            <span style={{ padding: "4px 10px", background: "rgb(232,233,246)", color: "rgb(83,74,255)", borderRadius: 6, fontWeight: 500 }}>1</span>
            <span style={{ padding: "4px 10px" }}>2</span>
            <span style={{ padding: "4px 10px" }}>3</span>
            <IconBtn icon="chevronRight" size={28} />
          </div>
        </div>
      </div>
    </div>
  );
};

const FilterPill = ({ label, value, options, onChange, icon, labelMap }) => {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef();
  React.useEffect(() => {
    const close = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", close);
    return () => document.removeEventListener("mousedown", close);
  }, []);
  const display = value === "All" ? label : (labelMap?.[value] || value);
  const isActive = value !== "All";
  return (
    <div ref={ref} style={{ position: "relative" }}>
      <button onClick={() => setOpen(!open)} style={{
        height: 28, padding: "0 10px", borderRadius: 9999,
        background: isActive ? "rgb(232,233,246)" : "#fff",
        border: `1px solid ${isActive ? "rgb(178,172,255)" : "rgb(213,219,225)"}`,
        color: isActive ? "rgb(83,74,255)" : "rgb(65,69,82)",
        fontSize: 12, fontWeight: 500, fontFamily: "inherit", cursor: "pointer",
        display: "inline-flex", alignItems: "center", gap: 5,
      }}>
        {icon && <Icon name={icon} size={12} />}
        {display}
        <Icon name="expandDown" size={11} />
      </button>
      {open && (
        <div style={{ position: "absolute", top: 32, left: 0, background: "#fff", border: "1px solid rgb(227,229,232)", borderRadius: 8, padding: 4, minWidth: 180, boxShadow: "0 4px 12px rgba(43,46,83,.08), 0 1px 2px rgba(64,68,82,.10), 0 0 0 1px rgba(64,68,82,.04)", zIndex: 10, maxHeight: 280, overflowY: "auto" }}>
          {options.map(opt => (
            <div key={opt} onClick={() => { onChange(opt); setOpen(false); }} style={{ padding: "7px 10px", borderRadius: 6, fontSize: 13, cursor: "pointer", color: opt === value ? "rgb(83,74,255)" : "rgb(26,27,37)", background: opt === value ? "rgb(232,233,246)" : "transparent", display: "flex", alignItems: "center", justifyContent: "space-between" }}
              onMouseEnter={e => { if (opt !== value) e.currentTarget.style.background = "rgb(248,248,251)"; }}
              onMouseLeave={e => { if (opt !== value) e.currentTarget.style.background = "transparent"; }}>
              {labelMap?.[opt] || opt}
              {opt === value && <Icon name="check" size={13} color="rgb(83,74,255)" />}
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

const ProjectRow = ({ p, idx, isLast, checked, onToggle, onClick, onHover, hover }) => {
  const variance = p.budgetActual - p.budgetPlan;
  const variancePct = p.budgetPlan ? (variance / p.budgetPlan) * 100 : 0;
  return (
    <div
      onClick={onClick}
      onMouseEnter={() => onHover(p.id)}
      onMouseLeave={() => onHover(null)}
      style={{
        display: "grid",
        gridTemplateColumns: "32px 2fr 1.4fr 1.2fr 0.9fr 1fr 1.1fr 1fr 1fr 1.2fr 0.7fr",
        padding: "14px 16px", fontSize: 13, color: "rgb(26,27,37)",
        borderBottom: isLast ? "none" : "1px solid rgb(239,240,242)",
        alignItems: "center", gap: 12, cursor: "pointer",
        background: hover ? "rgb(248,248,251)" : (checked ? "rgba(232,233,246,.4)" : "#fff"),
        transition: "background 120ms"
      }}
    >
      <input type="checkbox" checked={checked} onChange={onToggle} onClick={e => e.stopPropagation()} style={{ accentColor: "rgb(83,74,255)" }} />

      {/* Project name + risk + ID */}
      <div style={{ display: "flex", alignItems: "center", gap: 10, minWidth: 0 }}>
        <div style={{ width: 28, height: 28, borderRadius: 6, background: p.customerType === "Construction" ? "rgb(255,243,210)" : "rgb(232,233,246)", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
          <Icon name={p.customerType === "Construction" ? "hardhat" : "layers"} size={15} color={p.customerType === "Construction" ? "rgb(178,121,26)" : "rgb(83,74,255)"} />
        </div>
        <div style={{ minWidth: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
            {p.risk === "high" && <span title="High risk" style={{ width: 6, height: 6, borderRadius: "50%", background: "rgb(192,47,50)", flexShrink: 0 }} />}
            <span style={{ fontWeight: 500, color: "rgb(83,74,255)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{p.name}</span>
          </div>
          <div style={{ fontSize: 11, color: "rgb(106,115,131)", marginTop: 2, display: "flex", alignItems: "center", gap: 6 }}>
            <span>{p.id}</span>
            {p.changeOrders > 0 && (
              <span style={{ display: "inline-flex", alignItems: "center", gap: 3, padding: "1px 6px", borderRadius: 4, background: "rgb(255,243,210)", color: "rgb(178,121,26)", fontSize: 10, fontWeight: 500 }}>
                <Icon name="refresh" size={9} /> {p.changeOrders} CO
              </span>
            )}
          </div>
        </div>
      </div>

      {/* Customer */}
      <div style={{ minWidth: 0 }}>
        <div style={{ color: "rgb(26,27,37)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{p.customer}</div>
        <div style={{ fontSize: 11, color: "rgb(106,115,131)", marginTop: 2 }}>{p.customerType}</div>
      </div>

      {/* PM */}
      <div style={{ display: "inline-flex", alignItems: "center", gap: 8 }}>
        <Avatar size={24} initials={p.pm.initials} color={p.pm.color} />
        <span style={{ fontSize: 13 }}>{p.pm.name}</span>
      </div>

      {/* Status */}
      <div>
        <Chip tone={STATUS_TONES[p.status]} dot>{p.status}</Chip>
      </div>

      {/* Contract */}
      <div style={{ textAlign: "right", fontVariantNumeric: "tabular-nums", fontWeight: 500 }}>{fmtMoney(p.contract)}</div>

      {/* Budget */}
      <div>
        {p.budgetActual === 0 ? (
          <span style={{ fontSize: 12, color: "rgb(163,172,186)" }}>Not started</span>
        ) : (
          <div style={{ display: "flex", flexDirection: "column", gap: 3 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 5, fontSize: 12 }}>
              <span style={{ fontWeight: 500, color: TONES[p.budgetTone].fg, fontVariantNumeric: "tabular-nums" }}>
                {variance >= 0 ? "+" : "−"}{Math.abs(variancePct).toFixed(1)}%
              </span>
              <span style={{ color: "rgb(106,115,131)", fontSize: 11 }}>
                {p.budgetTone === "danger" ? "Over" : p.budgetTone === "warning" ? "Watch" : "On track"}
              </span>
            </div>
            <ProgressBar value={p.budgetActual} max={Math.max(p.budgetPlan, p.budgetActual) * 1.05} color={TONES[p.budgetTone].fg} height={4} />
          </div>
        )}
      </div>

      {/* Progress */}
      <div>
        <div style={{ display: "flex", flexDirection: "column", gap: 3 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 5, fontSize: 12 }}>
            <span style={{ fontWeight: 500, color: "rgb(65,69,82)", fontVariantNumeric: "tabular-nums" }}>{p.pct}%</span>
            <span style={{ color: "rgb(106,115,131)", fontSize: 11 }}>
              {p.pct === 100 ? "Complete" : p.status === "At Risk" ? "Behind" : p.status === "Planned" ? "Not started" : "In progress"}
            </span>
          </div>
          <ProgressBar value={p.pct} color={p.status === "At Risk" ? "rgb(192,47,50)" : p.status === "Completed" ? "rgb(34,134,58)" : "rgb(83,74,255)"} height={4} />
        </div>
      </div>

      {/* Billing */}
      <div>
        <Chip tone={BILLING_TONES[p.billing]}>{p.billing}</Chip>
      </div>

      {/* Next milestone */}
      <div style={{ minWidth: 0 }}>
        <div style={{ fontSize: 12, color: "rgb(26,27,37)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{p.nextMilestone}</div>
        <div style={{ fontSize: 11, color: "rgb(106,115,131)", marginTop: 2, fontVariantNumeric: "tabular-nums" }}>{p.nextMilestoneDate}</div>
      </div>

      {/* Updated */}
      <div style={{ textAlign: "right", fontSize: 12, color: "rgb(106,115,131)" }}>{p.updated}</div>
    </div>
  );
};

window.ProjectDashboard = ProjectDashboard;
