"""Unit tests — Spec 033 stack health probes (expect_status hardening)."""

from __future__ import annotations

import importlib.util
import sys
import unittest
from pathlib import Path
from unittest.mock import MagicMock, patch

API_ROOT = Path(__file__).resolve().parent
if not (API_ROOT / "app" / "stack_health.py").is_file():
    API_ROOT = API_ROOT.parent


def _load_stack_health():
    path = API_ROOT / "app/stack_health.py"
    spec = importlib.util.spec_from_file_location("stack_health_033", path)
    if spec is None or spec.loader is None:
        raise ImportError(path)
    mod = importlib.util.module_from_spec(spec)
    sys.modules["stack_health_033"] = mod
    spec.loader.exec_module(mod)
    return mod


sh = _load_stack_health()


class TestNormalizeExpectStatus(unittest.TestCase):
    def test_single_int(self):
        self.assertEqual(sh._normalize_expect_status(200), (200,))

    def test_single_element_tuple_with_comma(self):
        self.assertEqual(sh._normalize_expect_status((200,)), (200,))

    def test_multi_status_tuple(self):
        self.assertEqual(sh._normalize_expect_status((200, 301, 302)), (200, 301, 302))

    def test_list_from_yaml_contract(self):
        self.assertEqual(sh._normalize_expect_status([200, 403]), (200, 403))

    def test_invalid_type_raises(self):
        with self.assertRaises(TypeError):
            sh._normalize_expect_status("200")  # type: ignore[arg-type]


class TestProbeHttpExpectStatus(unittest.TestCase):
    @patch("stack_health_033.httpx.Client")
    def test_int_expect_status_does_not_crash(self, client_cls):
        res = MagicMock()
        res.status_code = 200
        client_cls.return_value.__enter__.return_value.get.return_value = res

        out = sh._probe_http(url="http://example.test/health", expect_status=200)

        self.assertTrue(out["ok"])
        self.assertEqual(out["http_status"], 200)
        self.assertEqual(out["detail"], "HTTP 200")

    @patch("stack_health_033.httpx.Client")
    def test_default_expect_status_tuple(self, client_cls):
        res = MagicMock()
        res.status_code = 200
        client_cls.return_value.__enter__.return_value.get.return_value = res

        out = sh._probe_http(url="http://example.test/")

        self.assertTrue(out["ok"])

    @patch("stack_health_033.httpx.Client")
    def test_wrong_status_marks_check(self, client_cls):
        res = MagicMock()
        res.status_code = 503
        client_cls.return_value.__enter__.return_value.get.return_value = res

        out = sh._probe_http(url="http://example.test/", expect_status=(200,))

        self.assertFalse(out["ok"])
        self.assertEqual(out["status"], "check")


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