/* global React, POOLS, HISTORY, fmt, quote, formatContractError,
   I, ModeBadge, Mono, Hash, Stat, useGetPool, useNetwork */

const { useState, useEffect, useMemo } = React;

// =============================================================
// PoolDetail (root)
// =============================================================
function PoolDetail({ poolId, go, wallet, showError, onTx }) {
  const net = useNetwork();
  const pool = POOLS.find(p => p.id === poolId);
  const [tab, setTab] = useState("trade");
  // Live-fetch only the demo pool ("stgy"). When demoTokenPrincipal is null
  // the hook is a no-op (returns { data: null }) -- UI stays on the mock with
  // a "mock data" badge. When set, the hook polls every 30 s; net's id is in
  // the hook's deps array so a network switch re-fires against the new host.
  const isDemo = poolId === "stgy";
  const livePool = useGetPool(isDemo ? net.demoTokenPrincipal : null, net);
  if (!pool) return <NotFound go={go} network={net.label}/>;

  const isBonding = pool.mode === "bonding";

  return (
    <div className="page">
      <div style={{ marginBottom: 12 }}>
        <button className="btn btn-ghost" onClick={() => go("pools")} style={{ fontSize: 12 }}>
          <span style={{ display: "inline-block", transform: "rotate(180deg)" }}><I.arrow/></span> Pools
        </button>
      </div>

      {isDemo && (
        <div style={{ marginBottom: 10 }}>
          {net.demoTokenPrincipal == null ? (
            <span className="badge" style={{ background: "var(--surface-2)", color: "var(--ink-3)", border: "1px solid var(--line)" }}>
              demo · mock data
            </span>
          ) : livePool.error ? (
            <span className="badge" style={{ background: "rgba(239,68,68,0.12)", color: "var(--red)" }}>
              demo · live read failed ({String(livePool.error.message || livePool.error).slice(0, 40)})
            </span>
          ) : livePool.data ? (
            <span className="badge" style={{ background: "rgba(34,197,94,0.12)", color: "var(--green)" }}>
              demo · live · polled 30s
            </span>
          ) : (
            <span className="badge" style={{ background: "var(--surface-2)", color: "var(--ink-3)", border: "1px solid var(--line)" }}>
              demo · loading…
            </span>
          )}
        </div>
      )}

      <Header pool={pool}/>

      <div style={{ marginTop: 18 }}>
        {isBonding
          ? <BondingHero pool={pool}/>
          : <ReservesHero pool={pool}/>}
      </div>

      <Tabs
        value={tab}
        onChange={setTab}
        pool={pool}
      />

      <div style={{ marginTop: 18 }}>
        {tab === "trade"   && <TradePanel pool={pool} wallet={wallet} showError={showError} onTx={onTx}/>}
        {tab === "burn"    && <BurnPanel pool={pool} wallet={wallet} showError={showError} onTx={onTx}/>}
        {tab === "history" && <HistoryPanel pool={pool} go={go}/>}
      </div>
    </div>
  );
}

function NotFound({ go, network }) {
  return (
    <div className="page">
      <div className="card" style={{ textAlign: "center", padding: 40 }}>
        <h2 style={{ marginTop: 0 }}>Pool not found</h2>
        <p className="muted">No pool exists for this id on {network}.</p>
        <button className="btn" onClick={() => go("pools")}>Back to pools</button>
      </div>
    </div>
  );
}

