"""
dashboard.py — MoneyMaker live monitoring dashboard.

Usage:
    python dashboard.py              # starts on http://localhost:5001
    python dashboard.py --port 5002

Auto-refreshes every 60 seconds. Shows:
  • Portfolio P&L + C25 benchmark
  • Open positions with live prices
  • Closed trades (win/loss)
  • Signal accuracy
  • Recent runner log tail
"""
import argparse
import json
import os
import time
from datetime import datetime, timezone
from pathlib import Path

import yfinance as yf
from flask import Flask, render_template_string

from db import get_conn, DB_TYPE
from report import _c25_day_return, _unrealised_pnl, _realised_pnl, _total_fees, _signal_accuracy

CAPITAL  = 10_000
LOG_DIR  = Path(os.getenv("LOG_DIR", str(Path(__file__).parent / "logs")))
REFRESH  = 60   # seconds

app = Flask(__name__)

# ── HTML template ────────────────────────────────────────────────────────────

TEMPLATE = """
<!DOCTYPE html>
<html lang="da">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta http-equiv="refresh" content="{{ refresh }}">
  <title>MoneyMaker Dashboard</title>
  <style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body { font-family: 'Segoe UI', system-ui, sans-serif; background: #0f1117; color: #e2e8f0; padding: 24px; }
    h1 { font-size: 1.4rem; font-weight: 700; color: #7dd3fc; margin-bottom: 4px; }
    .subtitle { font-size: 0.8rem; color: #64748b; margin-bottom: 24px; }
    .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px; }
    .card { background: #1e2535; border-radius: 10px; padding: 18px 20px; border: 1px solid #2d3748; }
    .card .label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: .06em; color: #64748b; margin-bottom: 6px; }
    .card .value { font-size: 1.6rem; font-weight: 700; }
    .card .sub   { font-size: 0.78rem; color: #94a3b8; margin-top: 4px; }
    .pos  { color: #4ade80; }
    .neg  { color: #f87171; }
    .neu  { color: #94a3b8; }
    .warn { color: #fbbf24; }
    table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
    th { text-align: left; padding: 8px 12px; background: #1e2535; color: #64748b; font-size: 0.72rem; text-transform: uppercase; letter-spacing: .06em; border-bottom: 1px solid #2d3748; }
    td { padding: 9px 12px; border-bottom: 1px solid #1a2030; }
    tr:hover td { background: #1e2535; }
    .section { background: #161c2d; border-radius: 10px; border: 1px solid #2d3748; margin-bottom: 20px; overflow: hidden; }
    .section-title { padding: 14px 18px; font-size: 0.8rem; font-weight: 600; color: #7dd3fc; text-transform: uppercase; letter-spacing: .08em; border-bottom: 1px solid #2d3748; background: #1a2236; }
    .badge { display: inline-block; padding: 2px 8px; border-radius: 99px; font-size: 0.72rem; font-weight: 600; }
    .badge-green { background: #14532d; color: #4ade80; }
    .badge-red   { background: #450a0a; color: #f87171; }
    .badge-gray  { background: #1e2535; color: #94a3b8; }
    pre { font-family: 'Cascadia Code', 'Fira Mono', monospace; font-size: 0.75rem; color: #94a3b8; padding: 16px 18px; overflow-x: auto; white-space: pre-wrap; line-height: 1.6; }
    .footer { font-size: 0.72rem; color: #334155; text-align: center; margin-top: 32px; }
  </style>
</head>
<body>
  <h1>📈 MoneyMaker</h1>
  <div class="subtitle">DB: {{ db_type }} &nbsp;·&nbsp; Opdateret: {{ now }} &nbsp;·&nbsp; Refresh om {{ refresh }}s</div>

  <!-- KPI cards -->
  <div class="grid">
    <div class="card">
      <div class="label">Net P&amp;L</div>
      <div class="value {{ 'pos' if net_pnl >= 0 else 'neg' }}">{{ "{:+,.0f}".format(net_pnl) }} kr</div>
      <div class="sub">{{ "{:+.2f}%".format(net_pct) }}</div>
    </div>
    <div class="card">
      <div class="label">Urealiseret</div>
      <div class="value {{ 'pos' if unreal >= 0 else 'neg' }}">{{ "{:+,.0f}".format(unreal) }} kr</div>
      <div class="sub">{{ open_count }} åben{{ 'e' if open_count != 1 else '' }} position{{ 'er' if open_count != 1 else '' }}</div>
    </div>
    <div class="card">
      <div class="label">Realiseret</div>
      <div class="value {{ 'pos' if realised >= 0 else 'neg' }}">{{ "{:+,.0f}".format(realised) }} kr</div>
      <div class="sub">Gebyrer: {{ "{:,.0f}".format(fees) }} kr</div>
    </div>
    <div class="card">
      <div class="label">C25 i dag</div>
      {% if c25_ret is not none %}
        <div class="value {{ 'pos' if c25_ret >= 0 else 'neg' }}">{{ "{:+.2f}%".format(c25_ret) }}</div>
        <div class="sub {{ 'pos' if vs_bench and vs_bench >= 0 else 'neg' }}">
          vs benchmark: {{ "{:+.2f}%".format(vs_bench) if vs_bench is not none else "—" }}
        </div>
      {% else %}
        <div class="value neu">—</div>
        <div class="sub">Marked lukket?</div>
      {% endif %}
    </div>
    <div class="card">
      <div class="label">Signal accuracy</div>
      {% if sig.total_trades > 0 %}
        <div class="value {{ 'pos' if sig.accuracy_pct >= 50 else 'neg' }}">{{ "{:.0f}%".format(sig.accuracy_pct) }}</div>
        <div class="sub">{{ sig.correct }} / {{ sig.total_trades }} handler korrekte</div>
      {% else %}
        <div class="value neu">—</div>
        <div class="sub">Ingen lukkede handler</div>
      {% endif %}
    </div>
    <div class="card">
      <div class="label">Kapital</div>
      <div class="value neu">{{ "{:,.0f}".format(capital) }} kr</div>
      <div class="sub">Kontant: {{ "{:,.0f}".format(cash) }} kr</div>
    </div>
  </div>

  <!-- Open positions -->
  <div class="section">
    <div class="section-title">📊 Åbne positioner</div>
    {% if positions %}
    <table>
      <tr><th>Ticker</th><th>Antal</th><th>Købt</th><th>Nu</th><th>P&amp;L</th><th>Ændring</th><th>Stop</th><th>Take</th><th>Status</th></tr>
      {% for p in positions %}
      <tr>
        <td><strong>{{ p.ticker }}</strong></td>
        <td>{{ "{:.0f}".format(p.shares) }}</td>
        <td>{{ "{:,.0f}".format(p.entry) }}</td>
        <td>{{ "{:,.0f}".format(p.last) }}</td>
        <td class="{{ 'pos' if p.unreal >= 0 else 'neg' }}">{{ "{:+,.0f}".format(p.unreal) }}</td>
        <td class="{{ 'pos' if p.pct >= 0 else 'neg' }}">{{ "{:+.1f}%".format(p.pct) }}</td>
        <td class="neg">{{ "{:,.0f}".format(p.stop) }}</td>
        <td class="pos">{{ "{:,.0f}".format(p.take) }}</td>
        <td>
          {% if p.stop_hit %}<span class="badge badge-red">🔴 STOP</span>
          {% elif p.take_hit %}<span class="badge badge-green">🟡 TAKE</span>
          {% else %}<span class="badge badge-gray">⏳ HOLD</span>{% endif %}
        </td>
      </tr>
      {% endfor %}
    </table>
    {% else %}
    <p style="padding:16px 18px; color:#64748b; font-size:0.85rem;">Ingen åbne positioner.</p>
    {% endif %}
  </div>

  <!-- Closed trades -->
  <div class="section">
    <div class="section-title">🏁 Lukkede handler</div>
    {% if trades %}
    <table>
      <tr><th>Ticker</th><th>Handling</th><th>Antal</th><th>Kurs</th><th>Total</th><th>P&amp;L</th><th>Signal</th><th>Dato</th></tr>
      {% for t in trades %}
      <tr>
        <td><strong>{{ t.ticker }}</strong></td>
        <td>{{ t.action.upper() }}</td>
        <td>{{ "{:.0f}".format(t.shares) }}</td>
        <td>{{ "{:,.0f}".format(t.price) }}</td>
        <td>{{ "{:,.0f}".format(t.total_dkk) }}</td>
        <td class="{{ 'pos' if t.pnl_dkk and t.pnl_dkk >= 0 else ('neg' if t.pnl_dkk else 'neu') }}">
          {{ "{:+,.0f}".format(t.pnl_dkk) if t.pnl_dkk is not none else "—" }}
        </td>
        <td>
          {% if t.signal_correct == 1 %}<span class="badge badge-green">✅ korrekt</span>
          {% elif t.signal_correct == 0 %}<span class="badge badge-red">❌ forkert</span>
          {% else %}<span class="badge badge-gray">—</span>{% endif %}
        </td>
        <td>{{ t.event_date }}</td>
      </tr>
      {% endfor %}
    </table>
    {% else %}
    <p style="padding:16px 18px; color:#64748b; font-size:0.85rem;">Ingen handler endnu.</p>
    {% endif %}
  </div>

  <!-- Signal pipeline stats -->
  <div class="section">
    <div class="section-title">🔬 NLP signal pipeline</div>
    <table>
      <tr><th>Analyserede signaler</th><th>Alert-triggers (≥threshold)</th><th>Gns. score</th></tr>
      <tr>
        <td>{{ sig.total }}</td>
        <td>{{ sig.alerts }}</td>
        <td>{{ "{:.3f}".format(sig.avg_score) }}</td>
      </tr>
    </table>
  </div>

  <!-- Log tail -->
  {% if log_tail %}
  <div class="section">
    <div class="section-title">📋 Seneste log ({{ log_file }})</div>
    <pre>{{ log_tail }}</pre>
  </div>
  {% endif %}

  <div class="footer">MoneyMaker · {{ db_type }} · hjess-desktop · auto-refresh {{ refresh }}s</div>
</body>
</html>
"""


