"""
Local analytics dashboard.
Opens in browser — data never leaves customer's machine.
"""
from __future__ import annotations
import threading, webbrowser, json
from http.server import HTTPServer, BaseHTTPRequestHandler
from typing import Optional


def launch_dashboard(storage, analytics, port: int = 7860, open_browser: bool = True):
    """Launch local dashboard server."""

    class Handler(BaseHTTPRequestHandler):
        def log_message(self, *args): pass  # suppress logs

        def do_GET(self):
            if self.path == "/":
                self._serve_html()
            elif self.path.startswith("/api/"):
                self._serve_api()
            else:
                self.send_error(404)

        def _serve_html(self):
            html = _build_dashboard_html()
            self.send_response(200)
            self.send_header("Content-Type", "text/html; charset=utf-8")
            self.end_headers()
            self.wfile.write(html.encode())

        def _serve_api(self):
            try:
                if self.path == "/api/metrics":
                    m = analytics.compute_metrics(days=30)
                    data = m.__dict__
                elif self.path == "/api/trends":
                    data = analytics.trends(days=30, interval="day")
                elif self.path == "/api/languages":
                    data = {k: v.__dict__ for k, v in
                            analytics.metrics_by_language(days=30).items()}
                elif self.path == "/api/domains":
                    data = {k: v.__dict__ for k, v in
                            analytics.metrics_by_domain(days=30).items()}
                else:
                    data = {"error": "not found"}

                body = json.dumps(data, default=str).encode()
                self.send_response(200)
                self.send_header("Content-Type", "application/json")
                self.send_header("Access-Control-Allow-Origin", "*")
                self.end_headers()
                self.wfile.write(body)
            except Exception as e:
                self.send_error(500, str(e))

    server = HTTPServer(("localhost", port), Handler)
    url = f"http://localhost:{port}"
    print(f"\n  A2RAG Dashboard running at {url}")
    print(f"  Press Ctrl+C to stop\n")
    if open_browser:
        threading.Timer(0.5, lambda: webbrowser.open(url)).start()
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        print("\n  Dashboard stopped.")


