"""
Тесты для валидации ответов ResponseValidator.

Этот модуль содержит unit-тесты для проверки работы декораторов валидации.
Тесты используют DummyResponse для имитации HTTP-ответов.
"""
import unittest

from request_handlers import ResponseValidator


class DummyResponse:
    """Mock объект для имитации HTTP ответа."""

    def __init__(self, *, status_code=200, headers=None, text="", json_data=None):
        default_headers = {"content-type": "application/json"}
        self.status_code = status_code
        self.headers = headers or default_headers
        self._text = text
        self._json_data = json_data
        self.url = "https://example.com/api"
        self.request = type("Req", (), {"method": "GET", "headers": {"X-Test": "1"}})()

    @property
    def text(self):
        """Возвращает текстовое содержимое ответа."""
        return self._text

    @property
    def content(self):
        """Возвращает бинарное содержимое ответа."""
        return self._text.encode("utf-8")

    def json(self, **kwargs):
        """Возвращает JSON данные."""
        if self._json_data is None:
            raise ValueError("no json body")
        return self._json_data


class ResponseValidatorTests(unittest.IsolatedAsyncioTestCase):
    """Тесты для декораторов валидации ResponseValidator."""

    async def test_status_validator_marks_error(self):
        """Тест: валидатор статус-кода должен фиксировать ошибку при неверном коде."""
        @ResponseValidator.status([200])
        async def fetch():
            return DummyResponse(status_code=404, headers={"content-type": "text/html"})

        result = await fetch()
        # Проверяем, что есть ошибки валидации
        self.assertTrue(result.valid.has_errors())
        self.assertEqual(result.valid.ERRORS[0].key, "STATUS_CODE")
        # Проверяем доступ к оригинальному response
        self.assertEqual(result.response.status_code, 404)

    async def test_regex_parser_saves_capture(self):
        """Тест: regex валидатор должен сохранять извлеченные данные в PARSED."""
        sample_json = {"token": "abc123", "user": {"email": "user@example.com"}}

        @ResponseValidator.regex(r'"token"\s*:\s*"([^\"]+)"', target="json", save_to="token")
        async def fetch():
            return DummyResponse(json_data=sample_json)

        result = await fetch()
        # Проверяем, что токен был извлечен и сохранен
        self.assertEqual(result.valid.PARSED["token"], "abc123")
        self.assertFalse(result.valid.has_errors())

    async def test_regex_expect_no_match_records_error(self):
        """Тест: regex валидатор с expect_match=False должен фиксировать ошибку при наличии совпадения."""
        @ResponseValidator.regex(r"error", expect_match=False)
        async def fetch_ok():
            return DummyResponse(text="everything is ok")

        ok_result = await fetch_ok()
        self.assertFalse(ok_result.valid.has_errors())

        @ResponseValidator.regex(r"error", expect_match=False)
        async def fetch_error():
            return DummyResponse(text="error occurred")

        error_result = await fetch_error()
        self.assertTrue(error_result.valid.has_errors())
        self.assertEqual(error_result.valid.ERRORS[0].key, "REGEX")


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