# ── Data helpers ─────────────────────────────────────────────────────────────

def _latest_log_tail(lines: int = 40) -> tuple[str, str]:
    """Return (filename, last N lines) from most recent runner log."""
    if not LOG_DIR.exists():
        return "", ""
    logs = sorted(LOG_DIR.glob("runner_*.log"), reverse=True)
    if not logs:
        return "", ""
    path = logs[0]
    try:
        content = path.read_text(errors="replace")
        tail = "\n".join(content.splitlines()[-lines:])
        return path.name, tail
    except Exception:
        return path.name, ""


def _open_positions_live(db) -> list[dict]:
    """Fetch open positions with live yfinance prices."""
    rows = db.execute("SELECT * FROM positions").fetchall()
    result = []
    for p in rows:
        ticker = p["ticker"]
        from report import C25
        yf_ticker = C25.get(ticker, {}).get("ticker_yahoo", ticker + ".CO")
        try:
            last = yf.Ticker(yf_ticker).fast_info.get("lastPrice") or p["entry_price"]
        except Exception:
            last = p["entry_price"]
        entry = float(p["entry_price"])
        shares = float(p["shares"])
        pct = (last - entry) / entry * 100
        result.append({
            "ticker":   ticker,
            "shares":   shares,
            "entry":    entry,
            "last":     last,
            "unreal":   shares * (last - entry),
            "pct":      pct,
            "stop":     float(p["stop_loss"]),
            "take":     float(p["take_profit"]),
            "stop_hit": last <= p["stop_loss"],
            "take_hit": last >= p["take_profit"],
        })
    return result


