// Portfolio · coin table, add/edit holdings, manual price override.

function Portfolio() {
  const { state, prices, addHolding, updateHolding, removeHolding, setManualPrice, clearManualPrice } = useStore();
  const cur = state.settings.currency;
  const portfolio = React.useMemo(() => computePortfolio(state, prices), [state, prices]);
  const [editing, setEditing] = React.useState(null); // holding id | "new"
  const [confirmDel, setConfirmDel] = React.useState(null);

  return (
    <div className="exos-page">
      <div className="exos-page-head">
        <div>
          <div className="exos-kicker mono">PORTFOLIO</div>
          <h1 className="exos-h1">Your holdings</h1>
          <div className="exos-page-head-sub">
            Every coin you're tracking, with average buy price, current value, and how much of the portfolio it represents.
          </div>
        </div>
        <Button variant="primary" icon={<Icons.Plus size={14} />} onClick={() => setEditing("new")}>Add holding</Button>
      </div>

      {/* summary strip */}
      <div className="exos-grid cols-4" style={{ marginBottom: 14 }}>
        <StatCard label="Total value" value={fmtCurrency(portfolio.total, cur, { compact: true })} sub={`${portfolio.rows.length} positions`} />
        <StatCard label="Cost basis" value={fmtCurrency(portfolio.totalCost, cur, { compact: true })} sub="all-in" />
        <StatCard
          label="Unrealized P/L"
          value={fmtCurrency(portfolio.pnl, cur, { compact: true })}
          tone={portfolio.pnl >= 0 ? "gain" : "loss"}
          sub={fmtPct(portfolio.pnlPct)}
        />
        <StatCard
          label="Best performer"
          value={portfolio.rows[0]?.meta.symbol ?? "·"}
          sub={portfolio.rows[0] ? <span style={{ color: portfolio.rows[0].pnl >= 0 ? "var(--gain)" : "var(--loss)" }}>{fmtPct(portfolio.rows[0].pnlPct)}</span> : "·"}
          tone="accent"
        />
      </div>

      {/* allocation bar */}
      <Card style={{ marginBottom: 14 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
          <div className="exos-label">Allocation</div>
          <div className="mono" style={{ fontSize: 11, color: "var(--text-mute)" }}>{portfolio.rows.length} coins</div>
        </div>
        <AllocationBar rows={portfolio.rows.sort((a,b)=>b.alloc-a.alloc)} />
        <div style={{ display: "flex", flexWrap: "wrap", gap: 12, marginTop: 10 }}>
          {portfolio.rows.map(r => (
            <span key={r.id} style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 12, color: "var(--text-mute)" }}>
              <span style={{ width: 7, height: 7, borderRadius: 2, background: r.meta.color }} />
              <span className="mono">{r.meta.symbol} {r.alloc.toFixed(1)}%</span>
            </span>
          ))}
        </div>
      </Card>

      {/* table */}
      <Card padding="p-none">
        {portfolio.rows.length === 0 ? (
          <EmptyState
            icon={<Icons.Portfolio size={22} />}
            title="No holdings yet"
            sub="Add your first coin to start building your exit plan."
            action={<Button variant="primary" icon={<Icons.Plus size={14} />} onClick={() => setEditing("new")}>Add holding</Button>}
          />
        ) : (
          <div className="exos-table-wrap">
            <table className="exos-table">
              <thead>
                <tr>
                  <th>Coin</th>
                  <th className="right">Amount</th>
                  <th className="right">Avg buy</th>
                  <th className="right">Live price</th>
                  <th className="right">Value</th>
                  <th className="right">P/L</th>
                  <th className="right">Alloc</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {portfolio.rows.map(r => {
                  const isManual = state.manualPrices[r.coinId] != null;
                  const change24h = prices[r.coinId]?.change24h ?? 0;
                  return (
                    <tr key={r.id}>
                      <td>
                        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                          <CoinIcon coinId={r.coinId} size={26} />
                          <div>
                            <div style={{ fontWeight: 500 }}>{r.meta.name}</div>
                            <div className="mono" style={{ fontSize: 11, color: "var(--text-mute)" }}>{r.meta.symbol}</div>
                          </div>
                        </div>
                      </td>
                      <td className="right mono">{fmtNum(r.amount, 6)}</td>
                      <td className="right mono">{fmtCurrency(r.avgBuyPrice, cur, { precise: true })}</td>
                      <td className="right">
                        <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 2 }}>
                          <div className="mono">
                            <Ticker value={r.price} format={v => fmtCurrency(v, cur, { precise: r.price < 10 })} />
                            {isManual && <Pill className="exos-manual-pill">manual</Pill>}
                          </div>
                          <div className="mono" style={{ fontSize: 11, color: change24h >= 0 ? "var(--gain)" : "var(--loss)" }}>
                            {fmtPct(change24h)}
                          </div>
                        </div>
                      </td>
                      <td className="right mono">{fmtCurrency(r.value, cur, { compact: true })}</td>
                      <td className="right">
                        <div className="mono" style={{ color: r.pnl >= 0 ? "var(--gain)" : "var(--loss)" }}>
                          {fmtCurrency(r.pnl, cur, { compact: true })}
                        </div>
                        <div className="mono" style={{ fontSize: 11, color: r.pnl >= 0 ? "var(--gain)" : "var(--loss)" }}>
                          {fmtPct(r.pnlPct)}
                        </div>
                      </td>
                      <td className="right">
                        <div style={{ display: "flex", alignItems: "center", gap: 8, justifyContent: "flex-end" }}>
                          <div style={{ width: 36, height: 4, background: "var(--line)", borderRadius: 2, overflow: "hidden" }}>
                            <div style={{ height: "100%", width: `${r.alloc}%`, background: r.meta.color }} />
                          </div>
                          <span className="mono" style={{ minWidth: 36 }}>{r.alloc.toFixed(1)}%</span>
                        </div>
                      </td>
                      <td className="right">
                        <div style={{ display: "flex", gap: 2, justifyContent: "flex-end" }}>
                          <button className="exos-icon-btn" onClick={() => setEditing(r.id)} title="Edit"><Icons.Pencil size={14} /></button>
                          <button className="exos-icon-btn" onClick={() => setConfirmDel(r.id)} title="Remove"><Icons.Trash size={14} /></button>
                        </div>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        )}
      </Card>

      <HoldingEditor
        open={editing != null}
        editing={editing}
        onClose={() => setEditing(null)}
        existingCoinIds={state.holdings.map(h => h.coinId)}
        holding={state.holdings.find(h => h.id === editing)}
        manualPrice={editing && editing !== "new" ? state.manualPrices[state.holdings.find(h => h.id === editing)?.coinId] : undefined}
        onSave={(data) => {
          if (editing === "new") {
            addHolding(data.holding);
          } else {
            updateHolding(editing, data.holding);
          }
          if (data.manualPrice != null) {
            setManualPrice(data.holding.coinId, data.manualPrice);
          } else if (editing !== "new") {
            clearManualPrice(data.holding.coinId);
          }
          setEditing(null);
        }}
      />

      <Modal open={confirmDel != null} onClose={() => setConfirmDel(null)} title="Remove holding"
        footer={<>
          <Button onClick={() => setConfirmDel(null)}>Cancel</Button>
          <Button variant="primary" onClick={() => { removeHolding(confirmDel); setConfirmDel(null); }}>Remove</Button>
        </>}>
        <p style={{ margin: 0, color: "var(--text-mute)", fontSize: 14 }}>
          This will remove the holding and its exit ladder. You can re-add it anytime.
        </p>
      </Modal>
    </div>
  );
}

// ---------- Holding editor modal
function HoldingEditor({ open, editing, holding, manualPrice, existingCoinIds, onSave, onClose }) {
  const { state, prices, rememberCoin, addCustomCoin } = useStore();
  const [coinId, setCoinId] = React.useState(holding?.coinId ?? "");
  const [amount, setAmount] = React.useState(holding?.amount ?? "");
  const [avgBuyPrice, setAvgBuyPrice] = React.useState(holding?.avgBuyPrice ?? "");
  const [manual, setManual] = React.useState(manualPrice);
  const [search, setSearch] = React.useState("");
  const [cgResults, setCgResults] = React.useState([]);
  const [cgLoading, setCgLoading] = React.useState(false);
  const [cgError, setCgError] = React.useState(null);
  const [showCustom, setShowCustom] = React.useState(false);
  const [customName, setCustomName] = React.useState("");
  const [customSymbol, setCustomSymbol] = React.useState("");
  const [customPrice, setCustomPrice] = React.useState("");

  React.useEffect(() => {
    if (open) {
      setCoinId(holding?.coinId ?? "");
      setAmount(holding?.amount ?? "");
      setAvgBuyPrice(holding?.avgBuyPrice ?? "");
      setManual(manualPrice);
      setSearch("");
      setCgResults([]);
      setCgError(null);
      setShowCustom(false);
      setCustomName(""); setCustomSymbol(""); setCustomPrice("");
    }
  }, [open]);

  const usingCG = isCoinGeckoSource(state.settings.priceSource);

  // CoinGecko live search (debounced)
  React.useEffect(() => {
    if (!usingCG || !search || search.length < 2 || editing !== "new") {
      setCgResults([]); setCgError(null); return;
    }
    let cancel = false;
    setCgLoading(true);
    setCgError(null);
    const t = setTimeout(async () => {
      try {
        const r = await cgSearch(search, state.settings.priceSource, state.settings.coingeckoKey);
        if (!cancel) setCgResults(r);
      } catch (e) {
        if (!cancel) { setCgResults([]); setCgError(e?.message || "Search failed"); }
      } finally {
        if (!cancel) setCgLoading(false);
      }
    }, 350);
    return () => { cancel = true; clearTimeout(t); };
  }, [search, usingCG, state.settings.priceSource, state.settings.coingeckoKey, editing]);

  const localResults = DEMO_COINS.filter(c => {
    if (editing !== "new" && holding?.coinId === c.id) return true;
    if (existingCoinIds.includes(c.id)) return false;
    if (!search) return true;
    return c.name.toLowerCase().includes(search.toLowerCase()) || c.symbol.toLowerCase().includes(search.toLowerCase());
  });

  // Combine results: dedupe CG over local
  const cgFiltered = cgResults
    .filter(r => !existingCoinIds.includes(r.id))
    .filter(r => !DEMO_COINS.find(c => c.id === r.id)); // demo coins already shown

  const livePrice = coinId ? (prices[coinId]?.price ?? getCoinMeta(coinId).basePrice ?? 0) : null;
  const cur = state.settings.currency;
  const valid = coinId && amount > 0 && avgBuyPrice > 0;
  const customValid = customName.trim() && customSymbol.trim() && customPrice > 0;

  function pickCG(r) {
    rememberCoin({
      id: r.id, symbol: r.symbol, name: r.name,
      color: colorFromId(r.id), image: r.image, basePrice: 0,
    });
    setCoinId(r.id);
  }

  function createCustom() {
    const id = "custom:" + customSymbol.toLowerCase().replace(/[^a-z0-9]/g, "") + "-" + Math.random().toString(36).slice(2, 6);
    addCustomCoin({
      id, symbol: customSymbol.toUpperCase().slice(0, 6), name: customName.trim(),
      color: colorFromId(id), basePrice: parseFloat(customPrice),
    });
    setCoinId(id);
    setManual(parseFloat(customPrice));
    setShowCustom(false);
  }

  return (
    <Modal open={open} onClose={onClose} title={editing === "new" ? "Add holding" : "Edit holding"} width={560}
      footer={<>
        <Button onClick={onClose}>Cancel</Button>
        <Button variant="primary" disabled={!valid}
          onClick={() => valid && onSave({
            holding: { coinId, amount: parseFloat(amount), avgBuyPrice: parseFloat(avgBuyPrice) },
            manualPrice: manual,
          })}>Save</Button>
      </>}>
      <div className="exos-col">
        <div>
          <div className="exos-label" style={{ marginBottom: 8 }}>Coin</div>
          {editing === "new" ? (
            <>
              {!showCustom ? (
                <>
                  <TextInput value={search} onChange={setSearch}
                    placeholder={usingCG ? "Search any coin on CoinGecko…" : "Search BTC, Ethereum…"}
                    prefix={<Icons.Search size={14} />} />

                  <div className="exos-coin-list">
                    {/* Show CG live results first if available */}
                    {usingCG && search && cgLoading && (
                      <div className="exos-coin-status">Searching CoinGecko…</div>
                    )}
                    {usingCG && cgError && (
                      <div className="exos-coin-status err">
                        <Icons.Warning size={12} /> {cgError}
                      </div>
                    )}
                    {cgFiltered.slice(0, 10).map(r => (
                      <button key={r.id} className={`exos-coin-row ${coinId === r.id ? "on" : ""}`} onClick={() => pickCG(r)}>
                        {r.image
                          ? <img src={r.image} className="exos-coin-row-img" alt="" />
                          : <CoinIcon coinId={r.id} size={26} />
                        }
                        <div style={{ textAlign: "left", flex: 1, minWidth: 0 }}>
                          <div style={{ fontWeight: 500, fontSize: 13, textOverflow: "ellipsis", overflow: "hidden", whiteSpace: "nowrap" }}>{r.name}</div>
                          <div className="mono" style={{ fontSize: 11, color: "var(--text-mute)" }}>
                            {r.symbol}{r.marketCapRank ? ` · #${r.marketCapRank}` : ""}
                          </div>
                        </div>
                        <span className="exos-coin-row-tag">live</span>
                        {coinId === r.id && <Icons.Check size={14} />}
                      </button>
                    ))}

                    {/* Local demo list */}
                    {localResults.slice(0, 10).map(c => (
                      <button key={c.id} className={`exos-coin-row ${coinId === c.id ? "on" : ""}`} onClick={() => setCoinId(c.id)}>
                        <CoinIcon coinId={c.id} size={26} />
                        <div style={{ textAlign: "left", flex: 1, minWidth: 0 }}>
                          <div style={{ fontWeight: 500, fontSize: 13 }}>{c.name}</div>
                          <div className="mono" style={{ fontSize: 11, color: "var(--text-mute)" }}>{c.symbol}</div>
                        </div>
                        <span className="mono" style={{ fontSize: 12, color: "var(--text-mute)" }}>{fmtCurrency(c.basePrice, cur, { compact: true })}</span>
                        {coinId === c.id && <Icons.Check size={14} />}
                      </button>
                    ))}

                    {localResults.length === 0 && cgFiltered.length === 0 && !cgLoading && (
                      <div className="exos-coin-status">
                        {usingCG ? "No CoinGecko matches. " : "Not in our list. "}
                        Try the custom option below.
                      </div>
                    )}
                  </div>

                  <button className="exos-add-custom-btn" onClick={() => setShowCustom(true)}>
                    <Icons.Plus size={13} />
                    <span>Add a coin not listed (custom)</span>
                  </button>
                </>
              ) : (
                <div className="exos-custom-form">
                  <div className="exos-label" style={{ marginBottom: 8 }}>Custom coin</div>
                  <div className="exos-grid cols-2">
                    <TextInput value={customName} onChange={setCustomName} placeholder="Name (e.g. SomeAltCoin)" />
                    <TextInput value={customSymbol} onChange={setCustomSymbol} placeholder="Symbol (e.g. ALT)" />
                  </div>
                  <div style={{ marginTop: 10 }}>
                    <div className="exos-label" style={{ marginBottom: 6 }}>Current price ({cur})</div>
                    <NumInput value={customPrice} onChange={setCustomPrice} prefix={CURRENCY_SYMBOLS[cur]} placeholder="0.00" />
                  </div>
                  <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 10, lineHeight: 1.5 }}>
                    Custom coins won't auto-update. You'll set their price by hand on the Portfolio page.
                  </div>
                  <div style={{ display: "flex", gap: 8, marginTop: 14 }}>
                    <Button onClick={() => setShowCustom(false)}>Back</Button>
                    <Button variant="primary" disabled={!customValid} onClick={createCustom}>Create coin</Button>
                  </div>
                </div>
              )}
            </>
          ) : (
            <div style={{ display: "flex", gap: 10, alignItems: "center", padding: "8px 0" }}>
              <CoinIcon coinId={coinId} size={32} />
              <div>
                <div style={{ fontWeight: 500 }}>{getCoinMeta(coinId).name}</div>
                <div className="mono" style={{ fontSize: 12, color: "var(--text-mute)" }}>{getCoinMeta(coinId).symbol}</div>
              </div>
            </div>
          )}
        </div>

        <div className="exos-grid cols-2">
          <div>
            <div className="exos-label" style={{ marginBottom: 8 }}>Amount held</div>
            <NumInput value={amount} onChange={setAmount} placeholder="0.0" />
          </div>
          <div>
            <div className="exos-label" style={{ marginBottom: 8 }}>Avg buy price ({cur})</div>
            <NumInput value={avgBuyPrice} onChange={setAvgBuyPrice} prefix={CURRENCY_SYMBOLS[cur]} placeholder="0.00" />
          </div>
        </div>

        {coinId && (
          <div className="exos-manual-section">
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }}>
              <div>
                <div className="exos-label">Manual price override</div>
                <div style={{ fontSize: 11, color: "var(--text-dim)", marginTop: 2 }}>
                  Live demo: <span className="mono">{fmtCurrency(livePrice, cur, { precise: livePrice < 10 })}</span>
                </div>
              </div>
              {manual != null && <Button size="sm" variant="ghost" onClick={() => setManual(undefined)}>Clear</Button>}
            </div>
            <NumInput value={manual} onChange={setManual} prefix={CURRENCY_SYMBOLS[cur]} placeholder="Use live demo" />
          </div>
        )}
      </div>
    </Modal>
  );
}

