"""Dashboard stats API endpoints."""

from fastapi import APIRouter, Query, Request
from fastapi.responses import HTMLResponse, JSONResponse

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


def _get_message_count() -> int:
    """Get total message count from parquet."""
    try:
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        return con.execute("SELECT COUNT(*) FROM conversations").fetchone()[0]
    except Exception:
        return 0


def _get_embedded_count() -> int:
    """Get embedding count from LanceDB."""
    try:
        from brain_mcp.server.db import lance_count
        return lance_count("message")
    except Exception:
        return 0


def _get_summary_count() -> int:
    """Get summary count."""
    try:
        from brain_mcp.server.db import get_summaries_db
        db = get_summaries_db()
        if db:
            return db.execute("SELECT COUNT(*) FROM summaries").fetchone()[0]
        return 0
    except Exception:
        return 0


def _get_conversation_count() -> int:
    """Get count of unique conversations."""
    try:
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        return con.execute(
            "SELECT COUNT(DISTINCT conversation_id) FROM conversations"
        ).fetchone()[0]
    except Exception:
        return 0


def _get_tools_status() -> tuple[int, int]:
    """Get (tools_ok, tools_total) count."""
    # All 25 tools register; we check if data exists for them to work
    total = 25
    ok = total  # All tools register, they gracefully degrade
    return ok, total


def _get_topic_count() -> int:
    """Get count of unique topics/domains from summaries, or unique titles."""
    try:
        from brain_mcp.server.db import get_summaries_db
        db = get_summaries_db()
        if db:
            count = db.execute(
                "SELECT COUNT(DISTINCT domain_primary) FROM summaries "
                "WHERE domain_primary != '' AND domain_primary IS NOT NULL"
            ).fetchone()[0]
            if count > 0:
                return count
    except Exception:
        pass
    # Fallback: unique conversation titles
    try:
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        return con.execute(
            "SELECT COUNT(DISTINCT conversation_title) FROM conversations "
            "WHERE conversation_title IS NOT NULL AND conversation_title != ''"
        ).fetchone()[0]
    except Exception:
        return 0


def _get_search_speed() -> str:
    """Get a representative search speed string."""
    try:
        import time as _time
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        t0 = _time.perf_counter()
        con.execute("SELECT COUNT(*) FROM conversations").fetchone()
        elapsed_ms = (_time.perf_counter() - t0) * 1000
        if elapsed_ms < 1:
            return "< 1ms"
        elif elapsed_ms < 15:
            return f"< 15ms"
        else:
            return f"~{int(elapsed_ms)}ms"
    except Exception:
        return "< 15ms"


@router.get("/health-summary.html", response_class=HTMLResponse)
async def health_summary_html(request: Request):
    """Inline health summary — loaded via htmx when health card is clicked."""
    from brain_mcp.dashboard.routes.tools import (
        TOOLS, _check_data_available, _tool_status, _status_icon,
    )

    available = _check_data_available()

    # Group tools by category and compute per-category health
    categories: dict[str, dict] = {}
    for tool in TOOLS:
        cat = tool["category"]
        status = _tool_status(tool, available)
        if cat not in categories:
            categories[cat] = {"total": 0, "ok": 0, "tools_needing_attention": []}
        categories[cat]["total"] += 1
        if status == "ok":
            categories[cat]["ok"] += 1
        else:
            categories[cat]["tools_needing_attention"].append(
                (tool["name"], status, _status_icon(status))
            )

    # Build HTML
    parts = [
        '<article style="margin-top:1rem;padding:1rem;">',
        '<h4 style="margin-bottom:0.5rem;">Tool Health by Category</h4>',
        "<ul>",
    ]
    for cat, info in categories.items():
        ok, total = info["ok"], info["total"]
        icon = "✅" if ok == total else "⚠️"
        parts.append(f"<li><strong>{cat}:</strong> {ok}/{total} {icon}")
        if info["tools_needing_attention"]:
            parts.append("<ul>")
            for name, status, s_icon in info["tools_needing_attention"]:
                parts.append(
                    f'<li><small>{s_icon} <code>{name}</code> — {status}</small></li>'
                )
            parts.append("</ul>")
        parts.append("</li>")
    parts.append("</ul>")
    parts.append('<a href="/tools" role="button" class="outline">Full tool details →</a>')
    parts.append("</article>")
    return HTMLResponse("\n".join(parts))