def _build_dashboard_html() -> str:
    return """<!DOCTYPE html>
<html><head>
<title>A2RAG Analytics Dashboard</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
  * { box-sizing: border-box; margin: 0; padding: 0; }
  body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
         background: #f0f4ff; color: #1a1a2e; min-height: 100vh; }
  .header { background: linear-gradient(135deg, #1B3A6B, #2E5EA8);
            color: white; padding: 24px 32px;
            display: flex; align-items: center; justify-content: space-between; }
  .header h1 { font-size: 1.5em; font-weight: 700; }
  .header .sub { font-size: 0.85em; opacity: 0.75; margin-top: 2px; }
  .privacy { background: #D3F9D8; border-left: 4px solid #2B8A3E;
             padding: 10px 20px; font-size: 0.85em; color: #2B8A3E; }
  .container { max-width: 1200px; margin: 0 auto; padding: 24px 20px; }
  .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
          gap: 16px; margin-bottom: 28px; }
  .card { background: white; border-radius: 12px; padding: 20px;
          box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
  .card h3 { font-size: 0.8em; color: #888; text-transform: uppercase;
             letter-spacing: 0.5px; margin-bottom: 8px; }
  .card .value { font-size: 2.2em; font-weight: 700; color: #1B3A6B; }
  .card .value.good { color: #2B8A3E; }
  .card .value.warn { color: #E67700; }
  .card .value.danger { color: #C92A2A; }
  .card .sub { font-size: 0.8em; color: #aaa; margin-top: 4px; }
  .section { background: white; border-radius: 12px; padding: 24px;
             box-shadow: 0 2px 8px rgba(0,0,0,0.08); margin-bottom: 20px; }
  .section h2 { font-size: 1em; font-weight: 600; color: #1B3A6B;
                margin-bottom: 16px; padding-bottom: 8px;
                border-bottom: 2px solid #E8EDFF; }
  .bar-row { display: flex; align-items: center; margin-bottom: 10px; }
  .bar-label { width: 100px; font-size: 0.85em; }
  .bar-track { flex: 1; height: 20px; background: #f0f0f0;
               border-radius: 10px; overflow: hidden; margin: 0 12px; }
  .bar-fill { height: 100%; border-radius: 10px; transition: width 0.8s; }
  .bar-val { width: 50px; font-size: 0.85em; text-align: right; font-weight: 600; }
  .trend { display: flex; gap: 4px; align-items: flex-end; height: 80px; margin-top: 12px; }
  .trend-bar { flex: 1; background: #1B3A6B; border-radius: 3px 3px 0 0;
               min-width: 4px; transition: height 0.5s; }
  table { width: 100%; border-collapse: collapse; font-size: 0.9em; }
  th { background: #F0F4FF; padding: 10px 12px; text-align: left; font-size: 0.8em;
       color: #555; text-transform: uppercase; }
  td { padding: 10px 12px; border-bottom: 1px solid #f0f0f0; }
  .badge { display: inline-block; padding: 2px 10px; border-radius: 20px;
           font-size: 0.8em; font-weight: 600; }
  .badge-answer { background: #D3F9D8; color: #2B8A3E; }
  .badge-clarify { background: #FFF3BF; color: #E67700; }
  .badge-abstain { background: #FFE3E3; color: #C92A2A; }
</style>
</head><body>

<div class="header">
  <div>
    <h1>A2RAG Analytics</h1>
    <div class="sub">Local dashboard — data never leaves your machine</div>
  </div>
  <div style="font-size:0.85em;opacity:0.8" id="lastUpdate"></div>
</div>
<div class="privacy">
  🔒 All data shown here is stored locally on your machine. Nothing is sent to A2RAG servers.
</div>

<div class="container">
  <div class="grid" id="kpiGrid">Loading...</div>

  <div class="grid" style="grid-template-columns: 1fr 1fr;">
    <div class="section">
      <h2>Decision Distribution</h2>
      <div id="distribution"></div>
    </div>
    <div class="section">
      <h2>Quality Metrics</h2>
      <div id="quality"></div>
    </div>
  </div>

  <div class="section">
    <h2>Activity Trend (last 30 days)</h2>
    <div class="trend" id="trend"></div>
  </div>

  <div class="grid" style="grid-template-columns: 1fr 1fr;">
    <div class="section">
      <h2>By Language</h2>
      <table id="langTable"><tr><th>Language</th><th>Total</th><th>Answer Rate</th><th>UAR</th></tr></table>
    </div>
    <div class="section">
      <h2>By Domain</h2>
      <table id="domainTable"><tr><th>Domain</th><th>Total</th><th>Answer Rate</th><th>UAR</th></tr></table>
    </div>
  </div>
</div>

<script>
async function load() {
  const [metrics, trends, langs, domains] = await Promise.all([
    fetch('/api/metrics').then(r=>r.json()),
    fetch('/api/trends').then(r=>r.json()),
    fetch('/api/languages').then(r=>r.json()),
    fetch('/api/domains').then(r=>r.json()),
  ]);

  document.getElementById('lastUpdate').textContent =
    'Updated: ' + new Date().toLocaleTimeString();

  // KPIs
  const ors = (metrics.coverage||0) * (1-(metrics.uar||0)) * (metrics.abstain_precision||1);
  document.getElementById('kpiGrid').innerHTML = `
    <div class="card"><h3>Total Decisions</h3>
      <div class="value">${metrics.total||0}</div>
      <div class="sub">last 30 days</div></div>
    <div class="card"><h3>Answer Rate</h3>
      <div class="value good">${((metrics.answer_rate||0)*100).toFixed(1)}%</div>
      <div class="sub">coverage</div></div>
    <div class="card"><h3>UAR</h3>
      <div class="value ${(metrics.uar||0) > 0.05 ? 'danger' : 'good'}">${((metrics.uar||0)*100).toFixed(1)}%</div>
      <div class="sub">unsafe answer rate</div></div>
    <div class="card"><h3>ORS</h3>
      <div class="value ${ors > 0.7 ? 'good' : ors > 0.4 ? 'warn' : 'danger'}">${(ors*100).toFixed(1)}%</div>
      <div class="sub">overall reliability</div></div>
    <div class="card"><h3>Avg Latency</h3>
      <div class="value">${(metrics.avg_latency_ms||0).toFixed(0)}ms</div>
      <div class="sub">p95: ${(metrics.p95_latency_ms||0).toFixed(0)}ms</div></div>
    <div class="card"><h3>Avg Confidence</h3>
      <div class="value">${((metrics.avg_confidence||0)*100).toFixed(0)}%</div>
      <div class="sub">high: ${((metrics.high_confidence_rate||0)*100).toFixed(0)}%</div></div>
  `;

  // Distribution
  const bars = [
    {label:'Answer',  val:metrics.answer_rate||0,  color:'#2B8A3E'},
    {label:'Clarify', val:metrics.clarify_rate||0, color:'#E67700'},
    {label:'Abstain', val:metrics.abstain_rate||0, color:'#C92A2A'},
  ];
  document.getElementById('distribution').innerHTML = bars.map(b => `
    <div class="bar-row">
      <div class="bar-label">${b.label}</div>
      <div class="bar-track"><div class="bar-fill" style="width:${b.val*100}%;background:${b.color}"></div></div>
      <div class="bar-val">${(b.val*100).toFixed(1)}%</div>
    </div>`).join('');

  // Quality
  const qbars = [
    {label:'AbstainP', val:metrics.abstain_precision||1, color:'#1B3A6B'},
    {label:'Low UAR',  val:1-(metrics.uar||0),           color:'#2B8A3E'},
    {label:'Hi Conf',  val:metrics.high_confidence_rate||0, color:'#2E5EA8'},
    {label:'Feedback', val:metrics.positive_feedback||0, color:'#E67700'},
  ];
  document.getElementById('quality').innerHTML = qbars.map(b => `
    <div class="bar-row">
      <div class="bar-label">${b.label}</div>
      <div class="bar-track"><div class="bar-fill" style="width:${b.val*100}%;background:${b.color}"></div></div>
      <div class="bar-val">${(b.val*100).toFixed(0)}%</div>
    </div>`).join('');

  // Trend
  if (trends.length > 0) {
    const maxTotal = Math.max(...trends.map(t=>t.total));
    document.getElementById('trend').innerHTML = trends.map(t => `
      <div class="trend-bar" title="${new Date(t.timestamp*1000).toLocaleDateString()}: ${t.total}"
           style="height:${Math.max(4, (t.total/maxTotal)*80)}px"></div>`).join('');
  }

  // Languages table
  const langRows = Object.entries(langs).map(([lang, m]) =>
    `<tr><td>${lang}</td><td>${m.total}</td>
     <td>${((m.answer_rate||0)*100).toFixed(0)}%</td>
     <td class="${(m.uar||0)>0.05?'badge badge-abstain':''}">${((m.uar||0)*100).toFixed(0)}%</td></tr>`
  ).join('');
  document.getElementById('langTable').innerHTML +=  langRows;

  // Domains table
  const domainRows = Object.entries(domains).map(([d, m]) =>
    `<tr><td>${d}</td><td>${m.total}</td>
     <td>${((m.answer_rate||0)*100).toFixed(0)}%</td>
     <td>${((m.uar||0)*100).toFixed(0)}%</td></tr>`
  ).join('');
  document.getElementById('domainTable').innerHTML += domainRows;
}

load();
setInterval(load, 30000);
</script>
</body></html>"""