// =============================================================
// Header
// =============================================================
function Header({ pool }) {
  // Glow effect for graduations: pool was previously bonding (had real reserves).
  const justGraduated = pool.mode === "graduated"
    && pool.bondedStxCollected > 0
    && pool.bondedTokensSold > 0;
  const [glow, setGlow] = useState(justGraduated);
  useEffect(() => {
    if (!justGraduated) return;
    const t = setTimeout(() => setGlow(false), 3000);
    return () => clearTimeout(t);
  }, [justGraduated]);

  const badgeStyle = glow
    ? { boxShadow: "0 0 0 4px var(--purple-glow)", transition: "box-shadow 0.6s" }
    : { transition: "box-shadow 0.6s" };

  return (
    <div className="pool-header">
      <h1 className="title h1" style={{ fontSize: 32, margin: 0 }}>
        {pool.name} <span className="mono dim" style={{ fontSize: 18 }}>&mdash; {pool.symbol}</span>
      </h1>
      <div className="meta" style={{ marginTop: 8 }}>
        <span style={badgeStyle}>
          <ModeBadge mode={pool.mode} paused={!pool.active}/>
        </span>
        <Hash>{pool.principal}</Hash>
        <a className="dim" style={{ display: "inline-flex", alignItems: "center" }}><I.ext/></a>
        <span className="dim" style={{ fontSize: 12 }}>created {pool.createdAt}</span>
      </div>
    </div>
  );
}

// =============================================================
// Tabs strip
// =============================================================
function Tabs({ value, onChange, pool }) {
  const isBonding = pool.mode === "bonding";
  const stxToGrad = isBonding ? Math.max(0, pool.graduationThreshold - pool.bondedStxCollected) : 0;
  const items = [
    { id: "trade",   label: "Trade",   disabled: false },
    { id: "burn",    label: "Burn",    disabled: false,
      // Tab itself is clickable so user sees the disabled card; tooltip explains why
      tooltip: isBonding ? `Available after graduation. Needs ${fmt.stx(stxToGrad)} STX more.` : null },
    { id: "history", label: "History", disabled: false },
  ];
  return (
    <div style={{
      display: "flex",
      gap: 4,
      marginTop: 22,
      borderBottom: "1px solid var(--line)",
    }}>
      {items.map(it => {
        const active = value === it.id;
        const dim = it.id === "burn" && isBonding;
        return (
          <button
            key={it.id}
            onClick={() => onChange(it.id)}
            title={it.tooltip || ""}
            style={{
              padding: "10px 14px",
              fontSize: 13,
              fontWeight: 500,
              border: 0,
              background: "transparent",
              color: active ? "var(--ink)" : (dim ? "var(--ink-3)" : "var(--ink-2)"),
              borderBottom: active ? "2px solid var(--purple)" : "2px solid transparent",
              marginBottom: -1,
              cursor: "pointer",
            }}
          >
            {it.label}
          </button>
        );
      })}
    </div>
  );
}