@router.get("/overview", response_class=HTMLResponse)
async def stats_overview(request: Request):
    """Stats cards for the dashboard home page."""
    templates = request.app.state.templates
    messages = _get_message_count()
    embedded = _get_embedded_count()
    summaries = _get_summary_count()
    conversations = _get_conversation_count()
    tools_ok, tools_total = _get_tools_status()
    topics = _get_topic_count()
    search_speed = _get_search_speed()

    return templates.TemplateResponse("partials/stats_cards.html", {
        "request": request,
        "messages": messages,
        "embedded": embedded,
        "summaries": summaries,
        "conversations": conversations,
        "tools_ok": tools_ok,
        "tools_total": tools_total,
        "topics": topics,
        "search_speed": search_speed,
    })


@router.get("/overview.json")
async def stats_overview_json():
    """Stats as JSON (for external consumers)."""
    messages = _get_message_count()
    embedded = _get_embedded_count()
    summaries = _get_summary_count()
    conversations = _get_conversation_count()
    tools_ok, tools_total = _get_tools_status()
    topics = _get_topic_count()
    search_speed = _get_search_speed()

    return {
        "messages": messages,
        "embedded": embedded,
        "summaries": summaries,
        "conversations": conversations,
        "tools_ok": tools_ok,
        "tools_total": tools_total,
        "topics": topics,
        "search_speed": search_speed,
    }


@router.get("/activity", response_class=HTMLResponse)
async def stats_activity(days: int = 30):
    """Activity sparkline for dashboard home."""
    try:
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        rows = con.execute(f"""
            SELECT CAST(created AS DATE) as day, COUNT(*) as msgs
            FROM conversations
            WHERE created >= CURRENT_DATE - INTERVAL '{days}' DAY
            GROUP BY day ORDER BY day
        """).fetchall()

        if not rows:
            return "<p><small>No recent activity data.</small></p>"

        # Build a simple bar chart with inline CSS
        max_msgs = max(r[1] for r in rows)
        bars = []
        for day, msgs in rows:
            height = max(4, int(msgs / max_msgs * 60))
            date_str = str(day)
            bars.append(
                f'<div class="bar" style="height:{height}px" '
                f'title="{date_str}: {msgs} messages"></div>'
            )

        total = sum(r[1] for r in rows)
        avg = total // len(rows) if rows else 0
        html = f"""
        <div class="sparkline">{''.join(bars)}</div>
        <small>{total:,} messages in {days} days (avg {avg:,}/day)</small>
        """
        return html
    except Exception as e:
        return f"<p><small>Activity data unavailable: {e}</small></p>"


@router.get("/sources", response_class=HTMLResponse)
async def stats_sources():
    """Connected apps health for dashboard home."""
    DISPLAY_NAMES = {
        "claude-code": "Claude Code", "clawdbot": "Clawdbot",
        "chatgpt": "ChatGPT", "cursor": "Cursor",
        "gemini-cli": "Gemini CLI", "claude-desktop": "Claude Desktop",
    }
    try:
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        sources = con.execute("""
            SELECT source, COUNT(DISTINCT conversation_id) as convs, MAX(created) as last_msg
            FROM conversations GROUP BY source ORDER BY convs DESC
        """).fetchall()

        if not sources:
            return "<p><small>No apps connected.</small></p>"

        html_parts = ["<ul>"]
        for source, convs, last_msg in sources:
            display = DISPLAY_NAMES.get(source, source)
            date_str = str(last_msg)[:10] if last_msg else "unknown"
            html_parts.append(
                f"<li><strong>{display}</strong> — {convs:,} conversations "
                f"<small>(updated: {date_str})</small></li>"
            )
        html_parts.append("</ul>")
        return "\n".join(html_parts)
    except Exception:
        return "<p><small>No apps connected. <a href='/sources'>Connect apps →</a></small></p>"


