from __future__ import annotations

from typing import Any

import httpx
import pytest

from eip_mcp import api_client


class _FakeResponse:
    def __init__(
        self,
        *,
        status_code: int,
        request_url: str,
        headers: dict[str, str] | None = None,
        payload: dict[str, Any] | None = None,
    ) -> None:
        self.status_code = status_code
        self.request = httpx.Request("GET", request_url)
        self.headers = headers or {}
        self._payload = payload or {}

    def json(self) -> dict[str, Any]:
        return self._payload


def _install_fake_client(
    monkeypatch: pytest.MonkeyPatch,
    responses: list[_FakeResponse],
    calls: list[tuple[str, dict[str, Any] | None]],
) -> None:
    class _FakeClient:
        def __init__(self, *args: Any, **kwargs: Any) -> None:
            pass

        def __enter__(self) -> "_FakeClient":
            return self

        def __exit__(self, exc_type: object, exc: object, tb: object) -> bool:
            return False

        def get(self, url: str, params: dict[str, Any] | None = None) -> _FakeResponse:
            calls.append((url, params))
            return responses.pop(0)

    monkeypatch.setattr(api_client.httpx, "Client", _FakeClient)


def test_request_json_preserves_params_across_queryless_redirect(monkeypatch: pytest.MonkeyPatch) -> None:
    params = {"q": "log4j", "per_page": 5}
    calls: list[tuple[str, dict[str, Any] | None]] = []
    responses = [
        _FakeResponse(
            status_code=302,
            request_url="https://exploit-intel.com/api/v1/vulns?q=log4j&per_page=5",
            headers={"Location": "https://www.exploit-intel.com/api/v1/vulns"},
        ),
        _FakeResponse(
            status_code=200,
            request_url="https://www.exploit-intel.com/api/v1/vulns?q=log4j&per_page=5",
            payload={"ok": True},
        ),
    ]
    _install_fake_client(monkeypatch, responses, calls)

    result = api_client._request_json("/api/v1/vulns", params=params)

    assert result == {"ok": True}
    assert calls == [
        ("https://exploit-intel.com/api/v1/vulns", params),
        ("https://www.exploit-intel.com/api/v1/vulns", params),
    ]


def test_request_json_does_not_duplicate_params_when_redirect_has_query(monkeypatch: pytest.MonkeyPatch) -> None:
    params = {"q": "ignored"}
    calls: list[tuple[str, dict[str, Any] | None]] = []
    responses = [
        _FakeResponse(
            status_code=302,
            request_url="https://exploit-intel.com/api/v1/vulns?q=ignored",
            headers={"Location": "https://www.exploit-intel.com/api/v1/vulns?q=redirected"},
        ),
        _FakeResponse(
            status_code=200,
            request_url="https://www.exploit-intel.com/api/v1/vulns?q=redirected",
            payload={"ok": True},
        ),
    ]
    _install_fake_client(monkeypatch, responses, calls)

    result = api_client._request_json("/api/v1/vulns", params=params)

    assert result == {"ok": True}
    assert calls == [
        ("https://exploit-intel.com/api/v1/vulns", params),
        ("https://www.exploit-intel.com/api/v1/vulns?q=redirected", None),
    ]


def test_request_json_non_redirect_behavior_is_unchanged(monkeypatch: pytest.MonkeyPatch) -> None:
    params = {"q": "apache"}
    calls: list[tuple[str, dict[str, Any] | None]] = []
    responses = [
        _FakeResponse(
            status_code=200,
            request_url="https://exploit-intel.com/api/v1/vulns?q=apache",
            payload={"items": []},
        )
    ]
    _install_fake_client(monkeypatch, responses, calls)

    result = api_client._request_json("/api/v1/vulns", params=params)

    assert result == {"items": []}
    assert calls == [("https://exploit-intel.com/api/v1/vulns", params)]
