"""Test suite runner — orchestrates all suites, supports quick/full mode."""

from __future__ import annotations

import time
from dataclasses import dataclass, field
from typing import Any

import httpx

from .adversarial import run_adversarial_tests
from .protocol import run_protocol_tests
from .load import run_load_tests
from .edge_cases import run_edge_case_tests
from .consistency import run_consistency_tests
from .reflection import run_reflection_tests
from .info_leak import run_info_leak_tests

# Safety limits
REQUEST_TIMEOUT = 10.0       # seconds per individual HTTP request
MAX_CONNECTIONS = 150
MAX_KEEPALIVE = 80


@dataclass
class TestResult:
    test: str
    status: str          # PASS | FAIL | CRASH | WARN
    detail: str
    latency_ms: float = 0.0
    category: str = "general"
    severity: str = "LOW"      # CRITICAL | HIGH | MEDIUM | LOW | INFO
    cwe: str = ""


@dataclass
class SuiteOutput:
    results: list[TestResult] = field(default_factory=list)
    latencies: list[float] = field(default_factory=list)
    duration_ms: float = 0.0


ALL_SUITES = [
    run_adversarial_tests,
    run_protocol_tests,
    run_load_tests,
    run_edge_case_tests,
    run_consistency_tests,
    run_reflection_tests,
    run_info_leak_tests,
]

QUICK_SUITES = [
    run_adversarial_tests,
    run_protocol_tests,
    run_load_tests,
    run_reflection_tests,
    run_info_leak_tests,
]


async def run_all_suites(
    url: str,
    method: str,
    headers: dict[str, str] | None,
    body: Any | None,
    mode: str = "full",
) -> SuiteOutput:
    output = SuiteOutput()
    start = time.perf_counter()
    suites = QUICK_SUITES if mode == "quick" else ALL_SUITES

    async with httpx.AsyncClient(
        timeout=httpx.Timeout(REQUEST_TIMEOUT, connect=5.0),
        limits=httpx.Limits(max_connections=MAX_CONNECTIONS, max_keepalive_connections=MAX_KEEPALIVE),
    ) as client:
        for suite_fn in suites:
            results = await suite_fn(
                client=client,
                url=url,
                method=method,
                headers=headers,
                body=body,
                mode=mode,
            )
            for r in results:
                output.results.append(r)
                output.latencies.append(r.latency_ms)

    output.duration_ms = round((time.perf_counter() - start) * 1000, 1)
    return output
