from __future__ import annotations

import time
from typing import List

from fastapi import APIRouter
from pydantic import BaseModel

from app.db import get_pool

START_TIME = time.time()

router = APIRouter(tags=["stats"])


# ---------- Pydantic models ----------

class StatsOut(BaseModel):
    uptime_seconds: float
    total_hits: int
    active_ips: int
    avg_latency_ms: float


class GeoDistributionItem(BaseModel):
    country: str
    count: int
    percentage: float


class GeoPoint(BaseModel):
    latitude: float
    longitude: float
    country: str
    city: str
    hit_count: int


# ---------- Endpoints ----------

@router.get("/stats", response_model=StatsOut)
async def get_stats() -> StatsOut:
    pool = get_pool()
    async with pool.acquire() as conn:
        total_hits: int = await conn.fetchval("SELECT COUNT(*) FROM access_logs") or 0
        active_ips: int = (
            await conn.fetchval(
                "SELECT COUNT(DISTINCT ip) FROM access_logs "
                "WHERE created_at > NOW() - INTERVAL '5 minutes'"
            )
            or 0
        )
        avg_latency = await conn.fetchval("SELECT AVG(latency_ms) FROM access_logs")

    return StatsOut(
        uptime_seconds=time.time() - START_TIME,
        total_hits=total_hits,
        active_ips=active_ips,
        avg_latency_ms=round(float(avg_latency), 2) if avg_latency is not None else 0.0,
    )


@router.get("/geo/distribution", response_model=List[GeoDistributionItem])
async def get_geo_distribution() -> List[GeoDistributionItem]:
    pool = get_pool()
    async with pool.acquire() as conn:
        rows = await conn.fetch(
            "SELECT country, COUNT(*) AS cnt FROM access_logs "
            "GROUP BY country ORDER BY cnt DESC"
        )
        total = sum(r["cnt"] for r in rows)

    return [
        GeoDistributionItem(
            country=row["country"],
            count=row["cnt"],
            percentage=round(row["cnt"] / total * 100, 2) if total else 0.0,
        )
        for row in rows
    ]


@router.get("/prices/top-ips", response_model=List[dict])
async def get_top_price_ips() -> List[dict]:
    pool = get_pool()
    async with pool.acquire() as conn:
        rows = await conn.fetch(
            """
            SELECT ip, COUNT(*) AS hit_count
            FROM access_logs
            WHERE path LIKE '/api/public/prices%'
            GROUP BY ip
            ORDER BY hit_count DESC
            LIMIT 20
            """
        )
    total = sum(r["hit_count"] for r in rows) or 1
    return [
        {
            "ip": r["ip"],
            "hit_count": r["hit_count"],
            "percentage": round(r["hit_count"] / total * 100, 2),
        }
        for r in rows
    ]


@router.get("/geo/points", response_model=List[GeoPoint])
async def get_geo_points() -> List[GeoPoint]:
    pool = get_pool()
    async with pool.acquire() as conn:
        rows = await conn.fetch(
            "SELECT latitude, longitude, country, city, COUNT(*) AS hit_count "
            "FROM access_logs "
            "WHERE latitude IS NOT NULL AND longitude IS NOT NULL "
            "GROUP BY latitude, longitude, country, city "
            "ORDER BY hit_count DESC "
            "LIMIT 1000"
        )

    return [
        GeoPoint(
            latitude=row["latitude"],
            longitude=row["longitude"],
            country=row["country"],
            city=row["city"],
            hit_count=row["hit_count"],
        )
        for row in rows
    ]
