"""Derived duel and weapon aggregates computed from the raw player event ledger."""

from __future__ import annotations

import sqlite3
from pathlib import Path

from .config import get_database_url, get_storage_path
from .player_event_storage import initialize_player_event_storage


def list_most_killed(
    *,
    server_slug: str | None = None,
    month: str | None = None,
    external_match_id: str | None = None,
    limit: int = 10,
    db_path: Path | None = None,
) -> list[dict[str, object]]:
    """Return strongest killer -> victim summaries from the raw ledger."""
    return _query_pair_summary(
        event_type="player_kill_summary",
        server_slug=server_slug,
        month=month,
        external_match_id=external_match_id,
        limit=limit,
        db_path=db_path,
    )


def list_death_by(
    *,
    server_slug: str | None = None,
    month: str | None = None,
    external_match_id: str | None = None,
    limit: int = 10,
    db_path: Path | None = None,
) -> list[dict[str, object]]:
    """Return strongest killer -> victim summaries from the victim perspective."""
    return _query_pair_summary(
        event_type="player_death_summary",
        server_slug=server_slug,
        month=month,
        external_match_id=external_match_id,
        limit=limit,
        db_path=db_path,
    )


def list_net_duel_summaries(
    *,
    server_slug: str | None = None,
    month: str | None = None,
    external_match_id: str | None = None,
    limit: int = 10,
    db_path: Path | None = None,
) -> list[dict[str, object]]:
    """Return partial net duel summaries using the strongest encounter signals available."""
    resolved_path = initialize_player_event_storage(db_path=db_path)
    where_sql, params = _build_common_where(
        event_type="player_kill_summary",
        server_slug=server_slug,
        month=month,
        external_match_id=external_match_id,
    )
    with _connect(resolved_path) as connection:
        rows = connection.execute(
            f"""
            WITH duel_pairs AS (
                SELECT
                    CASE
                        WHEN COALESCE(killer_player_key, '') <= COALESCE(victim_player_key, '')
                        THEN killer_player_key
                        ELSE victim_player_key
                    END AS player_a_key,
                    CASE
                        WHEN COALESCE(killer_player_key, '') <= COALESCE(victim_player_key, '')
                        THEN killer_display_name
                        ELSE victim_display_name
                    END AS player_a_name,
                    CASE
                        WHEN COALESCE(killer_player_key, '') <= COALESCE(victim_player_key, '')
                        THEN victim_player_key
                        ELSE killer_player_key
                    END AS player_b_key,
                    CASE
                        WHEN COALESCE(killer_player_key, '') <= COALESCE(victim_player_key, '')
                        THEN victim_display_name
                        ELSE killer_display_name
                    END AS player_b_name,
                    CASE
                        WHEN COALESCE(killer_player_key, '') <= COALESCE(victim_player_key, '')
                        THEN event_value
                        ELSE -event_value
                    END AS net_value,
                    event_value
                FROM player_event_raw_ledger
                WHERE {where_sql}
                    AND killer_player_key IS NOT NULL
                    AND victim_player_key IS NOT NULL
            )
            SELECT
                player_a_key,
                player_a_name,
                player_b_key,
                player_b_name,
                COALESCE(SUM(event_value), 0) AS total_encounters,
                COALESCE(SUM(net_value), 0) AS net_duel_value
            FROM duel_pairs
            GROUP BY player_a_key, player_a_name, player_b_key, player_b_name
            ORDER BY ABS(COALESCE(SUM(net_value), 0)) DESC,
                     COALESCE(SUM(event_value), 0) DESC,
                     player_a_name ASC,
                     player_b_name ASC
            LIMIT ?
            """,
            [*params, limit],
        ).fetchall()
    return [dict(row) for row in rows]


