"""Manual ingestion of Hell Let Loose RCON AdminLog events."""

from __future__ import annotations

import argparse
import json
from dataclasses import dataclass

from .config import get_rcon_request_timeout_seconds
from .rcon_admin_log_storage import (
    list_rcon_admin_log_event_counts,
    persist_rcon_admin_log_entries,
)
from .rcon_client import HllRconConnection, build_rcon_target_key, load_rcon_targets


@dataclass(slots=True)
class AdminLogIngestionStats:
    targets_seen: int = 0
    events_seen: int = 0
    events_inserted: int = 0
    duplicate_events: int = 0
    failed_targets: int = 0


def ingest_rcon_admin_logs(
    *,
    minutes: int,
    target_key: str | None = None,
) -> dict[str, object]:
    """Fetch and persist recent AdminLog entries from configured RCON targets."""
    selected_targets = _select_targets(target_key)
    stats = AdminLogIngestionStats()
    targets: list[dict[str, object]] = []
    errors: list[dict[str, object]] = []
    timeout_seconds = get_rcon_request_timeout_seconds()

    for target in selected_targets:
        stats.targets_seen += 1
        target_metadata = _serialize_target(target)

        try:
            with HllRconConnection(timeout_seconds=timeout_seconds) as connection:
                connection.connect(host=target.host, port=target.port, password=target.password)
                payload = connection.execute_json(
                    "GetAdminLog",
                    {
                        "LogBackTrackTime": minutes * 60,
                        "Filters": [],
                    },
                )

            entries = payload.get("entries")
            if not isinstance(entries, list):
                entries = []

            normalized_entries = [entry for entry in entries if isinstance(entry, dict)]
            delta = persist_rcon_admin_log_entries(
                target=target_metadata,
                entries=normalized_entries,
            )

            stats.events_seen += int(delta["events_seen"])
            stats.events_inserted += int(delta["events_inserted"])
            stats.duplicate_events += int(delta["duplicate_events"])
            targets.append(
                {
                    **target_metadata,
                    "status": "ok",
                    "minutes": minutes,
                    **delta,
                }
            )
        except Exception as exc:  # noqa: BLE001 - manual diagnostic command reports per-target failures
            stats.failed_targets += 1
            errors.append(
                {
                    **target_metadata,
                    "status": "error",
                    "error_type": type(exc).__name__,
                    "message": str(exc),
                }
            )

    return {
        "status": "ok" if not errors else ("partial" if targets else "error"),
        "target_scope": target_key or "all-configured-rcon-targets",
        "minutes": minutes,
        "targets": targets,
        "errors": errors,
        "totals": {
            "targets_seen": stats.targets_seen,
            "events_seen": stats.events_seen,
            "events_inserted": stats.events_inserted,
            "duplicate_events": stats.duplicate_events,
            "failed_targets": stats.failed_targets,
        },
        "event_counts": list_rcon_admin_log_event_counts(),
    }


def _select_targets(target_key: str | None) -> list[object]:
    configured_targets = list(load_rcon_targets())
    if not configured_targets:
        raise RuntimeError("No RCON targets configured in HLL_BACKEND_RCON_TARGETS.")
    if target_key is None:
        return configured_targets

    normalized = target_key.strip()
    selected = [
        target
        for target in configured_targets
        if build_rcon_target_key(target) == normalized
    ]
    if not selected:
        raise ValueError(f"Unknown RCON target key: {target_key}")
    return selected


def _serialize_target(target: object) -> dict[str, object]:
    return {
        "target_key": build_rcon_target_key(target),
        "external_server_id": target.external_server_id,
        "name": target.name,
        "host": target.host,
        "port": target.port,
        "source_name": target.source_name,
    }


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--minutes", type=int, default=60)
    parser.add_argument("--target", default=None)
    args = parser.parse_args()

    print(
        json.dumps(
            ingest_rcon_admin_logs(minutes=args.minutes, target_key=args.target),
            ensure_ascii=False,
            indent=2,
        )
    )


if __name__ == "__main__":
    main()