@router.get("/domains", response_class=HTMLResponse)
async def stats_domains():
    """Open threads/domains for dashboard home."""
    try:
        from brain_mcp.server.db import get_summaries_db
        db = get_summaries_db()
        if not db:
            return "<p><small>Summaries not generated. <a href='/settings'>Configure →</a></small></p>"

        domains = db.execute("""
            SELECT domain_primary, COUNT(*) as convs
            FROM summaries
            WHERE domain_primary != '' AND domain_primary IS NOT NULL
            GROUP BY domain_primary
            ORDER BY convs DESC LIMIT 5
        """).fetchall()

        if not domains:
            return "<p><small>No domain data available.</small></p>"

        html_parts = ["<ul>"]
        for domain, count in domains:
            html_parts.append(f"<li><strong>{domain}</strong> — {count} conversations</li>")
        html_parts.append("</ul>")
        return "\n".join(html_parts)
    except Exception:
        return "<p><small>Domain data unavailable.</small></p>"


@router.get("/sync-status", response_class=HTMLResponse)
async def sync_status():
    """Sync status line for dashboard home."""
    try:
        from brain_mcp.config import get_config
        cfg = get_config()
        import os
        from datetime import datetime

        if cfg.parquet_path.exists():
            mtime = os.path.getmtime(cfg.parquet_path)
            last_sync = datetime.fromtimestamp(mtime)
            delta = datetime.now() - last_sync
            if delta.total_seconds() < 3600:
                ago = f"{int(delta.total_seconds() / 60)} minutes ago"
            elif delta.total_seconds() < 86400:
                ago = f"{int(delta.total_seconds() / 3600)} hours ago"
            else:
                ago = f"{int(delta.total_seconds() / 86400)} days ago"
            return f"⏱ Updated {ago}"
        else:
            return "⚠️ No data yet. Click Update Now to start."
    except Exception:
        return "Sync status unknown"


@router.get("/disk", response_class=HTMLResponse)
async def stats_disk():
    """Disk usage stats."""
    try:
        from brain_mcp.config import get_config
        cfg = get_config()

        total = 0
        parts = []
        for name, path in [("Parquet", cfg.parquet_path), ("Vectors", cfg.lance_path),
                           ("Summaries", cfg.summaries_parquet)]:
            if path.exists():
                if path.is_file():
                    size = path.stat().st_size
                else:
                    size = sum(f.stat().st_size for f in path.rglob("*") if f.is_file())
                total += size
                parts.append(f"{name}: {size / 1024 / 1024:.1f} MB")

        return f"💾 {total / 1024 / 1024:.1f} MB total ({', '.join(parts)})"
    except Exception:
        return "Disk usage unknown"


# ═══════════════════════════════════════════════════════════════════
# HEATMAP — daily message counts for 365-day calendar grid
# ═══════════════════════════════════════════════════════════════════

@router.get("/heatmap")
async def stats_heatmap(days: int = Query(365, ge=1, le=730)):
    """Return daily message counts for heatmap visualization.

    Returns JSON: [{"date": "2025-01-15", "count": 42}, ...]
    """
    try:
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        rows = con.execute(f"""
            SELECT CAST(created AS DATE) AS day, COUNT(*) AS cnt
            FROM conversations
            WHERE created >= CURRENT_DATE - INTERVAL '{days}' DAY
            GROUP BY day
            ORDER BY day
        """).fetchall()
        return [{"date": str(row[0]), "count": row[1]} for row in rows]
    except Exception:
        return []


