// Chain deployments showcase.
//
// Rendered by Viewer when file.kind === 'chains'. Pure static list — every
// new chain deployment = one line in CHAINS below. No DB, no API, no
// network call. Each card is a clickable link to the canonical block
// explorer for that contract.
//
// Logos are inlined SVG approximations so the section works fully offline
// once cached. Brand colours match each chain's identity.

// Order follows JB's canonical deployment list (2026-07-02). Contract
// addresses + explorer URLs are the exact values he provided. `id` maps to
// the logo file at /logos/<id>.svg.
const CHAINS = [
  {
    id: 'base',
    name: 'Base',
    chainShort: 'BASE',
    chainId: 8453,
    status: 'live',
    color: '#0052FF',
    contract: '0xEa4Fcd4dE37eC038947a6834751E71Bb8FE68fff',
    explorer: 'https://basescan.org/address/0xEa4Fcd4dE37eC038947a6834751E71Bb8FE68fff',
    explorerName: 'BaseScan',
  },
  {
    id: 'megaeth',
    name: 'MegaETH',
    chainShort: 'MEGA',
    chainId: 4326,
    status: 'live',
    color: '#7B61FF',
    contract: '0x543b44aCf892e190b574780ea5f228f59d26B23c',
    explorer: 'https://megaeth.blockscout.com/address/0x543b44aCf892e190b574780ea5f228f59d26B23c',
    explorerName: 'Blockscout',
  },
  {
    id: 'arbitrum',
    name: 'Arbitrum One',
    chainShort: 'ARB',
    chainId: 42161,
    status: 'live',
    color: '#28A0F0',
    contract: '0x2c8cbe32da6feaeccf99ecee2900556a17a529ed',
    explorer: 'https://arbiscan.io/token/0x2c8cbe32da6feaeccf99ecee2900556a17a529ed',
    explorerName: 'Arbiscan',
  },
  {
    id: 'polygon',
    name: 'Polygon PoS',
    chainShort: 'POL',
    chainId: 137,
    status: 'live',
    color: '#8247E5',
    contract: '0x3319d8A0A7f742AAC63D586E7bb846a9ee8218Ab',
    explorer: 'https://polygonscan.com/token/0x3319d8A0A7f742AAC63D586E7bb846a9ee8218Ab',
    explorerName: 'PolygonScan',
  },
  {
    id: 'gnosis',
    name: 'Gnosis Chain',
    chainShort: 'GNO',
    chainId: 100,
    status: 'live',
    color: '#133629',
    contract: '0x68115ffa8bf088289b80b1e17cd486b5752492aa',
    explorer: 'https://gnosisscan.io/token/0x68115ffa8bf088289b80b1e17cd486b5752492aa',
    explorerName: 'GnosisScan',
    bridge: 'https://bridge.gnosischain.com/',
  },
  {
    id: 'unichain',
    name: 'Unichain',
    chainShort: 'UNI',
    chainId: 130,
    status: 'live',
    color: '#F50DB4',
    contract: '0x8eDe8Ab36BFED06ed6EC491a4E3ba8813C8A21a1',
    explorer: 'https://uniscan.xyz/address/0x8eDe8Ab36BFED06ed6EC491a4E3ba8813C8A21a1',
    explorerName: 'Uniscan',
  },
  {
    id: 'celo',
    name: 'Celo',
    chainShort: 'CELO',
    chainId: 42220,
    status: 'live',
    color: '#FCFF52',
    contract: '0xbAa2F11995aDe2fAB5323fb5884Cd7331CBE575d',
    explorer: 'https://celoscan.io/address/0xbAa2F11995aDe2fAB5323fb5884Cd7331CBE575d',
    explorerName: 'CeloScan',
  },
  {
    id: 'ink',
    name: 'Ink',
    chainShort: 'INK',
    chainId: 57073,
    status: 'live',
    color: '#7132F5',
    contract: '0x8eDe8Ab36BFED06ed6EC491a4E3ba8813C8A21a1',
    explorer: 'https://explorer.inkonchain.com/address/0x8eDe8Ab36BFED06ed6EC491a4E3ba8813C8A21a1',
    explorerName: 'Ink Explorer',
  },
  {
    id: 'optimism',
    name: 'OP Mainnet',
    chainShort: 'OP',
    chainId: 10,
    status: 'live',
    color: '#FF0420',
    contract: '0x5355e007F4875c99e571818b28C9CC9f231D0269',
    explorer: 'https://optimistic.etherscan.io/address/0x5355e007F4875c99e571818b28C9CC9f231D0269',
    explorerName: 'Optimistic Etherscan',
  },
  {
    id: 'robinhood',
    name: 'Robinhood Chain',
    chainShort: 'RHC',
    chainId: 4663,
    status: 'live',
    color: '#00C805',
    contract: '0x4cE63b5E213337aDF891c2819d0246b15F44BAca',
    explorer: 'https://robinhoodchain.blockscout.com/token/0x4cE63b5E213337aDF891c2819d0246b15F44BAca',
    explorerName: 'Blockscout',
    logo: 'robinhood.png', // brand asset is a PNG, not SVG (default is /logos/<id>.svg)
  },
];

