"""Admin read API над `user_events` — Feature 2 (login/IP audit) + Feature 3 (behavior
analytics dashboard data).

Read-only: только SELECT, никаких мутаций. Auth не нужен в этом файле — вся ветка
`/api/v1/admin/*` уже гейтится `rbac_guard` middleware в app/main.py
(`_ADMIN_API_RE`, role != admin → 403).

`user_events` (migration `184_user_events.sql`) может быть пустой (feature только
что задеплоена) — все запросы ниже написаны так, чтобы на пустой таблице отдавать
пустые списки/нулевые счётчики, а не падать.
"""

from __future__ import annotations

import logging
from typing import Annotated

from fastapi import APIRouter, Depends, Path, Query
from sqlalchemy import text
from sqlalchemy.orm import Session

from app.core.db import get_db
from app.schemas.audit import (
    AccountActivityEntry,
    AccountDeviceEntry,
    AccountDrilldown,
    AccountIpEntry,
    AccountSearchEntry,
    AccountSummary,
    AnalyticsByAccount,
    AnalyticsDailyPoint,
    AnalyticsDashboard,
    AnalyticsSummary,
    AnalyticsTopPath,
    AnalyticsTopSearch,
)

logger = logging.getLogger(__name__)

router = APIRouter()


@router.get("/audit/accounts", response_model=list[AccountSummary])
async def list_accounts(
    db: Annotated[Session, Depends(get_db)],
) -> list[AccountSummary]:
    """Список аккаунтов, по одной строке на username, с базовой сводкой активности."""
    rows = (
        db.execute(
            text(
                """
                SELECT username,
                       min(created_at) AS first_seen_at,
                       max(created_at) AS last_seen_at,
                       count(DISTINCT ip_address) AS distinct_ips,
                       count(DISTINCT user_agent) AS distinct_devices,
                       count(*) FILTER (WHERE event_type = 'login') AS login_count,
                       count(*) FILTER (WHERE event_type = 'api_request') AS request_count,
                       count(*) FILTER (WHERE event_type = 'estimate_request') AS search_count
                FROM user_events
                GROUP BY username
                ORDER BY last_seen_at DESC
                """
            )
        )
        .mappings()
        .all()
    )
    return [AccountSummary.model_validate(r) for r in rows]


@router.get("/audit/accounts/{username}", response_model=AccountDrilldown)
async def account_drilldown(
    db: Annotated[Session, Depends(get_db)],
    username: Annotated[str, Path(min_length=1, max_length=200)],
) -> AccountDrilldown:
    """Drilldown по одному username: IP-адреса, устройства, поиски, недавняя активность.

    Неизвестный username — НЕ 404, а пустой отчёт (все 4 списка == []): аудит не
    подтверждает/опровергает существование аккаунта, просто нет событий.
    """
    params = {"username": username}

    ips = (
        db.execute(
            text(
                """
                SELECT CAST(ip_address AS text) AS ip_address,
                       count(*) AS event_count,
                       min(created_at) AS first_seen,
                       max(created_at) AS last_seen
                FROM user_events
                WHERE username = :username AND ip_address IS NOT NULL
                GROUP BY ip_address
                ORDER BY last_seen DESC
                """
            ),
            params,
        )
        .mappings()
        .all()
    )

    devices = (
        db.execute(
            text(
                """
                SELECT user_agent,
                       count(*) AS event_count,
                       min(created_at) AS first_seen,
                       max(created_at) AS last_seen
                FROM user_events
                WHERE username = :username AND user_agent IS NOT NULL
                GROUP BY user_agent
                ORDER BY last_seen DESC
                """
            ),
            params,
        )
        .mappings()
        .all()
    )

    searches = (
        db.execute(
            text(
                """
                SELECT payload ->> 'address' AS address,
                       payload ->> 'area_m2' AS area_m2,
                       payload ->> 'rooms' AS rooms,
                       CAST(estimate_id AS text) AS estimate_id,
                       CAST(ip_address AS text) AS ip_address,
                       created_at
                FROM user_events
                WHERE username = :username AND event_type = 'estimate_request'
                ORDER BY created_at DESC
                LIMIT 200
                """
            ),
            params,
        )
        .mappings()
        .all()
    )

    recent_activity = (
        db.execute(
            text(
                """
                SELECT event_type,
                       path,
                       method,
                       CAST(ip_address AS text) AS ip_address,
                       created_at
                FROM user_events
                WHERE username = :username
                ORDER BY created_at DESC
                LIMIT 200
                """
            ),
            params,
        )
        .mappings()
        .all()
    )

    return AccountDrilldown(
        ips=[AccountIpEntry.model_validate(r) for r in ips],
        devices=[AccountDeviceEntry.model_validate(r) for r in devices],
        searches=[AccountSearchEntry.model_validate(r) for r in searches],
        recent_activity=[AccountActivityEntry.model_validate(r) for r in recent_activity],
    )