// =============================================================
// Bonding hero
// =============================================================
function BondingHero({ pool }) {
  const collected = pool.bondedStxCollected;
  const threshold = pool.graduationThreshold;
  const progress = Math.min(100, Math.round((collected / threshold) * 100));
  const almost = progress >= 90;

  const xR = pool.virtualStx + pool.bondedStxCollected;
  const yR = pool.virtualToken - pool.bondedTokensSold;
  const spot = yR > 0 ? xR / yR : 0;

  const status =
    progress < 50  ? { text: "EARLY -- high upside, high slippage",                 color: "var(--ink-3)" } :
    progress < 90  ? { text: "BONDING -- gathering momentum",                       color: "var(--orange)" } :
                     { text: "ALMOST GRADUATED -- next big buy may unlock real reserves", color: "var(--orange)" };

  return (
    <div className="bonding-hero">
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 14, flexWrap: "wrap", gap: 8 }}>
        <div style={{ display: "inline-flex", alignItems: "center", gap: 10 }}>
          <ModeBadge mode="bonding"/>
          <span style={{ fontWeight: 600 }}>{pool.symbol}</span>
        </div>
        <div className="num-stack" style={{ alignItems: "flex-end" }}>
          <div className="lbl">Spot price</div>
          <div className="big mono">{spot.toExponential(3)} <span style={{ color: "var(--orange)", fontSize: 13 }}>STX/{pool.symbol}</span></div>
        </div>
      </div>

      <div className="bonding-hero-progress">
        <div
          className={"bonding-hero-progress-fill" + (almost ? " almost" : "")}
          style={{ width: progress + "%" }}
        />
      </div>

      <div style={{ display: "flex", justifyContent: "space-between", marginTop: 10, gap: 12, flexWrap: "wrap" }}>
        <span className="bonding-hero-meta">
          <Mono>{fmt.stx(collected)} STX</Mono> collected
        </span>
        <span className="bonding-hero-meta" style={{ textAlign: "right" }}>
          <Mono>{fmt.stx(threshold)} STX</Mono> threshold &middot; <span className="mono">{progress}%</span>
        </span>
      </div>

      <div className="mono" style={{ marginTop: 10, fontSize: 12, color: status.color, letterSpacing: "0.04em" }}>
        {status.text}
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginTop: 18 }}>
        <div className="card" style={{ padding: 14 }}>
          <div className="eyebrow" style={{ marginBottom: 8 }}>Virtual reserves</div>
          <div className="kv"><span className="k">virtual-stx</span><span className="v"><Mono>{fmt.stx(pool.virtualStx)} STX</Mono></span></div>
          <div className="kv"><span className="k">virtual-token</span><span className="v"><Mono>{fmt.big(pool.virtualToken)} {pool.symbol}</Mono></span></div>
          <div className="muted" style={{ fontSize: 11.5, marginTop: 6 }}>
            Read-only at create-time. Cannot be modified.
          </div>
        </div>
        <div className="card" style={{ padding: 14 }}>
          <div className="eyebrow" style={{ marginBottom: 8 }}>Accumulated (real)</div>
          <div className="kv"><span className="k">bonded-stx-collected</span><span className="v"><Mono>{fmt.stx(pool.bondedStxCollected)} STX</Mono></span></div>
          <div className="kv"><span className="k">bonded-tokens-sold</span><span className="v"><Mono>{fmt.big(pool.bondedTokensSold)} {pool.symbol}</Mono></span></div>
          <div className="muted" style={{ fontSize: 11.5, marginTop: 6 }}>
            Migrates atomically to real reserves on graduation.
          </div>
        </div>
      </div>
    </div>
  );
}

// =============================================================
// Reserves hero (direct / graduated)
// =============================================================
function ReservesHero({ pool }) {
  const spot = pool.tokenReserve > 0 ? pool.stxReserve / pool.tokenReserve : 0;
  const changeColor = pool.change24 >= 0 ? "var(--green)" : "var(--red)";
  const isGraduated = pool.mode === "graduated";

  return (
    <div className="card" style={{ padding: 18 }}>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(5, 1fr)", gap: 12 }}>
        <Stat label="STX reserve"   value={<><Mono>{fmt.stxShort(pool.stxReserve)}</Mono> <span style={{ color: "var(--purple)", fontSize: 13 }}>STX</span></>} sub="real reserve"/>
        <Stat label="Token reserve" value={<><Mono>{fmt.big(pool.tokenReserve)}</Mono> <span style={{ color: "var(--ink-3)", fontSize: 13 }}>{pool.symbol}</span></>} sub="in pool"/>
        <Stat label="Spot price"    value={<span className="mono">{spot.toExponential(3)}</span>} sub={`STX / ${pool.symbol}`}/>
        <Stat label="TVL"           value={<><Mono>{fmt.stxShort(pool.tvl)}</Mono> <span style={{ color: "var(--purple)", fontSize: 13 }}>STX</span></>} sub="locked value"/>
        <Stat label="24h"
              value={<>
                <span className="mono">{fmt.stxShort(pool.vol24)}</span>
                <span style={{ color: changeColor, marginLeft: 8, fontFamily: "var(--font-mono)", fontSize: 13 }}>{fmt.pct(pool.change24)}</span>
              </>}
              sub="vol &middot; change"/>
      </div>
      {isGraduated && (
        <div className="muted mono" style={{ marginTop: 14, fontSize: 11.5, color: "var(--green)" }}>
          &uarr; Graduated from bonding curve on {pool.createdAt}
        </div>
      )}
    </div>
  );
}