function shortAddr(addr) {
  if (!addr || addr.length < 12) return addr || '—';
  return `${addr.slice(0, 6)}…${addr.slice(-4)}`;
}

// Pick black or white text for a solid background by relative luminance, so a
// light brand colour (e.g. Celo yellow) in the fallback badge stays legible.
function readableTextOn(hex) {
  const m = /^#?([0-9a-f]{6})$/i.exec(hex || '');
  if (!m) return '#ffffff';
  const n = parseInt(m[1], 16);
  const r = (n >> 16) & 255, g = (n >> 8) & 255, b = n & 255;
  const L = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
  return L > 0.6 ? '#1a1a1a' : '#ffffff';
}

function ChainLogo({ chain }) {
  // Official brand logo served from /logos/<id>.svg, on a clean white tile.
  // If the asset is missing/fails, fall back to a brand-colour lettered badge
  // so a card never renders empty.
  const [failed, setFailed] = React.useState(false);
  const tile = {
    width: 56, height: 56, borderRadius: 14, flex: '0 0 auto',
    display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden',
  };
  if (failed) {
    return (
      <span style={{ ...tile, background: chain.color }}>
        <span className="mono" style={{ color: readableTextOn(chain.color), fontSize: 24, fontWeight: 700, letterSpacing: '-0.02em' }}>
          {chain.chainShort.charAt(0)}
        </span>
      </span>
    );
  }
  return (
    <span style={{ ...tile, background: '#FFFFFF', border: '1px solid var(--border)' }}>
      <img
        src={`/logos/${chain.logo || `${chain.id}.svg`}`}
        alt=""
        width="36" height="36"
        style={{ width: 36, height: 36, objectFit: 'contain', display: 'block' }}
        onError={() => setFailed(true)}
      />
    </span>
  );
}

function ChainCard({ chain }) {
  const [copied, setCopied] = React.useState(false);
  const handleCopy = (e) => {
    e.preventDefault();
    e.stopPropagation();
    try {
      navigator.clipboard.writeText(chain.contract);
      setCopied(true);
      setTimeout(() => setCopied(false), 1400);
    } catch (err) { /* private mode / permissions */ }
  };

  // Outbound clicks aren't audited individually — the viewer already
  // tracks doc.opened/scrolled/closed for the 'chains' doc, and the click
  // destination is an external block explorer outside our tracking surface.

  const isLive = chain.status === 'live';
  const pillLabel = isLive ? 'LIVE' : 'TESTNET';

  return (
    <a
      className="chain-card"
      href={chain.explorer}
      target="_blank"
      rel="noopener noreferrer"
      style={{ '--chain-color': chain.color }}
    >
      <div className="chain-card-head">
        <ChainLogo chain={chain} />
        <div className="chain-card-title">
          <div className="chain-card-name">{chain.name}</div>
          <div className="chain-card-meta">
            <span className={`chain-pill chain-pill-${isLive ? 'live' : 'testnet'}`}>
              <span className="chain-pill-dot" />
              {pillLabel}
            </span>
            <span className="chain-card-id mono">Chain ID {chain.chainId}</span>
          </div>
        </div>
      </div>

      <div className="chain-card-addr-row">
        <span className="chain-card-addr-label">Token</span>
        <span className="chain-card-addr mono" title={chain.contract}>{shortAddr(chain.contract)}</span>
        <button
          type="button"
          className="chain-card-copy"
          onClick={handleCopy}
          aria-label={`Copy ${chain.name} contract address`}
        >
          {copied ? '✓ Copied' : 'Copy'}
        </button>
      </div>

      <div className="chain-card-cta">
        View on {chain.explorerName} <span aria-hidden="true">→</span>
      </div>

      {chain.bridge && (
        <button
          type="button"
          className="chain-card-bridge"
          onClick={(e) => {
            e.preventDefault();
            e.stopPropagation();
            window.open(chain.bridge, '_blank', 'noopener,noreferrer');
          }}
        >
          Bridge to {chain.name} <span aria-hidden="true">↗</span>
        </button>
      )}
    </a>
  );
}

function ChainsBody({ file }) {
  const liveCount = CHAINS.filter(c => c.status === 'live').length;
  const testCount = CHAINS.filter(c => c.status === 'testnet').length;

  return (
    <div className="chains-body">
      <div className="chains-header">
        <div className="chains-header-title">wstGBP — Deployments</div>
        <div className="chains-header-sub">
          The wrapper is live on {liveCount} chain{liveCount === 1 ? '' : 's'}
          {testCount > 0 ? `, with ${testCount} testnet deployment${testCount === 1 ? '' : 's'}` : ''}.
          Same contract, same audit, same supply mechanics. Tap a card to verify on the canonical block explorer.
        </div>
      </div>

      <div className="chains-grid">
        {CHAINS.map(c => <ChainCard key={c.id} chain={c} />)}
      </div>

      <div className="chains-footnote">
        Contract addresses are immutable references to the on-chain wstGBP wrapper.
        Block-explorer data is the source of truth, not anything shown here.
      </div>
    </div>
  );
}
