"""Shared aggregation logic for EDR event processing."""

from datetime import datetime, timezone
from typing import Any

from astrix_openclaw_scanner.utils.timestamps import format_timestamp


def coalesce(*values: str | None) -> str:
    """Return the first non-empty value, or empty string."""
    for v in values:
        if v:
            return v
    return ""


def _prefer_known(val1: str, val2: str) -> str:
    """Return the non-Unknown value, preferring val1."""
    if val1 and val1 != "Unknown":
        return val1
    return val2


def _merge_entry(existing: dict[str, Any], new: dict[str, Any]) -> None:
    """Merge new entry into existing, preferring non-Unknown and latest ts."""
    for field in ("endpoint", "username", "os"):
        existing[field] = _prefer_known(existing[field], new[field])
    if new["ts"] and (existing["ts"] is None or new["ts"] > existing["ts"]):
        existing["ts"] = new["ts"]
        existing["commandline"] = new["commandline"]


def group_and_sort(
    entries: list[dict[str, Any]],
    os_mapping: dict[str, str],
) -> list[dict[str, Any]]:
    """Group normalized entries by endpoint/username and produce final output.

    Takes a list of entries with keys: endpoint, username, os, commandline, ts.
    Groups by (endpoint, username), merges duplicates preferring non-Unknown
    values and latest timestamps, then builds sorted output.

    Args:
        entries: Normalized entries from an EDR-specific aggregator
        os_mapping: Mapping from raw OS values to display names

    Returns:
        List of dicts with keys: endpoint, username, os, last_seen, commandline
    """
    if not entries:
        return []

    # Step 1: Group by (endpoint, username) and keep latest per group
    groups: dict[tuple[str, str], dict[str, Any]] = {}
    for entry in entries:
        key = (entry["endpoint"], entry["username"])
        if key not in groups:
            groups[key] = entry.copy()
        else:
            _merge_entry(groups[key], entry)

    # Step 2: Build output
    result: list[dict[str, Any]] = []
    for entry in groups.values():
        result.append(
            {
                "endpoint": entry["endpoint"],
                "username": entry["username"],
                "os": os_mapping.get(entry["os"], entry["os"]),
                "last_seen": format_timestamp(entry["ts"]),
                "commandline": entry.get("commandline") or "",
                "_ts": entry["ts"],
            }
        )

    # Sort by timestamp descending
    result.sort(
        key=lambda x: x.get("_ts") or datetime.min.replace(tzinfo=timezone.utc),
        reverse=True,
    )

    # Remove internal key
    for item in result:
        item.pop("_ts", None)

    return result
