"""Tests for the Sirius Prediction Market API client."""

import json
import unittest
from http.server import HTTPServer, BaseHTTPRequestHandler
from threading import Thread
from typing import Any, Dict

from sirius_prediction_api import (
    SiriusAPI,
    SiriusAPIError,
    SiriusAuthError,
    SiriusForbiddenError,
    SiriusRateLimitError,
    SiriusNotFoundError,
    SiriusServerError,
)


# ---------------------------------------------------------------------------
# Tiny HTTP server for integration-style tests
# ---------------------------------------------------------------------------

_MOCK_RESPONSES: Dict[str, Any] = {
    "/v1/health": {"status": "ok", "uptime": "42h"},
    "/v1/markets": [{"question": "Will BTC hit 100k?", "odds": 0.65}],
    "/v1/signals": [{"layer": "L1", "gap": 0.12, "direction": "BUY"}],
    "/v1/signals/history": [{"id": 1, "outcome": "WIN"}],
    "/v1/sentiment": {"fear_greed": 55, "long_short": 1.2},
    "/v1/sports": [{"sport": "NBA", "game": "LAL vs BOS"}],
    "/v1/weather": [{"city": "Miami", "temp": 28}],
    "/v1/odds": [{"platform": "Polymarket", "odds": 0.72}],
    "/v1/performance": {"win_rate": 0.75, "pnl": 18.19},
    "/v1/trades": [{"id": 1, "side": "BUY", "pnl": 1.5}],
    "/v1/brain": {"kelly": 0.40, "trailing": 0.05},
}


class _MockHandler(BaseHTTPRequestHandler):
    def do_GET(self) -> None:
        path = self.path.split("?")[0]

        # Check auth header
        key = self.headers.get("X-RapidAPI-Key", "")
        if key == "INVALID":
            self.send_response(401)
            self.end_headers()
            self.wfile.write(json.dumps({"message": "Unauthorized"}).encode())
            return

        if key == "FORBIDDEN":
            self.send_response(403)
            self.end_headers()
            self.wfile.write(json.dumps({"message": "Forbidden"}).encode())
            return

        if path in _MOCK_RESPONSES:
            body = json.dumps(_MOCK_RESPONSES[path]).encode()
            self.send_response(200)
            self.send_header("Content-Type", "application/json")
            self.end_headers()
            self.wfile.write(body)
        else:
            self.send_response(404)
            self.end_headers()
            self.wfile.write(json.dumps({"message": "Not found"}).encode())

    def log_message(self, format: str, *args: Any) -> None:  # noqa: A002
        pass  # silence request logs during tests


class TestSiriusAPI(unittest.TestCase):
    server: HTTPServer
    thread: Thread
    base_url: str

    @classmethod
    def setUpClass(cls) -> None:
        cls.server = HTTPServer(("127.0.0.1", 0), _MockHandler)
        port = cls.server.server_address[1]
        cls.base_url = "http://127.0.0.1:{}".format(port)
        cls.thread = Thread(target=cls.server.serve_forever, daemon=True)
        cls.thread.start()

    @classmethod
    def tearDownClass(cls) -> None:
        cls.server.shutdown()

    def _client(self, key: str = "TEST_KEY") -> SiriusAPI:
        return SiriusAPI(key, base_url=self.base_url, timeout=5)

    # -- Constructor -------------------------------------------------------

    def test_empty_key_raises(self) -> None:
        with self.assertRaises(ValueError):
            SiriusAPI("")

    # -- Endpoints ---------------------------------------------------------

    def test_health(self) -> None:
        result = self._client().health()
        self.assertEqual(result["status"], "ok")

    def test_markets(self) -> None:
        result = self._client().markets()
        self.assertIsInstance(result, list)
        self.assertEqual(result[0]["question"], "Will BTC hit 100k?")

    def test_signals(self) -> None:
        result = self._client().signals(limit=10, layer="L1", min_gap=0.1)
        self.assertIsInstance(result, list)

    def test_signals_history(self) -> None:
        result = self._client().signals_history()
        self.assertIsInstance(result, list)

    def test_sentiment(self) -> None:
        result = self._client().sentiment()
        self.assertIn("fear_greed", result)

    def test_sports(self) -> None:
        result = self._client().sports()
        self.assertIsInstance(result, list)

    def test_weather(self) -> None:
        result = self._client().weather()
        self.assertIsInstance(result, list)

    def test_odds(self) -> None:
        result = self._client().odds()
        self.assertIsInstance(result, list)

    def test_performance(self) -> None:
        result = self._client().performance()
        self.assertIn("win_rate", result)

    def test_trades(self) -> None:
        result = self._client().trades()
        self.assertIsInstance(result, list)

    def test_brain(self) -> None:
        result = self._client().brain()
        self.assertIn("kelly", result)

    # -- Error handling ----------------------------------------------------

    def test_auth_error(self) -> None:
        with self.assertRaises(SiriusAuthError):
            self._client("INVALID").health()

    def test_forbidden_error(self) -> None:
        with self.assertRaises(SiriusForbiddenError):
            self._client("FORBIDDEN").health()

    def test_not_found_error(self) -> None:
        client = self._client()
        with self.assertRaises(SiriusNotFoundError):
            client._request("/v1/nonexistent")


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