@router.get("/analytics", response_model=AnalyticsDashboard)
async def analytics_dashboard(
    db: Annotated[Session, Depends(get_db)],
    days: Annotated[int, Query(ge=1, le=365)] = 30,
) -> AnalyticsDashboard:
    """Feature 3 dashboard bundle: сводка, дневной time-series, топ-поиски/пути/аккаунты."""
    summary_row = (
        db.execute(
            text(
                """
            SELECT count(*) AS total_events,
                   count(DISTINCT username) AS distinct_users,
                   count(*) FILTER (
                       WHERE created_at >= now() - INTERVAL '24 hours'
                   ) AS events_last_24h,
                   count(DISTINCT username) FILTER (
                       WHERE created_at >= now() - INTERVAL '24 hours'
                   ) AS active_users_last_24h
            FROM user_events
            """
            )
        )
        .mappings()
        .one()
    )

    daily_rows = (
        db.execute(
            text(
                """
                SELECT date_trunc('day', created_at)::date AS day,
                       count(*) AS events,
                       count(DISTINCT username) AS users
                FROM user_events
                WHERE created_at >= now() - make_interval(days => CAST(:days AS int))
                GROUP BY date_trunc('day', created_at)::date
                ORDER BY day
                """
            ),
            {"days": days},
        )
        .mappings()
        .all()
    )

    top_searches_rows = (
        db.execute(
            text(
                """
                SELECT payload ->> 'address' AS address, count(*) AS n
                FROM user_events
                WHERE event_type = 'estimate_request'
                  AND payload ->> 'address' IS NOT NULL
                GROUP BY payload ->> 'address'
                ORDER BY n DESC
                LIMIT 20
                """
            )
        )
        .mappings()
        .all()
    )

    top_paths_rows = (
        db.execute(
            text(
                """
                SELECT path, count(*) AS n
                FROM user_events
                WHERE event_type = 'api_request'
                GROUP BY path
                ORDER BY n DESC
                LIMIT 20
                """
            )
        )
        .mappings()
        .all()
    )

    by_account_rows = (
        db.execute(
            text(
                """
                SELECT username,
                       count(*) AS events,
                       count(*) FILTER (WHERE event_type = 'estimate_request') AS searches,
                       max(created_at) AS last_seen
                FROM user_events
                GROUP BY username
                ORDER BY events DESC
                LIMIT 50
                """
            )
        )
        .mappings()
        .all()
    )

    return AnalyticsDashboard(
        summary=AnalyticsSummary.model_validate(summary_row),
        daily=[AnalyticsDailyPoint.model_validate(r) for r in daily_rows],
        top_searches=[AnalyticsTopSearch.model_validate(r) for r in top_searches_rows],
        top_paths=[AnalyticsTopPath.model_validate(r) for r in top_paths_rows],
        by_account=[AnalyticsByAccount.model_validate(r) for r in by_account_rows],
    )
