"""Wazuh SOC — dados para Audit Overview (tenant VM104)."""

from __future__ import annotations

import json
import os
import sqlite3
from datetime import datetime, timedelta, timezone
from typing import Any

import httpx

WAZUH_TENANT_ID = 2
WAZUH_API_URL = os.getenv("WAZUH_API_URL", "https://10.10.10.104:55000/")
WAZUH_MIN_LEVEL = int(os.getenv("WAZUH_MIN_TICKET_LEVEL", "10"))


def _now() -> str:
    return datetime.now(timezone.utc).isoformat()


def _parse_payload(raw: str | dict) -> dict:
    if isinstance(raw, dict):
        return raw
    try:
        return json.loads(raw or "{}")
    except json.JSONDecodeError:
        return {}


def wazuh_api_status() -> dict:
    try:
        with httpx.Client(timeout=5.0, verify=False) as client:
            response = client.get(WAZUH_API_URL)
        online = response.status_code in (200, 401)
        return {
            "reachable": True,
            "http_status": response.status_code,
            "api_online": online,
        }
    except Exception as exc:
        return {"reachable": False, "http_status": None, "api_online": False, "error": str(exc)}


def _parse_alert_row(row: sqlite3.Row) -> dict:
    payload = _parse_payload(row["payload"])
    data = payload.get("data") or {}
    level = int(data.get("level") or 0)
    return {
        "id": row["id"],
        "event_type": row["event_type"],
        "created_at": row["created_at"],
        "level": level,
        "rule_id": data.get("rule_id"),
        "description": (data.get("description") or "").strip(),
        "agent": (data.get("agent") or payload.get("domain") or "—").strip(),
        "agent_ip": data.get("agent_ip"),
        "srcip": data.get("srcip"),
        "session_id": payload.get("session_id"),
        "severity": _level_severity(level),
    }


def _level_severity(level: int) -> str:
    if level >= 12:
        return "critical"
    if level >= WAZUH_MIN_LEVEL:
        return "high"
    if level >= 7:
        return "medium"
    return "low"


def list_wazuh_alerts(conn: sqlite3.Connection, limit: int = 200) -> list[dict]:
    rows = conn.execute(
        """
        SELECT id, event_type, payload, created_at
        FROM webhook_events
        WHERE source = 'wazuh'
        ORDER BY id DESC
        LIMIT ?
        """,
        (limit,),
    ).fetchall()
    return [_parse_alert_row(r) for r in rows]


def _in_hours(iso: str | None, hours: int) -> bool:
    if not iso:
        return False
    try:
        ts = datetime.fromisoformat(iso.replace("Z", "+00:00"))
        if ts.tzinfo is None:
            ts = ts.replace(tzinfo=timezone.utc)
        return datetime.now(timezone.utc) - ts <= timedelta(hours=hours)
    except ValueError:
        return False


def _build_agents(alerts: list[dict]) -> list[dict]:
    agents: dict[str, dict] = {}
    for alert in alerts:
        name = alert["agent"] or "—"
        entry = agents.setdefault(
            name,
            {
                "agent": name,
                "agent_ip": alert.get("agent_ip"),
                "alerts_count": 0,
                "max_level": 0,
                "last_seen": alert["created_at"],
            },
        )
        entry["alerts_count"] += 1
        entry["max_level"] = max(entry["max_level"], alert["level"])
        if alert["created_at"] > entry["last_seen"]:
            entry["last_seen"] = alert["created_at"]
            if alert.get("agent_ip"):
                entry["agent_ip"] = alert["agent_ip"]
    return sorted(agents.values(), key=lambda a: (-a["max_level"], -a["alerts_count"]))