def _closed_trades(db, limit: int = 20) -> list[dict]:
    rows = db.execute("""
        SELECT ticker, action, shares, price, total_dkk, pnl_dkk, signal_correct, event_date
        FROM position_events
        ORDER BY id DESC LIMIT ?
    """, (limit,)).fetchall()
    return [dict(r) for r in rows]


# ── Routes ────────────────────────────────────────────────────────────────────

@app.route("/")
def index():
    db = get_conn()
    try:
        positions  = _open_positions_live(db)
        trades     = _closed_trades(db)
        unreal     = sum(p["unreal"] for p in positions)
        invested   = sum(p["shares"] * p["entry"] for p in positions)
        realised   = _realised_pnl(db)
        fees       = _total_fees(db)
        sig        = _signal_accuracy(db)
        c25_ret    = _c25_day_return()
        net_pnl    = realised + unreal - fees
        net_pct    = net_pnl / CAPITAL * 100
        vs_bench   = (net_pct - c25_ret) if c25_ret is not None else None
        cash       = CAPITAL - invested
        log_file, log_tail = _latest_log_tail()
        now = datetime.now(timezone.utc).strftime("%d %b %Y %H:%M UTC")

        return render_template_string(
            TEMPLATE,
            now=now,
            db_type=DB_TYPE,
            refresh=REFRESH,
            capital=CAPITAL,
            cash=cash,
            unreal=unreal,
            realised=realised,
            fees=fees,
            net_pnl=net_pnl,
            net_pct=net_pct,
            c25_ret=c25_ret,
            vs_bench=vs_bench,
            positions=positions,
            open_count=len(positions),
            trades=trades,
            sig=type("Sig", (), sig)(),
            log_file=log_file,
            log_tail=log_tail,
        )
    finally:
        db.close()


@app.route("/health")
def health():
    return {"status": "ok", "db": DB_TYPE, "ts": time.time()}


# ── Main ──────────────────────────────────────────────────────────────────────

def main():
    parser = argparse.ArgumentParser(description="MoneyMaker Dashboard")
    parser.add_argument("--port", type=int, default=int(os.getenv("PORT", 5001)))
    parser.add_argument("--host", default=os.getenv("HOST", "0.0.0.0"))
    args = parser.parse_args()
    print(f"\n  MoneyMaker Dashboard -> http://localhost:{args.port}\n")
    app.run(host=args.host, port=args.port, debug=False)


if __name__ == "__main__":
    main()
