"""
WalletSafe Frontend - Entity explorer, wallet search, risk page.
===============================================================
Served at /walletsafe/ as a single-page app.
Hits /api/v1/wallet/* endpoints directly via fetch().
"""

from fastapi import APIRouter
from fastapi.responses import HTMLResponse

router = APIRouter(tags=["walletsafe"])

WALLETSAFE_HTML = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WalletSafe - Wallet Intelligence Explorer</title>
<style>
  :root {
    --bg: #0a0a0f;
    --card: #12121a;
    --border: #1e1e2e;
    --text: #e0e0e8;
    --muted: #8888a0;
    --accent: #6c5ce7;
    --danger: #ff4757;
    --warning: #ffa502;
    --safe: #2ed573;
    --info: #1e90ff;
  }
  * { margin:0; padding:0; box-sizing:border-box; }
  body { background:var(--bg); color:var(--text); font-family:'Inter',system-ui,sans-serif; min-height:100vh; }

  nav { background:var(--card); border-bottom:1px solid var(--border); padding:12px 24px; display:flex; align-items:center; gap:24px; }
  nav .logo { font-size:20px; font-weight:700; color:var(--accent); letter-spacing:-0.5px; }
  nav .tab { color:var(--muted); cursor:pointer; padding:6px 14px; border-radius:6px; font-size:14px; transition:all .2s; }
  nav .tab:hover { color:var(--text); background:var(--border); }
  nav .tab.active { color:var(--accent); background:rgba(108,92,231,0.15); }

  .container { max-width:1200px; margin:0 auto; padding:24px; }

  /* Search bar */
  .search-bar { display:flex; gap:12px; margin-bottom:24px; }
  .search-bar input { flex:1; padding:12px 16px; background:var(--card); border:1px solid var(--border); border-radius:8px; color:var(--text); font-size:15px; outline:none; }
  .search-bar input:focus { border-color:var(--accent); }
  .search-bar select { padding:10px 12px; background:var(--card); border:1px solid var(--border); border-radius:8px; color:var(--text); font-size:14px; }
  .search-bar button { padding:10px 24px; background:var(--accent); color:#fff; border:none; border-radius:8px; font-size:15px; cursor:pointer; font-weight:600; }
  .search-bar button:hover { opacity:0.9; }

  /* Cards */
  .card { background:var(--card); border:1px solid var(--border); border-radius:12px; padding:20px; margin-bottom:16px; }
  .card h3 { font-size:16px; color:var(--muted); margin-bottom:12px; text-transform:uppercase; letter-spacing:0.5px; }

  /* Risk gauge */
  .risk-gauge { display:flex; align-items:center; gap:16px; margin:16px 0; }
  .risk-score { font-size:48px; font-weight:800; line-height:1; }
  .risk-label { font-size:18px; font-weight:600; padding:4px 12px; border-radius:6px; }
  .risk-minimal { color:var(--safe); background:rgba(46,213,115,0.1); }
  .risk-low { color:#7bed9f; background:rgba(123,237,159,0.1); }
  .risk-medium { color:var(--warning); background:rgba(255,165,2,0.1); }
  .risk-high { color:#ff6348; background:rgba(255,99,72,0.1); }
  .risk-critical { color:var(--danger); background:rgba(255,71,87,0.15); }
  .risk-unknown { color:var(--muted); background:rgba(136,136,160,0.1); }

  /* Risk bar */
  .risk-bar { height:8px; background:var(--border); border-radius:4px; overflow:hidden; margin-top:8px; }
  .risk-bar-fill { height:100%; border-radius:4px; transition:width .5s ease; }

  /* Profile grid */
  .profile-grid { display:grid; grid-template-columns:1fr 1fr; gap:16px; }
  @media(max-width:768px) { .profile-grid { grid-template-columns:1fr; } }
  .profile-field { display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid var(--border); }
  .profile-field:last-child { border:none; }
  .profile-field .label { color:var(--muted); font-size:13px; }
  .profile-field .value { font-weight:500; font-size:14px; word-break:break-all; }

  /* Tags */
  .tag { display:inline-block; padding:3px 8px; border-radius:4px; font-size:12px; margin:2px; }
  .tag-exchange { background:rgba(30,144,255,0.15); color:var(--info); }
  .tag-scam { background:rgba(255,71,87,0.15); color:var(--danger); }
  .tag-sanctioned { background:rgba(255,71,87,0.25); color:var(--danger); }
  .tag-defi { background:rgba(108,92,231,0.15); color:var(--accent); }
  .tag-bridge { background:rgba(255,165,2,0.15); color:var(--warning); }
  .tag-mev { background:rgba(255,165,2,0.15); color:var(--warning); }
  .tag-deployer { background:rgba(46,213,115,0.15); color:var(--safe); }
  .tag-wallet { background:rgba(136,136,160,0.15); color:var(--muted); }
  .tag-unknown { background:rgba(136,136,160,0.1); color:var(--muted); }

  /* Wallet list */
  .wallet-item { display:flex; align-items:center; gap:12px; padding:10px 0; border-bottom:1px solid var(--border); }
  .wallet-item:last-child { border:none; }
  .wallet-addr { font-family:monospace; font-size:13px; color:var(--info); cursor:pointer; }
  .wallet-addr:hover { text-decoration:underline; }
  .wallet-chain { font-size:11px; padding:2px 6px; border-radius:3px; background:rgba(108,92,231,0.15); color:var(--accent); }

  /* Deployer history */
  .deploy-item { padding:10px 0; border-bottom:1px solid var(--border); font-size:13px; }
  .deploy-item:last-child { border:none; }
  .deploy-token { font-family:monospace; color:var(--info); }

  /* Loading state */
  .loading { display:flex; align-items:center; justify-content:center; padding:60px; color:var(--muted); }
  .spinner { width:24px; height:24px; border:3px solid var(--border); border-top-color:var(--accent); border-radius:50%; animation:spin 0.8s linear infinite; margin-right:12px; }
  @keyframes spin { to { transform:rotate(360deg); } }

  /* Empty state */
  .empty { text-align:center; padding:60px; color:var(--muted); }
  .empty h2 { font-size:20px; margin-bottom:8px; color:var(--text); }

  /* Error */
  .error { background:rgba(255,71,87,0.1); border:1px solid rgba(255,71,87,0.3); border-radius:8px; padding:16px; color:var(--danger); margin-bottom:16px; }

  /* Stats bar */
  .stats-bar { display:flex; gap:24px; margin-bottom:24px; flex-wrap:wrap; }
  .stat-item { display:flex; flex-direction:column; }
  .stat-value { font-size:28px; font-weight:700; }
  .stat-label { font-size:12px; color:var(--muted); text-transform:uppercase; }

  /* Entity graph placeholder */
  .entity-graph { min-height:200px; display:flex; flex-wrap:wrap; gap:8px; padding:12px; }
  .entity-node { background:var(--card); border:1px solid var(--border); border-radius:8px; padding:8px 12px; font-size:12px; cursor:pointer; transition:all .2s; }
  .entity-node:hover { border-color:var(--accent); }
  .entity-node.center { border-color:var(--accent); background:rgba(108,92,231,0.1); }
  .entity-node .addr { font-family:monospace; color:var(--info); }
  .entity-node .method { color:var(--muted); font-size:10px; margin-top:2px; }
</style>
</head>
<body>

<nav>
  <div class="logo">WalletSafe</div>
  <div class="tab active" data-tab="search" onclick="switchTab('search')">Search</div>
  <div class="tab" data-tab="dashboard" onclick="switchTab('dashboard')">Dashboard</div>
</nav>

<!-- Search Tab -->
<div id="tab-search" class="container">
  <div class="search-bar">
    <input id="search-input" type="text" placeholder="Enter wallet address (0x..., Solana...)" onkeydown="if(event.key==='Enter')searchWallet()">
    <select id="chain-select">
      <option value="solana">Solana</option>
      <option value="ethereum">Ethereum</option>
      <option value="bsc">BSC</option>
      <option value="polygon">Polygon</option>
      <option value="arbitrum">Arbitrum</option>
      <option value="base">Base</option>
    </select>
    <button onclick="searchWallet()">Analyze</button>
  </div>

  <div id="search-results"></div>
  <div id="empty-state" class="empty">
    <h2>Wallet Intelligence Explorer</h2>
    <p>Enter a wallet address to see risk scores, entity clusters, labels, and deployer history</p>
  </div>
</div>

<!-- Dashboard Tab -->
<div id="tab-dashboard" class="container" style="display:none">
  <div class="stats-bar" id="dashboard-stats"></div>
  <div class="profile-grid" id="dashboard-content"></div>
</div>

<script>
const API = '/api/v1/wallet';
let currentTab = 'search';

function switchTab(tab) {
  currentTab = tab;
  document.querySelectorAll('.tab').forEach(t => t.classList.toggle('active', t.dataset.tab === tab));
  document.getElementById('tab-search').style.display = tab === 'search' ? 'block' : 'none';
  document.getElementById('tab-dashboard').style.display = tab === 'dashboard' ? 'block' : 'none';
  if (tab === 'dashboard') loadDashboard();
}

async function api(endpoint, opts = {}) {
  try {
    const r = await fetch(API + endpoint, opts);
    return await r.json();
  } catch(e) {
    console.error('API error:', e);
    return null;
  }
}

async function searchWallet() {
  const addr = document.getElementById('search-input').value.trim();
  const chain = document.getElementById('chain-select').value;
  if (!addr) return;

  const results = document.getElementById('search-results');
  const empty = document.getElementById('empty-state');
  empty.style.display = 'none';
  results.innerHTML = '<div class="loading"><div class="spinner"></div>Analyzing wallet...</div>';

  const profile = await api(`/${addr}/profile?chain=${chain}`);
  if (!profile) {
    results.innerHTML = '<div class="error">Failed to fetch wallet profile. Check the address and try again.</div>';
    return;
  }

  results.innerHTML = renderProfile(profile, chain);
}

function renderProfile(p, chain) {
  const score = p.risk_score || 0;
  const level = p.risk_level || 'unknown';
  const scoreColor = riskColor(score);
  const barColor = riskBarColor(level);

  let html = '';

  // Risk Card
  html += `<div class="card">
    <h3>Risk Assessment</h3>
    <div class="risk-gauge">
      <div class="risk-score" style="color:${scoreColor}">${Math.round(score)}</div>
      <div>
        <span class="risk-label risk-${level}">${level.toUpperCase()}</span>
        <div class="risk-bar" style="width:200px;margin-top:8px">
          <div class="risk-bar-fill" style="width:${score}%;background:${barColor}"></div>
        </div>
      </div>
    </div>
    ${p.scam_associations?.length ? `<div style="margin-top:12px"><strong>Scam Associations:</strong> ${p.scam_associations.map(s => `<span class="tag tag-scam">${s.type} (${s.source})</span>`).join(' ')}</div>` : ''}
  </div>`;

  // Profile Info
  html += `<div class="profile-grid">
    <div class="card">
      <h3>Wallet Identity</h3>
      <div class="profile-field"><span class="label">Address</span><span class="value" style="font-family:monospace;font-size:12px">${p.address}</span></div>
      <div class="profile-field"><span class="label">Chain</span><span class="value">${p.chain}</span></div>
      <div class="profile-field"><span class="label">Entity</span><span class="value">${p.entity_label || p.entity_id?.slice(0,16) + '...' || 'Unknown'}</span></div>
      <div class="profile-field"><span class="label">Category</span><span class="value"><span class="tag tag-${p.entity_category || 'unknown'}">${p.entity_category || 'unknown'}</span></span></div>
      <div class="profile-field"><span class="label">Confidence</span><span class="value">${(p.confidence * 100).toFixed(0)}%</span></div>
      ${p.total_transactions ? `<div class="profile-field"><span class="label">Transactions</span><span class="value">${p.total_transactions.toLocaleString()}</span></div>` : ''}
      ${p.total_volume ? `<div class="profile-field"><span class="label">Volume</span><span class="value">$${p.total_volume.toLocaleString()}</span></div>` : ''}
    </div>

    <div class="card">
      <h3>Labels (${p.labels?.length || 0})</h3>
      ${p.labels?.length ? p.labels.map(l => `<div class="profile-field"><span class="label">${l.source}</span><span class="value"><span class="tag tag-${l.category || 'unknown'}">${l.label || l.category}</span></span></div>`).join('') : '<div style="color:var(--muted);padding:20px;text-align:center">No labels found</div>'}
    </div>
  </div>`;

  // Linked Wallets / Entity
  if (p.linked_wallets?.length) {
    html += `<div class="card">
      <h3>Linked Wallets (${p.linked_wallets.length})</h3>
      <div class="entity-graph">
        <div class="entity-node center">
          <div class="addr">${p.address.slice(0,10)}...${p.address.slice(-6)}</div>
          <div class="method">primary</div>
        </div>
        ${p.linked_wallets.map(w => `<div class="entity-node" onclick="drillDown('${w.address}','${w.chain}')">
          <div class="addr">${w.address.slice(0,10)}...${w.address.slice(-6)}</div>
          <div class="method">${w.heuristic || w.method || 'linked'} · ${w.chain} · ${(w.confidence * 100).toFixed(0)}%</div>
        </div>`).join('')}
      </div>
    </div>`;
  }

  // Cross-chain
  if (p.cross_chain_presence?.length) {
    html += `<div class="card"><h3>Cross-Chain Presence</h3>
      ${p.cross_chain_presence.map(b => `<div class="wallet-item">
        <span class="wallet-addr" onclick="drillDown('${b.dest_address}','${b.dest_chain}')">${b.dest_address.slice(0,12)}...${b.dest_address.slice(-6)}</span>
        <span class="wallet-chain">${b.dest_chain}</span>
        <span style="color:var(--muted);font-size:12px">via ${b.bridge_name}</span>
      </div>`).join('')}
    </div>`;
  }

  // Deployer History
  if (p.deployer_history?.length) {
    html += `<div class="card"><h3>Deployer History (${p.deployer_history.length})</h3>
      ${p.deployer_history.map(d => `<div class="deploy-item">
        <span class="deploy-token">${d.token_symbol || d.token_address?.slice(0,12)}</span>
        <span style="margin-left:8px">${d.token_name || ''}</span>
        ${d.is_scam_related ? '<span class="tag tag-scam" style="margin-left:8px">SCAM</span>' : ''}
        <span style="float:right;color:var(--muted)">${d.deployed_at ? new Date(d.deployed_at).toLocaleDateString() : ''} · ${d.outcome || 'unknown'}</span>
      </div>`).join('')}
    </div>`;
  }

  return html;
}

function drillDown(addr, chain) {
  document.getElementById('search-input').value = addr;
  document.getElementById('chain-select').value = chain;
  searchWallet();
}

function riskColor(score) {
  if (score >= 80) return 'var(--danger)';
  if (score >= 60) return '#ff6348';
  if (score >= 40) return 'var(--warning)';
  if (score >= 20) return '#7bed9f';
  return 'var(--safe)';
}

function riskBarColor(level) {
  const m = {critical:'var(--danger)',high:'#ff6348',medium:'var(--warning)',low:'#7bed9f',minimal:'var(--safe)',unknown:'var(--muted)'};
  return m[level] || 'var(--muted)';
}

async function loadDashboard() {
  const stats = document.getElementById('dashboard-stats');
  const content = document.getElementById('dashboard-content');
  stats.innerHTML = '<div class="loading"><div class="spinner"></div>Loading...</div>';

  const [health, labelStats] = await Promise.all([
    api('/health'),
    api('/labels/stats'),
  ]);

  let statsHtml = '';
  if (health) {
    statsHtml += `
      <div class="stat-item"><span class="stat-value" style="color:${health.storage?.redis ? 'var(--safe)' : 'var(--danger)'}">${health.storage?.redis ? 'Online' : 'Offline'}</span><span class="stat-label">Redis</span></div>
      <div class="stat-item"><span class="stat-value" style="color:${health.storage?.clickhouse ? 'var(--safe)' : 'var(--warning)'}">${health.storage?.clickhouse ? 'Online' : 'Offline'}</span><span class="stat-label">ClickHouse</span></div>
      <div class="stat-item"><span class="stat-value">${health.clustering?.wallets || 0}</span><span class="stat-label">Cluster Nodes</span></div>
    `;
  }
  if (labelStats) {
    const c = labelStats.last_counts || {};
    statsHtml += `
      <div class="stat-item"><span class="stat-value">${c.total || 0}</span><span class="stat-label">Total Labels</span></div>
      <div class="stat-item"><span class="stat-value">${c.ofac || 0}</span><span class="stat-label">OFAC Sanctions</span></div>
      <div class="stat-item"><span class="stat-value">${c.etherscan_combined || 0}</span><span class="stat-label">Etherscan Labels</span></div>
      <div class="stat-item"><span class="stat-value">${c.solana_cex || 0}</span><span class="stat-label">Solana CEX</span></div>
    `;
  }
  stats.innerHTML = statsHtml;

  // Show recent high-risk wallets from Redis scan
  content.innerHTML = `
    <div class="card" style="grid-column:1/-1">
      <h3>System Health</h3>
      <div class="profile-field"><span class="label">Status</span><span class="value">${health?.status === 'ok' ? '<span style="color:var(--safe)">Operational</span>' : '<span style="color:var(--warning)">Degraded</span>'}</span></div>
      <div class="profile-field"><span class="label">Redis</span><span class="value">${health?.storage?.redis ? '<span style="color:var(--safe)">Connected</span>' : '<span style="color:var(--danger)">Disconnected</span>'}</span></div>
      <div class="profile-field"><span class="label">ClickHouse</span><span class="value">${health?.storage?.clickhouse ? '<span style="color:var(--safe)">Connected</span>' : '<span style="color:var(--warning)">Unavailable (Redis-only)</span>'}</span></div>
      <div class="profile-field"><span class="label">Clustering Heuristics</span><span class="value">${health?.clustering?.heuristics || 6}</span></div>
      <div class="profile-field"><span class="label">Label Sources</span><span class="value">9 (6 static + 3 live)</span></div>
      <div class="profile-field"><span class="label">Label Import</span><span class="value">${labelStats?.loading ? '<span style="color:var(--warning)">Loading...</span>' : '<span style="color:var(--safe)">Complete</span>'}</span></div>
    </div>
  `;
}
</script>
</body>
</html>"""


@router.get("/walletsafe/")
async def walletsafe_root():
    """Serve the WalletSafe frontend."""
    return HTMLResponse(content=WALLETSAFE_HTML)


@router.get("/walletsafe")
async def walletsafe_no_slash():
    """Redirect to /walletsafe/."""
    return HTMLResponse(content=WALLETSAFE_HTML)