def _overall_status(alerts: list[dict], api_online: bool, open_tickets: int) -> str:
    recent_24h = [a for a in alerts if _in_hours(a["created_at"], 24)]
    max_level_24h = max((a["level"] for a in recent_24h), default=0)
    if max_level_24h >= 12 or open_tickets > 0:
        return "critical"
    if any(a["level"] >= WAZUH_MIN_LEVEL for a in recent_24h):
        return "degraded"
    if alerts and api_online:
        return "healthy"
    if api_online:
        return "healthy"
    if alerts:
        return "degraded"
    return "unknown"


def wazuh_tenant_overview(
    conn: sqlite3.Connection,
    tenant_id: int,
    name: str,
    ip: str,
) -> dict:
    alerts = list_wazuh_alerts(conn, 200)
    agents = _build_agents(alerts)
    api = wazuh_api_status()
    open_tickets = conn.execute(
        "SELECT COUNT(*) c FROM tickets WHERE tenant_id = ? AND status NOT IN ('closed', 'resolved')",
        (tenant_id,),
    ).fetchone()["c"]
    alerts_24h = sum(1 for a in alerts if _in_hours(a["created_at"], 24))
    alerts_high = sum(1 for a in alerts if a["level"] >= WAZUH_MIN_LEVEL)
    status = _overall_status(alerts, api.get("api_online", False), open_tickets)
    last_alert = alerts[0]["created_at"] if alerts else None
    top_issues = [
        {
            "domain": a["agent"],
            "check_id": f"L{a['level']}",
            "status": a["severity"],
            "message": a["description"] or a["event_type"],
            "at": a["created_at"],
        }
        for a in alerts[:5]
    ]
    return {
        "tenant_id": tenant_id,
        "name": name,
        "ip": ip,
        "kind": "wazuh_soc",
        "status": status,
        "api_online": api.get("api_online", False),
        "http_status": api.get("http_status"),
        "alerts_total": len(alerts),
        "alerts_24h": alerts_24h,
        "alerts_high": alerts_high,
        "agents_count": len(agents),
        "open_tickets": open_tickets,
        "min_ticket_level": WAZUH_MIN_LEVEL,
        "domains_count": 0,
        "last_audit_at": last_alert,
        "last_alert_at": last_alert,
        "score": {
            "pass": len(agents),
            "warn": alerts_high,
            "fail": open_tickets,
            "total": max(len(alerts), 1),
        },
        "top_issues": top_issues,
    }


def wazuh_tenant_details(
    conn: sqlite3.Connection,
    tenant_id: int,
    name: str,
    ip: str,
) -> dict:
    alerts = list_wazuh_alerts(conn, 100)
    agents = _build_agents(alerts)
    api = wazuh_api_status()
    tickets = conn.execute(
        """
        SELECT id, subject, status, created_at, session_id
        FROM tickets WHERE tenant_id = ?
        ORDER BY id DESC LIMIT 50
        """,
        (tenant_id,),
    ).fetchall()
    ticket_rows = [dict(r) for r in tickets]
    open_tickets = sum(1 for t in ticket_rows if t["status"] not in ("closed", "resolved"))
    alerts_24h = [a for a in alerts if _in_hours(a["created_at"], 24)]
    alerts_7d = [a for a in alerts if _in_hours(a["created_at"], 168)]
    level_10_plus = sum(1 for a in alerts if a["level"] >= WAZUH_MIN_LEVEL)
    level_12_plus = sum(1 for a in alerts if a["level"] >= 12)
    return {
        "tenant_id": tenant_id,
        "name": name,
        "ip": ip,
        "kind": "wazuh_soc",
        "generated_at": _now(),
        "api": api,
        "min_ticket_level": WAZUH_MIN_LEVEL,
        "summary": {
            "alerts_total": len(alerts),
            "alerts_24h": len(alerts_24h),
            "alerts_7d": len(alerts_7d),
            "agents_total": len(agents),
            "level_10_plus": level_10_plus,
            "level_12_plus": level_12_plus,
            "open_tickets": open_tickets,
            "api_online": api.get("api_online", False),
        },
        "agents": agents,
        "alerts": alerts,
        "tickets": ticket_rows,
        "domains": [],
    }