@router.get("/heatmap.html", response_class=HTMLResponse)
async def stats_heatmap_html(request: Request, days: int = Query(365, ge=1, le=730)):
    """Return heatmap as an HTML partial (canvas-rendered via JS)."""
    try:
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        rows = con.execute(f"""
            SELECT CAST(created AS DATE) AS day, COUNT(*) AS cnt
            FROM conversations
            WHERE created >= CURRENT_DATE - INTERVAL '{days}' DAY
            GROUP BY day
            ORDER BY day
        """).fetchall()

        import json
        data_json = json.dumps([{"date": str(r[0]), "count": r[1]} for r in rows])
        total_days_with_data = len(rows)
        total_msgs = sum(r[1] for r in rows) if rows else 0

        return f"""
        <canvas id="heatmap-canvas" width="722" height="112"
                style="width:100%;max-width:722px;height:auto;border-radius:8px;"></canvas>
        <small class="text-muted">{total_days_with_data} active days · {total_msgs:,} messages in {days} days</small>
        <script>
        (function() {{
            var data = {data_json};
            renderHeatmap('heatmap-canvas', data, {days});
        }})();
        </script>
        """
    except Exception:
        return "<p><small>Heatmap data unavailable.</small></p>"


# ═══════════════════════════════════════════════════════════════════
# RECENT — most recent conversations
# ═══════════════════════════════════════════════════════════════════

@router.get("/recent")
async def stats_recent(limit: int = Query(5, ge=1, le=20)):
    """Return most recent conversations with title, date, message count."""
    try:
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        rows = con.execute(f"""
            SELECT conversation_id,
                   MAX(conversation_title) AS title,
                   MAX(created) AS last_date,
                   COUNT(*) AS message_count
            FROM conversations
            GROUP BY conversation_id
            ORDER BY last_date DESC
            LIMIT {limit}
        """).fetchall()
        return [
            {
                "conversation_id": row[0],
                "title": row[1] or "Untitled",
                "date": str(row[2])[:10] if row[2] else "unknown",
                "message_count": row[3],
            }
            for row in rows
        ]
    except Exception:
        return []


@router.get("/recent.html", response_class=HTMLResponse)
async def stats_recent_html(request: Request, limit: int = Query(5, ge=1, le=20)):
    """Return recent conversations as an HTML partial."""
    try:
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        rows = con.execute(f"""
            SELECT conversation_id,
                   MAX(conversation_title) AS title,
                   MAX(created) AS last_date,
                   COUNT(*) AS message_count
            FROM conversations
            GROUP BY conversation_id
            ORDER BY last_date DESC
            LIMIT {limit}
        """).fetchall()

        if not rows:
            return "<p><small>No recent conversations.</small></p>"

        parts = ['<ul class="recent-activity-list">']
        for row in rows:
            conv_id, title, last_date, msg_count = row
            title = title or "Untitled"
            date_str = str(last_date)[:10] if last_date else "unknown"
            parts.append(
                f'<li class="recent-item">'
                f'<a href="/conversation/{conv_id}">'
                f'<strong>{title}</strong></a>'
                f'<span class="recent-meta">{date_str} · {msg_count} msgs</span>'
                f'</li>'
            )
        parts.append("</ul>")
        return "\n".join(parts)
    except Exception:
        return "<p><small>No recent activity data.</small></p>"


# ═══════════════════════════════════════════════════════════════════
# SPARK — daily counts for sparkline
# ═══════════════════════════════════════════════════════════════════

@router.get("/spark")
async def stats_spark(
    metric: str = Query("messages", description="Metric to chart"),
    days: int = Query(7, ge=1, le=90),
):
    """Return daily counts for sparkline display.

    Returns JSON: [{"date": "2025-07-10", "count": 15}, ...]
    """
    try:
        from brain_mcp.server.db import get_conversations
        con = get_conversations()
        rows = con.execute(f"""
            SELECT CAST(created AS DATE) AS day, COUNT(*) AS cnt
            FROM conversations
            WHERE created >= CURRENT_DATE - INTERVAL '{days}' DAY
            GROUP BY day
            ORDER BY day
        """).fetchall()
        return [{"date": str(row[0]), "count": row[1]} for row in rows]
    except Exception:
        return []