def list_weapon_kills(
    *,
    server_slug: str | None = None,
    month: str | None = None,
    external_match_id: str | None = None,
    limit: int = 10,
    db_path: Path | None = None,
) -> list[dict[str, object]]:
    """Return partial weapon summaries derived from top kill events."""
    resolved_path = initialize_player_event_storage(db_path=db_path)
    where_sql, params = _build_common_where(
        event_type="player_weapon_kill_summary",
        server_slug=server_slug,
        month=month,
        external_match_id=external_match_id,
    )
    with _connect(resolved_path) as connection:
        rows = connection.execute(
            f"""
            SELECT
                killer_player_key,
                killer_display_name,
                COALESCE(weapon_name, 'unknown') AS weapon_name,
                COALESCE(SUM(event_value), 0) AS total_kills
            FROM player_event_raw_ledger
            WHERE {where_sql}
                AND killer_player_key IS NOT NULL
            GROUP BY killer_player_key, killer_display_name, COALESCE(weapon_name, 'unknown')
            ORDER BY total_kills DESC, killer_display_name ASC, weapon_name ASC
            LIMIT ?
            """,
            [*params, limit],
        ).fetchall()
    return [dict(row) for row in rows]


def list_teamkill_summaries(
    *,
    server_slug: str | None = None,
    month: str | None = None,
    external_match_id: str | None = None,
    limit: int = 10,
    db_path: Path | None = None,
) -> list[dict[str, object]]:
    """Return derived teamkill totals per player from the raw ledger."""
    resolved_path = initialize_player_event_storage(db_path=db_path)
    where_sql, params = _build_common_where(
        event_type="player_teamkill_summary",
        server_slug=server_slug,
        month=month,
        external_match_id=external_match_id,
    )
    with _connect(resolved_path) as connection:
        rows = connection.execute(
            f"""
            SELECT
                killer_player_key,
                killer_display_name,
                COALESCE(SUM(event_value), 0) AS total_teamkills
            FROM player_event_raw_ledger
            WHERE {where_sql}
                AND killer_player_key IS NOT NULL
            GROUP BY killer_player_key, killer_display_name
            ORDER BY total_teamkills DESC, killer_display_name ASC
            LIMIT ?
            """,
            [*params, limit],
        ).fetchall()
    return [dict(row) for row in rows]


def _query_pair_summary(
    *,
    event_type: str,
    server_slug: str | None,
    month: str | None,
    external_match_id: str | None,
    limit: int,
    db_path: Path | None,
) -> list[dict[str, object]]:
    resolved_path = initialize_player_event_storage(db_path=db_path)
    where_sql, params = _build_common_where(
        event_type=event_type,
        server_slug=server_slug,
        month=month,
        external_match_id=external_match_id,
    )
    with _connect(resolved_path) as connection:
        rows = connection.execute(
            f"""
            SELECT
                killer_player_key,
                killer_display_name,
                victim_player_key,
                victim_display_name,
                COALESCE(SUM(event_value), 0) AS total_kills
            FROM player_event_raw_ledger
            WHERE {where_sql}
                AND killer_player_key IS NOT NULL
                AND victim_player_key IS NOT NULL
            GROUP BY killer_player_key, killer_display_name, victim_player_key, victim_display_name
            ORDER BY total_kills DESC, killer_display_name ASC, victim_display_name ASC
            LIMIT ?
            """,
            [*params, limit],
        ).fetchall()
    return [dict(row) for row in rows]


def _build_common_where(
    *,
    event_type: str,
    server_slug: str | None,
    month: str | None,
    external_match_id: str | None,
) -> tuple[str, list[object]]:
    clauses = ["event_type = ?"]
    params: list[object] = [event_type]

    if server_slug and server_slug != "all-servers":
        clauses.append("server_slug = ?")
        params.append(server_slug.strip())
    if month:
        clauses.append("substr(COALESCE(CAST(occurred_at AS TEXT), ''), 1, 7) = ?")
        params.append(month.strip())
    if external_match_id:
        clauses.append("external_match_id = ?")
        params.append(external_match_id.strip())

    return " AND ".join(clauses), params


def _connect(db_path: Path) -> sqlite3.Connection:
    if get_database_url():
        from .postgres_display_storage import connect_postgres_compat

        return connect_postgres_compat()
    connection = sqlite3.connect(db_path or get_storage_path())
    connection.row_factory = sqlite3.Row
    return connection