// =============================================================
// Trade panel
// =============================================================
function TradePanel({ pool, wallet, showError, onTx }) {
  const paused = !pool.active;
  const [dir, setDir] = useState("buy");
  const [amountIn, setAmountIn] = useState("");
  const [slippage, setSlippage] = useState(0.5);
  const [slippageCustom, setSlippageCustom] = useState("");
  const [deadlineBlocks, setDeadlineBlocks] = useState(10);
  const [deadlineCustom, setDeadlineCustom] = useState("20");
  const [recipient, setRecipient] = useState(wallet && wallet.address ? wallet.address : "");

  useEffect(() => {
    if (wallet && wallet.address && !recipient) setRecipient(wallet.address);
  }, [wallet]);

  const slipPct = slippage === "custom" ? parseFloat(slippageCustom) || 0 : slippage;
  const q = useMemo(() => quote({ pool, mode: pool.mode, dir, amountIn }), [pool, dir, amountIn]);

  const inUnit  = dir === "buy" ? "STX" : pool.symbol;
  const outUnit = dir === "buy" ? pool.symbol : "STX";

  const setMax = () => {
    if (dir === "buy") {
      const cap = pool.mode === "bonding"
        ? Math.max(0, pool.graduationThreshold - pool.bondedStxCollected)
        : pool.tvl * 0.5;
      setAmountIn(cap.toFixed(2));
    } else {
      const tokensInPool = pool.mode === "bonding"
        ? pool.bondedTokensSold * 0.5
        : pool.tokenReserve * 0.1;
      setAmountIn(Math.floor(tokensInPool).toString());
    }
  };

  const submit = () => {
    if (!wallet || !wallet.connected) {
      if (wallet && typeof wallet.connect === "function") return wallet.connect();
      return showError("Connect a wallet first.");
    }
    if (!amountIn || !q) return showError("Enter a valid amount.");
    onTx({
      summary: `Swap ${dir} on ${pool.symbol}`,
      detail: `${amountIn} ${inUnit} -> ~${q.out.toFixed(2)} ${outUnit} (slip ${slipPct}%)`,
    });
  };

  const minOut   = q ? q.out * (1 - slipPct / 100) : 0;
  const fee      = q ? q.feeBps / 100 : 0;
  const feeBreak = pool.mode === "bonding"
    ? "1% (0.9% to fee-receiver + 0.1% to protocol)"
    : "5% (4.5% to fee-receiver + 0.5% to protocol)";

  return (
    <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 18 }}>
      {/* LEFT -- the form */}
      <div className="card">
        {paused && (
          <div style={{
            background: "rgba(239, 68, 68, 0.15)",
            border: "1px solid var(--red)",
            padding: "12px 16px",
            borderRadius: "var(--radius)",
            marginBottom: 16,
          }}>
            <span style={{
              color: "var(--red)",
              fontFamily: "var(--font-mono)",
              fontSize: 12,
              letterSpacing: "0.08em",
              textTransform: "uppercase",
            }}>
              Pool paused -- trading is disabled
            </span>
          </div>
        )}
        <div style={{ display: "flex", gap: 6, marginBottom: 14 }}>
          <SegBtn active={dir === "buy"}  onClick={() => setDir("buy")}  disabled={paused}>Buy</SegBtn>
          <SegBtn active={dir === "sell"} onClick={() => setDir("sell")} disabled={paused}>Sell</SegBtn>
        </div>

        <div className="field" style={{ marginBottom: 14 }}>
          <label className="muted" style={{ fontSize: 11, fontFamily: "var(--font-mono)", textTransform: "uppercase", letterSpacing: "0.08em" }}>
            You pay ({inUnit})
          </label>
          <div style={{ display: "flex", gap: 8 }}>
            <input
              className="input mono"
              placeholder={dir === "buy" ? "0.0 STX" : `0 ${pool.symbol}`}
              value={amountIn}
              onChange={(e) => setAmountIn(e.target.value)}
              disabled={paused}
            />
            <button className="btn" onClick={setMax} disabled={paused}>Max</button>
          </div>
        </div>

        <div className="field" style={{ marginBottom: 14 }}>
          <label className="muted" style={{ fontSize: 11, fontFamily: "var(--font-mono)", textTransform: "uppercase", letterSpacing: "0.08em" }}>
            Slippage tolerance
          </label>
          <div style={{ display: "flex", gap: 6, flexWrap: "wrap", alignItems: "center" }}>
            {[0.1, 0.5, 1.0].map(s => (
              <SegBtn key={s} active={slippage === s} onClick={() => setSlippage(s)} disabled={paused}>{s}%</SegBtn>
            ))}
            <SegBtn active={slippage === "custom"} onClick={() => setSlippage("custom")} disabled={paused}>Custom</SegBtn>
            {slippage === "custom" && (
              <input
                className="input mono"
                style={{ width: 80, padding: "6px 8px", fontSize: 12 }}
                placeholder="2.5"
                value={slippageCustom}
                onChange={(e) => setSlippageCustom(e.target.value)}
                disabled={paused}
              />
            )}
          </div>
        </div>

        <div className="field" style={{ marginBottom: 14 }}>
          <label className="muted" style={{ fontSize: 11, fontFamily: "var(--font-mono)", textTransform: "uppercase", letterSpacing: "0.08em" }}>
            Deadline (blocks)
          </label>
          <div style={{ display: "flex", gap: 6 }}>
            {[5, 10].map(b => (
              <SegBtn key={b} active={deadlineBlocks === b} onClick={() => setDeadlineBlocks(b)} disabled={paused}>{b}</SegBtn>
            ))}
            <SegBtn active={deadlineBlocks === "custom"} onClick={() => setDeadlineBlocks("custom")} disabled={paused}>Custom</SegBtn>
            {deadlineBlocks === "custom" && (
              <input
                className="input mono"
                style={{ width: 80 }}
                placeholder="20"
                value={deadlineCustom}
                onChange={e => setDeadlineCustom(e.target.value)}
                disabled={paused}
              />
            )}
          </div>
        </div>

        <div className="field" style={{ marginBottom: 14 }}>
          <label className="muted" style={{ fontSize: 11, fontFamily: "var(--font-mono)", textTransform: "uppercase", letterSpacing: "0.08em" }}>
            Recipient
          </label>
          <input
            className="input mono"
            placeholder="ST..."
            value={recipient}
            onChange={(e) => setRecipient(e.target.value)}
            disabled={paused}
          />
        </div>

        <button
          className="btn btn-primary"
          style={{ width: "100%", justifyContent: "center", padding: "10px 14px" }}
          disabled={paused || (!!(wallet && wallet.connected) && (!amountIn || !q))}
          onClick={submit}
        >
          {paused ? "Pool paused" : (wallet && wallet.connected ? "Sign and send" : "Connect wallet")}
        </button>
      </div>

      {/* RIGHT -- live quote preview */}
      <div className="card">
        <div className="eyebrow" style={{ marginBottom: 12 }}>Quote preview</div>
        {!amountIn ? (
          <p className="muted" style={{ fontSize: 13 }}>Enter an amount to see the quote.</p>
        ) : !q ? (
          <div style={{ padding: 12, border: "1px solid var(--red)", borderRadius: 8, color: "var(--red)", fontSize: 13 }}>
            <strong>{formatContractError("u216")}</strong>
          </div>
        ) : (
          <>
            <div className="kv"><span className="k">You receive</span>
              <span className="v"><Mono>{q.out.toFixed(2)} {outUnit}</Mono></span></div>
            <div className="kv"><span className="k">Effective price</span>
              <span className="v mono">{(parseFloat(amountIn) / q.out).toExponential(3)}</span></div>
            <div className="kv"><span className="k">Price impact</span>
              <span className="v mono" style={{ color: q.priceImpact > 5 ? "var(--orange)" : "var(--ink)" }}>
                {q.priceImpact.toFixed(2)}%
              </span></div>
            <div className="kv"><span className="k">Fee ({fee}%)</span>
              <span className="v" style={{ fontSize: 11.5, color: "var(--ink-2)" }}>{feeBreak}</span></div>
            <div className="kv"><span className="k">Min received (slip)</span>
              <span className="v"><Mono>{minOut.toFixed(2)} {outUnit}</Mono></span></div>

            <div className="hr"/>
            <div className="eyebrow" style={{ marginBottom: 8, fontSize: 10.5 }}>Post-condition (deny mode)</div>
            <div className="muted mono" style={{ fontSize: 11.5, lineHeight: 1.6 }}>
              {dir === "buy" ? (
                <>
                  Sender STX out: &le; <Mono>{amountIn} STX</Mono><br/>
                  Recipient {pool.symbol} in: &ge; <Mono>{minOut.toFixed(2)} {pool.symbol}</Mono>
                </>
              ) : (
                <>
                  Sender {pool.symbol} out: &le; <Mono>{amountIn} {pool.symbol}</Mono><br/>
                  Recipient STX in: &ge; <Mono>{minOut.toFixed(2)} STX</Mono>
                </>
              )}
            </div>
          </>
        )}
      </div>
    </div>
  );
}

