"""
IwoooS Wazuh read-only metadata status.

This module returns public-safe aggregate metadata only. It never stores raw
Wazuh payloads, never exposes agent identity or LAN topology, and never
authorizes active response or host writes.
"""

from __future__ import annotations

import os
from base64 import b64encode
from dataclasses import dataclass
from typing import Any
from urllib.parse import urljoin, urlparse

import httpx

REQUEST_TIMEOUT_SECONDS = 5.0


@dataclass(frozen=True)
class WazuhReadonlyStatus:
    payload: dict[str, Any]
    http_status: int = 200


def wazuh_env() -> dict[str, str]:
    return {
        "enabled": os.getenv("IWOOOS_WAZUH_READONLY_ENABLED", "").strip().lower(),
        "base_url": os.getenv("WAZUH_API_BASE_URL", "").strip(),
        "username": os.getenv("WAZUH_API_USERNAME", "").strip(),
        "password": os.getenv("WAZUH_API_PASSWORD", "").strip(),
        "expected_min_agent_count": os.getenv("IWOOOS_WAZUH_EXPECTED_MIN_AGENT_COUNT", "").strip(),
    }


def expected_min_agent_count(value: str) -> int:
    try:
        return max(0, int(value))
    except ValueError:
        return 0


def https_url(value: str) -> str | None:
    parsed = urlparse(value)
    if parsed.scheme != "https" or not parsed.netloc:
        return None
    return value.rstrip("/") + "/"


def boundaries() -> dict[str, bool]:
    return {
        "active_response_authorized": False,
        "host_write_authorized": False,
        "secret_value_collection_allowed": False,
        "raw_wazuh_payload_storage_allowed": False,
        "agent_identity_public_display_allowed": False,
        "internal_ip_public_display_allowed": False,
        "not_authorization": True,
    }


def boundary_status(status_text: str, http_status: int = 200) -> WazuhReadonlyStatus:
    return WazuhReadonlyStatus(
        http_status=http_status,
        payload={
            "schema_version": "iwooos_wazuh_readonly_status_v1",
            "status": status_text,
            "mode": "metadata_only_no_active_response_no_raw_payload",
            "configured": False,
            "summary": {
                "wazuh_platform_reported_count": 1,
                "readonly_api_enabled_count": 0,
                "wazuh_manager_query_accepted_count": 0,
                "wazuh_event_accepted_count": 0,
                "host_forensics_accepted_count": 0,
                "active_response_authorized_count": 0,
                "host_write_authorized_count": 0,
                "runtime_gate_count": 0,
                "expected_min_agent_count": expected_min_agent_count(wazuh_env()["expected_min_agent_count"]),
                "agent_registry_empty_count": 0,
                "agent_below_expected_minimum_count": 0,
                "agent_visibility_no_false_green_count": 1,
            },
            "boundaries": boundaries(),
        },
    )


def redacted_agent(agent: dict[str, Any], index: int) -> dict[str, Any]:
    os_info = agent.get("os") if isinstance(agent.get("os"), dict) else {}
    return {
        "alias": f"agent-{index + 1:02d}",
        "status": agent.get("status", "unknown"),
        "os": os_info.get("platform") or os_info.get("name") or "unknown",
        "last_seen_present": bool(agent.get("lastKeepAlive")),
    }


def int_or_default(value: Any, default: int) -> int:
    return value if isinstance(value, int) else default


def agent_visibility_status(agent_total: int, expected_minimum: int) -> str:
    if agent_total <= 0:
        return "wazuh_agent_registry_empty"
    if expected_minimum > 0 and agent_total < expected_minimum:
        return "wazuh_agent_registry_below_expected"
    return "readonly_metadata_available"


async def fetch_json(client: httpx.AsyncClient, url: str, headers: dict[str, str]) -> dict[str, Any]:
    response = await client.get(url, headers=headers)
    response.raise_for_status()
    payload = response.json()
    return payload if isinstance(payload, dict) else {}


async def load_iwooos_wazuh_readonly_status() -> WazuhReadonlyStatus:
    env = wazuh_env()
    if env["enabled"] != "true":
        return boundary_status("disabled_waiting_iwooos_wazuh_owner_gate")

    base_url = https_url(env["base_url"])
    if not base_url or not env["username"] or not env["password"]:
        return boundary_status("misconfigured_missing_server_side_wazuh_env", 503)

    try:
        auth_header = b64encode(f"{env['username']}:{env['password']}".encode("utf-8")).decode("ascii")
        async with httpx.AsyncClient(timeout=REQUEST_TIMEOUT_SECONDS) as client:
            auth = await fetch_json(
                client,
                urljoin(base_url, "security/user/authenticate"),
                {"Authorization": f"Basic {auth_header}"},
            )
            token = (auth.get("data") or {}).get("token")
            if not token:
                return boundary_status("wazuh_auth_token_missing", 502)

            bearer_headers = {"Authorization": f"Bearer {token}"}
            status_payload = await fetch_json(
                client,
                urljoin(base_url, "agents/summary/status"),
                bearer_headers,
            )
            agents_payload = await fetch_json(
                client,
                urljoin(base_url, "agents?limit=100&select=id,status,os.name,os.platform,lastKeepAlive"),
                bearer_headers,
            )
    except (httpx.HTTPError, ValueError):
        return boundary_status("wazuh_readonly_metadata_unavailable", 502)

    connection = ((status_payload.get("data") or {}).get("connection") or {})
    affected_items = ((agents_payload.get("data") or {}).get("affected_items") or [])
    if not isinstance(affected_items, list):
        affected_items = []
    expected_minimum = expected_min_agent_count(env["expected_min_agent_count"])
    agent_total = int_or_default(connection.get("total"), len(affected_items))
    agent_active = int_or_default(connection.get("active"), 0)
    agent_disconnected = int_or_default(connection.get("disconnected"), 0)
    agent_pending = int_or_default(connection.get("pending"), 0)
    agent_registry_empty = agent_total <= 0
    agent_below_expected = expected_minimum > 0 and agent_total < expected_minimum

    return WazuhReadonlyStatus(
        payload={
            "schema_version": "iwooos_wazuh_readonly_status_v1",
            "status": agent_visibility_status(agent_total, expected_minimum),
            "mode": "metadata_only_no_active_response_no_raw_payload",
            "configured": True,
            "summary": {
                "wazuh_platform_reported_count": 1,
                "readonly_api_enabled_count": 1,
                "agent_total": agent_total,
                "agent_active": agent_active,
                "agent_disconnected": agent_disconnected,
                "agent_pending": agent_pending,
                "expected_min_agent_count": expected_minimum,
                "agent_registry_empty_count": 1 if agent_registry_empty else 0,
                "agent_below_expected_minimum_count": 1 if agent_below_expected else 0,
                "agent_visibility_no_false_green_count": 1,
                "wazuh_manager_query_accepted_count": 0,
                "wazuh_event_accepted_count": 0,
                "host_forensics_accepted_count": 0,
                "active_response_authorized_count": 0,
                "host_write_authorized_count": 0,
                "runtime_gate_count": 0,
            },
            "agents": [redacted_agent(agent, index) for index, agent in enumerate(affected_items[:20])],
            "boundaries": boundaries(),
        },
    )