const PORTFOLIO_STYLES = `
.exos-table-wrap { overflow-x: auto; }
.exos-manual-pill { margin-left: 6px; font-size: 9px; padding: 1px 5px; }
.exos-coin-list { margin-top: 8px; max-height: 240px; overflow-y: auto; border: 1px solid var(--line); border-radius: 8px; }
.exos-coin-row {
  width: 100%; display: flex; align-items: center; gap: 10px;
  padding: 9px 11px; border: 0; background: transparent; cursor: pointer;
  border-bottom: 1px solid var(--line); transition: background .12s;
  color: var(--text);
}
.exos-coin-row:last-child { border-bottom: 0; }
.exos-coin-row:hover { background: var(--bg-elev-2); }
.exos-coin-row.on { background: var(--accent-soft); color: var(--accent); }
.exos-coin-row.on .mono { color: var(--accent); }
.exos-manual-section { padding: 12px; background: var(--bg-elev-2); border: 1px solid var(--line); border-radius: 8px; }
.exos-coin-row-img { width: 26px; height: 26px; border-radius: 50%; background: var(--bg-elev-2); flex-shrink: 0; }
.exos-coin-row-tag {
  font-size: 9px; font-family: "Geist Mono", monospace;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 2px 6px; border-radius: 4px;
  background: var(--gain-soft); color: var(--gain);
}
.exos-coin-status {
  padding: 12px; color: var(--text-mute); font-size: 12px;
  display: flex; align-items: center; gap: 6px;
  border-bottom: 1px solid var(--line);
}
.exos-coin-status.err { color: var(--loss); }
.exos-coin-status.err svg { color: var(--loss); }

.exos-add-custom-btn {
  display: flex; align-items: center; gap: 8px;
  margin-top: 10px; width: 100%; padding: 10px 12px;
  background: transparent; border: 1px dashed var(--line); border-radius: 8px;
  color: var(--text-mute); cursor: pointer; font: inherit; font-size: 13px;
  transition: border-color .12s, color .12s, background .12s;
}
.exos-add-custom-btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

.exos-custom-form { padding: 14px; background: var(--bg-elev-2); border: 1px solid var(--line); border-radius: 10px; }
@media (max-width: 760px) {
  .exos-table th:nth-child(3), .exos-table td:nth-child(3),
  .exos-table th:nth-child(7), .exos-table td:nth-child(7) { display: none; }
}
`;
(function(){ if(document.getElementById("exos-portfolio-styles")) return; const t=document.createElement("style"); t.id="exos-portfolio-styles"; t.textContent=PORTFOLIO_STYLES; document.head.appendChild(t); })();

window.Portfolio = Portfolio;