function SegBtn({ active, onClick, children, disabled }) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      style={{
        padding: "6px 12px",
        borderRadius: 6,
        border: "1px solid " + (active ? "var(--purple)" : "var(--line)"),
        background: active ? "var(--purple)" : "var(--surface)",
        color: active ? "var(--ink)" : "var(--ink-2)",
        fontFamily: "var(--font-mono)",
        fontSize: 12,
        fontWeight: 500,
        cursor: disabled ? "not-allowed" : "pointer",
        opacity: disabled ? 0.5 : 1,
      }}
    >
      {children}
    </button>
  );
}

// =============================================================
// Burn panel
// =============================================================
function BurnPanel({ pool, wallet, showError, onTx }) {
  const net = useNetwork();
  if (pool.mode === "bonding") return <BurnDisabledCard pool={pool}/>;

  const paused = !pool.active;
  const [stxIn, setStxIn] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const a = parseFloat(stxIn);
  const tokensOut = a > 0 && pool.stxReserve > 0
    ? (pool.tokenReserve * a) / (pool.stxReserve + a)
    : 0;

  const burnedPct = pool.burnTotal > 0
    ? (pool.burnTotal / (pool.tokenReserve + pool.burnTotal)) * 100
    : 0;

  const submit = async () => {
    if (!wallet || !wallet.connected) {
      if (wallet && typeof wallet.connect === "function") return wallet.connect();
      return showError("Connect a wallet first.");
    }
    if (!a || a <= 0) return showError("Enter a valid amount.");
    const stxAmount = Math.floor(a * 1_000_000); // STX -> uSTX
    const tokenPrincipal = net.demoTokenPrincipal
      || `${net.deployer}.dummy-token`;

    // Layer C guardrail: bail before the wallet sees the tx if its active
    // network does not match the app. Cancel/reconnect both throw; quiet exit.
    try {
      await window.assertWalletReady(net, wallet);
    } catch (_) {
      return;
    }

    setSubmitting(true);
    try {
      // swap-and-burn signature: (token, stx-in, min-tokens-burned, deadline)
      // - min-tokens-burned: 0 = accept any (no slippage protection for demo)
      // - deadline: current block height + 100 (~16 min buffer on Stacks)
      let deadline = 99_999_999; // fallback if /v2/info fails
      try {
        const info = await fetch(`${net.apiHost}/v2/info`).then(r => r.json());
        deadline = (info.stacks_tip_height || 0) + 100;
      } catch (_) {}

      const { txid } = await window.HiroApi.signAndBroadcast({
        contractAddress: net.deployer,
        contractName: net.singletonName,
        fnName: "swap-and-burn",
        fnArgs: [
          { kind: "principal", value: tokenPrincipal },
          { kind: "uint",      value: stxAmount },
          { kind: "uint",      value: 0 },         // min-tokens-burned: 0 = no slippage check
          { kind: "uint",      value: deadline },  // block-height + 100
        ],
        // "allow" mode + empty PCs: wallet permits all transfers (incl. the
        // STX transfer the contract makes). For mainnet we'd build a strict
        // Pc.principal(sender).willSendEq(stxAmount).ustx() -- defer to M3.
        postConditions: [],
        postConditionMode: "allow",
        cfg: net,
      });
      onTx({
        summary: `swap-and-burn on ${pool.symbol}`,
        detail:  `${stxIn} STX -> ~${tokensOut.toFixed(0)} ${pool.symbol} (target: ${tokenPrincipal})`,
        txid,
      });
    } catch (e) {
      showError(e.message || String(e));
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 18 }}>
      <div className="card">
        {paused && (
          <div style={{
            background: "rgba(239, 68, 68, 0.15)",
            border: "1px solid var(--red)",
            padding: "12px 16px",
            borderRadius: "var(--radius)",
            marginBottom: 16,
          }}>
            <span style={{
              color: "var(--red)",
              fontFamily: "var(--font-mono)",
              fontSize: 12,
              letterSpacing: "0.08em",
              textTransform: "uppercase",
            }}>
              Pool paused -- trading is disabled
            </span>
          </div>
        )}
        <div className="eyebrow" style={{ marginBottom: 12 }}>Permissionless burn</div>

        <div className="field" style={{ marginBottom: 14 }}>
          <label className="muted" style={{ fontSize: 11, fontFamily: "var(--font-mono)", textTransform: "uppercase", letterSpacing: "0.08em" }}>
            STX in (no fee)
          </label>
          <input
            className="input mono"
            placeholder="0.0 STX"
            value={stxIn}
            onChange={(e) => setStxIn(e.target.value)}
            disabled={paused}
          />
        </div>

        {a > 0 && (
          <div style={{ marginBottom: 14 }}>
            <div className="kv"><span className="k">Tokens to burn</span>
              <span className="v"><Mono>{fmt.num(Math.floor(tokensOut))} {pool.symbol}</Mono></span></div>
            <div className="kv"><span className="k">Recipient</span>
              <span className="v mono dim">none (burn address)</span></div>
            <div className="kv"><span className="k">Fee</span>
              <span className="v">0% &middot; <span className="mono dim">fee-free</span></span></div>
          </div>
        )}

        <button
          className="btn btn-primary"
          style={{ width: "100%", justifyContent: "center", padding: "10px 14px" }}
          disabled={paused || (!!(wallet && wallet.connected) && (!a || a <= 0 || submitting))}
          onClick={submit}
        >
          {paused ? "Pool paused"
            : !wallet || !wallet.connected ? "Connect wallet"
            : submitting ? "Confirm in wallet…"
            : "Swap and burn"}
        </button>

        <div className="muted" style={{ fontSize: 11.5, marginTop: 12 }}>
          <Mono>swap-and-burn</Mono> is permissionless and fee-free. Anyone (EOA, bot, contract) can call it
          to retire token supply against real STX.
        </div>
      </div>

      <div className="card">
        <div className="eyebrow" style={{ marginBottom: 12 }}>Burn telemetry</div>
        <div className="kv"><span className="k">24h burned</span>
          <span className="v"><Mono>{fmt.num(pool.burn24)} {pool.symbol}</Mono></span></div>
        <div className="kv"><span className="k">Total burned</span>
          <span className="v"><Mono>{fmt.big(pool.burnTotal)} {pool.symbol}</Mono></span></div>
        <div className="kv"><span className="k">% of supply retired</span>
          <span className="v mono">{burnedPct.toFixed(2)}%</span></div>
      </div>
    </div>
  );
}

