"""Tests para http_get_json."""

import json
import sys
import unittest
import urllib.error
import urllib.request
from io import BytesIO
from unittest.mock import MagicMock, patch

sys.path.insert(0, "/home/lucas/fn_registry/python/functions")

from infra.http_get_json import http_get_json


def _make_response(data: bytes, status: int = 200, content_type: str = "application/json"):
    """Crea un mock de HTTPResponse."""
    resp = MagicMock()
    resp.read.return_value = data
    resp.status = status
    resp.__enter__ = lambda s: s
    resp.__exit__ = MagicMock(return_value=False)
    return resp


class TestHttpGetJson(unittest.TestCase):

    def test_mock_respuesta_200_con_json(self):
        payload = {"ok": True, "value": 42}
        mock_resp = _make_response(json.dumps(payload).encode())
        with patch("urllib.request.urlopen", return_value=mock_resp):
            result = http_get_json("http://example.com/api")
        self.assertEqual(result, payload)

    def test_mock_respuesta_404_error_con_status_code(self):
        err = urllib.error.HTTPError(
            url="http://example.com/missing",
            code=404,
            msg="Not Found",
            hdrs=None,  # type: ignore[arg-type]
            fp=BytesIO(b"not found"),
        )
        with patch("urllib.request.urlopen", side_effect=err):
            with self.assertRaises(RuntimeError) as ctx:
                http_get_json("http://example.com/missing")
        self.assertIn("404", str(ctx.exception))

    def test_mock_respuesta_json_invalido_error_descriptivo(self):
        mock_resp = _make_response(b"not-json!!!")
        with patch("urllib.request.urlopen", return_value=mock_resp):
            with self.assertRaises(RuntimeError) as ctx:
                http_get_json("http://example.com/api")
        self.assertIn("not valid JSON", str(ctx.exception))

    def test_params_serializados_como_query_string(self):
        captured_url = []

        def fake_urlopen(req, timeout=None):
            captured_url.append(req.full_url)
            return _make_response(b"{}")

        with patch("urllib.request.urlopen", side_effect=fake_urlopen):
            http_get_json("http://example.com/api", params={"page": "1", "limit": "10"})

        url = captured_url[0]
        self.assertIn("page=1", url)
        self.assertIn("limit=10", url)

    def test_headers_custom_enviados(self):
        captured_headers = []

        def fake_urlopen(req, timeout=None):
            captured_headers.append(dict(req.headers))
            return _make_response(b'{"x": 1}')

        with patch("urllib.request.urlopen", side_effect=fake_urlopen):
            http_get_json("http://example.com/api", headers={"X-Api-Key": "secret"})

        # urllib capitaliza el primer caracter de cada header
        headers_lower = {k.lower(): v for k, v in captured_headers[0].items()}
        self.assertIn("x-api-key", headers_lower)
        self.assertEqual(headers_lower["x-api-key"], "secret")
        self.assertIn("accept", headers_lower)


if __name__ == "__main__":
    unittest.main()
