import asyncio
import json
import tempfile
import unittest
from pathlib import Path

from src.request_decorator_handlers import RequestDebugger, Validator


class DummyValidator(Validator):
    def __init__(self, *, status_code=200, url="https://example.com/data", errors=None, body=None):
        # Create lightweight proxy response
        self.status_code = status_code
        self.url = url
        self.headers = {"content-type": "application/json"}
        self._body = body or {"value": 42}
        self.request = type("Req", (), {"method": "GET", "headers": {"X-Test": "1"}})()
        super().__init__(self)  # populate .valid
        for error in errors or []:
            self.valid.add_error(**error)

    def json(self):
        return self._body


class RequestDebuggerTests(unittest.IsolatedAsyncioTestCase):
    async def test_debugger_stores_error_payload(self):
        with tempfile.TemporaryDirectory() as tmp:
            @RequestDebugger.debug(debug_dir=tmp, save_errors=True, save_unique_structures=False)
            async def failing_call():
                return DummyValidator(errors=[{"key": "STATUS_CODE", "expected": 200, "actual": 500}])

            await failing_call()

            files = list(Path(tmp).rglob("*.json"))
            self.assertTrue(files, "Expected error dump to be created")
            payload = json.loads(files[0].read_text(encoding="utf-8"))
            self.assertIn("errors", payload)
            self.assertEqual(payload["errors"][0]["key"], "STATUS_CODE")

    async def test_debugger_stores_unique_structure_once(self):
        with tempfile.TemporaryDirectory() as tmp:
            @RequestDebugger.debug(debug_dir=tmp, save_errors=False, save_unique_structures=True)
            async def call():
                return DummyValidator()

            await call()
            await call()  # second call should reuse hash

            files = list(Path(tmp).rglob("*.json"))
            self.assertEqual(len(files), 1, "Structure should be saved only once")


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