function BurnDisabledCard({ pool }) {
  const remaining = Math.max(0, pool.graduationThreshold - pool.bondedStxCollected);
  return (
    <div className="card" style={{ textAlign: "center", padding: 32, border: "1px dashed var(--line)" }}>
      <div style={{ fontSize: 16, fontWeight: 600, marginBottom: 8 }}>Burn unlocks at graduation</div>
      <p className="muted" style={{ maxWidth: 480, margin: "0 auto", fontSize: 13 }}>
        This pool needs <Mono>{fmt.stx(remaining)} STX</Mono> more to graduate. Once graduated, anyone can
        call <Mono>swap-and-burn</Mono> to retire token supply against real STX.
      </p>
    </div>
  );
}

// =============================================================
// History panel
// =============================================================
function HistoryPanel({ pool, go }) {
  const events = HISTORY.filter(e => e.pool === pool.id);
  if (events.length === 0) {
    return (
      <div className="card" style={{ textAlign: "center", padding: 32 }}>
        <p className="muted">No events recorded for this pool yet.</p>
      </div>
    );
  }
  return (
    <div className="card" style={{ padding: 0 }}>
      {events.map((e, i) => (
        <HistoryRow key={i} event={e} pool={pool} last={i === events.length - 1}/>
      ))}
    </div>
  );
}

