"""Wevitos MCP Server — exposes error tracking tools for AI coding assistants."""

import os

import httpx
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Wevitos")

BASE_URL = os.environ.get("WEVITOS_BASE_URL", "https://wevitos.com")


def _client(api_key: str) -> httpx.Client:
    return httpx.Client(
        base_url=f"{BASE_URL}/api",
        headers={"X-API-Key": api_key},
        timeout=30,
    )


@mcp.tool()
def list_errors(api_key: str, status: str = "open") -> str:
    """List error groups for a project. Status can be: open, resolved, ignored."""
    with _client(api_key) as client:
        resp = client.get("/errors/", params={"status": status})
        resp.raise_for_status()
        data = resp.json()

    results = data.get("results", [])
    if not results:
        return f"No errors with status '{status}'."

    lines = [f"Found {len(results)} error(s) with status '{status}':\n"]
    for e in results:
        lines.append(
            f"- [{e['id']}] {e['exception_class']}: {e['message']}\n"
            f"  File: {e['file_path']}:{e['line_number']} in {e['function_name']}\n"
            f"  Events: {e['event_count']} | Last seen: {e['last_seen']}"
        )
    return "\n".join(lines)


@mcp.tool()
def get_error(api_key: str, error_id: str) -> str:
    """Get error detail including stacktrace and metadata."""
    with _client(api_key) as client:
        resp = client.get(f"/errors/{error_id}/")
        resp.raise_for_status()
        e = resp.json()

    lines = [
        f"{e['exception_class']}: {e['message']}",
        f"Status: {e['status']}",
        f"File: {e['file_path']}:{e['line_number']} in {e['function_name']}",
        f"Events: {e['event_count']}",
        f"First seen: {e['first_seen']} | Last seen: {e['last_seen']}",
        f"Environment: {e.get('environment', '')} | Release: {e.get('release', '')}",
    ]

    stacktrace = e.get("stacktrace", [])
    if stacktrace:
        lines.append("\nStacktrace:")
        for frame in stacktrace:
            if isinstance(frame, dict):
                lines.append(
                    f"  {frame.get('file', '?')}:{frame.get('line', '?')} "
                    f"in {frame.get('function', '?')}"
                )
                if frame.get("code"):
                    lines.append(f"    > {frame['code']}")
            else:
                lines.append(f"  {frame}")

    return "\n".join(lines)


@mcp.tool()
def resolve_error(api_key: str, error_id: str, comment: str = "", author: str = "Claude Code") -> str:
    """Resolve an error. Optionally add a comment explaining the fix."""
    with _client(api_key) as client:
        resp = client.post(
            f"/errors/{error_id}/resolve/",
            json={"comment": comment, "author": author},
        )
        resp.raise_for_status()
    return f"Error {error_id} resolved." + (f" Comment: {comment}" if comment else "")


@mcp.tool()
def ignore_error(api_key: str, error_id: str, comment: str = "", author: str = "Claude Code") -> str:
    """Ignore an error. Optionally add a comment explaining why."""
    with _client(api_key) as client:
        resp = client.post(
            f"/errors/{error_id}/ignore/",
            json={"comment": comment, "author": author},
        )
        resp.raise_for_status()
    return f"Error {error_id} ignored." + (f" Comment: {comment}" if comment else "")


@mcp.tool()
def reopen_error(api_key: str, error_id: str, comment: str = "", author: str = "Claude Code") -> str:
    """Reopen a resolved or ignored error."""
    with _client(api_key) as client:
        resp = client.post(
            f"/errors/{error_id}/reopen/",
            json={"comment": comment, "author": author},
        )
        resp.raise_for_status()
    return f"Error {error_id} reopened." + (f" Comment: {comment}" if comment else "")


@mcp.tool()
def list_events(
    api_key: str,
    error_id: str,
    search: str = "",
    limit: int = 20,
    offset: int = 0,
) -> str:
    """List individual events within an error group. Use search to filter by message text (e.g. 'yt-dlp', 'instagram.com')."""
    params = {"limit": limit, "offset": offset}
    if search:
        params["search"] = search

    with _client(api_key) as client:
        resp = client.get(f"/errors/{error_id}/events/", params=params)
        resp.raise_for_status()
        data = resp.json()

    results = data.get("results", [])
    total = data.get("total", 0)

    if not results:
        msg = f"No events found"
        if search:
            msg += f" matching '{search}'"
        return msg + "."

    lines = [f"Events {offset + 1}-{offset + len(results)} of {total}"]
    if search:
        lines[0] += f" (search: '{search}')"
    lines.append("")

    for e in results:
        lines.append(
            f"- [{e['id'][:8]}] {e['exception_class']}: {e['message']}\n"
            f"  Time: {e['timestamp']} | Env: {e.get('environment', '')} | Release: {e.get('release', '')}"
        )

    if offset + len(results) < total:
        lines.append(f"\n... {total - offset - len(results)} more events. Use offset={offset + limit} to see next page.")

    return "\n".join(lines)


@mcp.tool()
def event_breakdown(api_key: str, error_id: str) -> str:
    """Get a breakdown of events in an error group by message pattern and domain. Useful for understanding what types of errors are grouped together."""
    with _client(api_key) as client:
        resp = client.get(f"/errors/{error_id}/breakdown/")
        resp.raise_for_status()
        data = resp.json()

    lines = [f"Breakdown for error {error_id} ({data['total_events']} total events)\n"]

    patterns = data.get("by_pattern", [])
    if patterns:
        lines.append("By pattern:")
        for p in patterns:
            lines.append(f"  {p['count']:>7,} — {p['pattern']}")

    domains = data.get("by_domain", [])
    if domains:
        lines.append("\nBy domain:")
        for d in domains:
            lines.append(f"  {d['count']:>7,} — {d['domain']}")

    if not patterns and not domains:
        lines.append("No patterns or domains found in event messages.")

    return "\n".join(lines)


def main():
    mcp.run()


if __name__ == "__main__":
    main()
