from __future__ import annotations

from types import SimpleNamespace

import httpx
import pytest

from autodebug.agent.core import HikaflowDeps
from autodebug.agent.tools import register_hikaflow_tools


class _DummyAgent:
    def __init__(self):
        self.tools = {}

    def tool(self, fn):
        self.tools[fn.__name__] = fn
        return fn


class _FakeAsyncClient:
    def __init__(self, responder):
        self._responder = responder

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc, tb):
        return False

    async def request(self, method, url, headers=None, params=None, json=None, timeout=None):
        return self._responder(method, url, params)


def _ctx(tmp_path):
    deps = HikaflowDeps(
        api_base="https://api.example.com",
        token="tkn",
        project_path=str(tmp_path),
    )
    return SimpleNamespace(deps=deps)


def _get_tools():
    agent = _DummyAgent()
    register_hikaflow_tools(agent)
    return agent.tools


@pytest.mark.asyncio
async def test_list_sessions_surfaces_request_id_on_500(monkeypatch, tmp_path):
    monkeypatch.setattr(
        "autodebug.auth.get_credentials",
        lambda: {"project_id": "proj_1"},
    )
    monkeypatch.setattr(
        "autodebug.config.load_credentials",
        lambda: {"project_id": "proj_1"},
    )

    def _responder(method, url, _params):
        req = httpx.Request(method, url)
        return httpx.Response(
            500,
            request=req,
            text="sessions backend unavailable",
            headers={"x-request-id": "req-sess-123"},
        )

    monkeypatch.setattr(
        "autodebug.agent.tools.httpx.AsyncClient",
        lambda: _FakeAsyncClient(_responder),
    )

    tools = _get_tools()
    result = await tools["sessions"](_ctx(tmp_path))

    assert result.startswith("Error:")
    assert "500" in result
    assert "sessions backend unavailable" in result
    assert "request_id=req-sess-123" in result


@pytest.mark.asyncio
async def test_list_issue_groups_formats_success_response(monkeypatch, tmp_path):
    monkeypatch.setattr(
        "autodebug.auth.get_credentials",
        lambda: {"project_id": "proj_1"},
    )
    monkeypatch.setattr(
        "autodebug.config.load_credentials",
        lambda: {"project_id": "proj_1"},
    )

    def _responder(method, url, _params):
        req = httpx.Request(method, url)
        return httpx.Response(
            200,
            request=req,
            json={
                "groups": [
                    {
                        "id": "group_abc12345",
                        "title": "AssertionError cluster",
                        "member_count": 3,
                        "created_at": "2026-02-12T00:00:00Z",
                    }
                ]
            },
        )

    monkeypatch.setattr(
        "autodebug.agent.tools.httpx.AsyncClient",
        lambda: _FakeAsyncClient(_responder),
    )

    tools = _get_tools()
    result = await tools["issue_groups"](_ctx(tmp_path))

    assert "**Issue Groups (1):**" in result
    assert "AssertionError cluster" in result
    assert "| `group_ab` |" in result


@pytest.mark.asyncio
async def test_fetch_production_errors_surfaces_request_id_on_500(monkeypatch, tmp_path):
    monkeypatch.setattr(
        "autodebug.config.load_credentials",
        lambda: {"project_id": "proj_1"},
    )

    def _responder(method, url, _params):
        req = httpx.Request(method, url)
        return httpx.Response(
            500,
            request=req,
            text='{"detail":"Internal server error"}',
            headers={"x-request-id": "req-prod-500"},
        )

    monkeypatch.setattr(
        "autodebug.agent.tools.httpx.AsyncClient",
        lambda: _FakeAsyncClient(_responder),
    )

    tools = _get_tools()
    result = await tools["fetch_production_errors"](_ctx(tmp_path), limit=5)

    assert result.startswith("Error fetching errors:")
    assert "500" in result
    assert "request_id=req-prod-500" in result


@pytest.mark.asyncio
async def test_issue_groups_requires_project_link(monkeypatch, tmp_path):
    monkeypatch.setattr("autodebug.config.load_credentials", lambda: {})

    def _responder(method, url, _params):  # pragma: no cover - should never be hit
        req = httpx.Request(method, url)
        return httpx.Response(200, request=req, json={"groups": []})

    monkeypatch.setattr(
        "autodebug.agent.tools.httpx.AsyncClient",
        lambda: _FakeAsyncClient(_responder),
    )

    tools = _get_tools()
    result = await tools["issue_groups"](_ctx(tmp_path), action="list")

    assert result == "Error: No project linked. Run 'hikaflow init' first."


@pytest.mark.asyncio
async def test_issue_groups_surfaces_request_id_on_500(monkeypatch, tmp_path):
    monkeypatch.setattr("autodebug.config.load_credentials", lambda: {"project_id": "proj_1"})
    monkeypatch.setattr("autodebug.auth.get_credentials", lambda: {"project_id": "proj_1"})

    def _responder(method, url, _params):
        req = httpx.Request(method, url)
        return httpx.Response(
            500,
            request=req,
            text='{"detail":"Internal server error"}',
            headers={"x-request-id": "req-issues-500"},
        )

    monkeypatch.setattr(
        "autodebug.agent.tools.httpx.AsyncClient",
        lambda: _FakeAsyncClient(_responder),
    )

    tools = _get_tools()
    result = await tools["issue_groups"](_ctx(tmp_path), action="list")

    assert result.startswith("Error:")
    assert "500" in result
    assert "request_id=req-issues-500" in result


@pytest.mark.asyncio
async def test_fetch_production_errors_requires_project_link(monkeypatch, tmp_path):
    monkeypatch.setattr("autodebug.config.load_credentials", lambda: {})

    def _responder(method, url, _params):  # pragma: no cover - should never be hit
        req = httpx.Request(method, url)
        return httpx.Response(200, request=req, json={"errors": []})

    monkeypatch.setattr(
        "autodebug.agent.tools.httpx.AsyncClient",
        lambda: _FakeAsyncClient(_responder),
    )

    tools = _get_tools()
    result = await tools["fetch_production_errors"](_ctx(tmp_path), limit=5)

    assert result == "Error fetching errors: No project linked. Run 'hikaflow init' first."