function HistoryRow({ event, pool, last }) {
  let icon, accent, line, highlight = false;
  if (event.kind === "swap") {
    icon = <I.swap/>;
    accent = "var(--purple)";
    line = event.side === "buy"
      ? <><Mono>{fmt.stx(event.stx)} STX</Mono> <I.arrow/> <Mono>{fmt.num(event.tokens)} {pool.symbol}</Mono> &middot; fee <Mono>{fmt.stx(event.fee)} STX</Mono></>
      : <><Mono>{fmt.num(event.tokens)} {pool.symbol}</Mono> <I.arrow/> <Mono>{fmt.stx(event.stx)} STX</Mono> &middot; fee <Mono>{fmt.stx(event.fee)} STX</Mono></>;
  } else if (event.kind === "swap-and-burn") {
    icon = <I.fire/>;
    accent = "var(--orange)";
    line = <><Mono>{fmt.stx(event.stx)} STX</Mono> &rarr; <Mono>{fmt.num(event.tokens)} {pool.symbol}</Mono> burned &middot; fee-free</>;
  } else if (event.kind === "graduated") {
    icon = <I.shield/>;
    accent = "var(--green)";
    highlight = true;
    line = <><strong>Graduated</strong> &middot; bonding curve migrated to direct mode</>;
  } else if (event.kind === "pool-active") {
    icon = <I.pause/>;
    accent = event.state ? "var(--green)" : "var(--red)";
    line = <>Pool {event.state ? "resumed" : "paused"} by <Mono>{event.who}</Mono></>;
  } else {
    icon = <I.list/>;
    accent = "var(--ink-3)";
    line = <>{event.kind}</>;
  }
  return (
    <div style={{
      display: "flex",
      alignItems: "center",
      gap: 12,
      padding: "12px 16px",
      borderBottom: last ? "0" : "1px solid var(--line)",
      background: highlight ? "rgba(16, 185, 129, 0.05)" : "transparent",
      boxShadow: highlight ? "inset 3px 0 0 var(--green)" : "none",
    }}>
      <span style={{ color: accent, display: "inline-flex", flexShrink: 0 }}>{icon}</span>
      <span style={{ flex: 1, fontSize: 13, minWidth: 0 }}>
        {line}
        {event.who && event.kind === "swap" && (
          <> &middot; <span className="mono dim" style={{ fontSize: 11 }}>{event.who}</span></>
        )}
      </span>
      <span className="muted mono" style={{ fontSize: 11, flexShrink: 0 }}>{event.time}</span>
      <a className="dim" style={{ display: "inline-flex", flexShrink: 0 }}><I.ext/></a>
    </div>
  );
}

// =============================================================
// Export
// =============================================================
Object.assign(window, { PoolDetail });
