from typing import Annotated

from fastapi import APIRouter, Depends, Query
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession

from app.auth.deps import CurrentUser, current_user
from app.db import get_session
from app.schemas.intel import CompetitorMetrics, CompetitorRanking

router = APIRouter(prefix="/competitors", tags=["competitors"])


@router.get("", response_model=CompetitorRanking)
async def competitor_ranking(
    session: Annotated[AsyncSession, Depends(get_session)],
    _user: Annotated[CurrentUser, Depends(current_user)],
    monitoring_type: str = Query(
        "competitor", pattern="^(competitor|internal|analysis|client|all)$"
    ),
    include_archived: bool = Query(False),
    limit: int = Query(50, ge=1, le=500),
) -> CompetitorRanking:
    """Ranking of companies by recent judicial activity. Defaults to
    monitoring_type='competitor' but accepts 'internal', 'analysis', or 'all'.

    Archived companies (active=FALSE — closed/insolvency imports from Racius)
    are hidden by default since ranking measures ongoing activity; set
    `include_archived=true` to see them too."""
    clauses: list[str] = []
    if monitoring_type != "all":
        clauses.append("c.monitoring_type = :mt")
    if not include_archived:
        clauses.append("c.active = TRUE")
    where = " AND ".join(clauses) if clauses else "1=1"
    params: dict[str, object] = {"lim": limit}
    if monitoring_type != "all":
        params["mt"] = monitoring_type
    rows = (
        await session.execute(
            text(
                f"""
                SELECT
                  c.id::text, c.legal_name, c.nif, c.monitoring_type, c.risk_score,
                  c.data_coverage_end,
                  COUNT(p.id) AS total,
                  COUNT(p.id) FILTER (
                    WHERE p.date_filed >= (now() - interval '30 days')::date
                  ) AS d30,
                  COUNT(p.id) FILTER (
                    WHERE p.date_filed >= (now() - interval '180 days')::date
                  ) AS d180,
                  COUNT(p.id) FILTER (
                    WHERE p.date_filed >= (now() - interval '60 days')::date
                      AND p.date_filed <  (now() - interval '30 days')::date
                  ) AS d30_prev
                FROM companies c
                LEFT JOIN processes p ON p.company_id = c.id
                WHERE {where}
                GROUP BY c.id, c.legal_name, c.nif, c.monitoring_type, c.risk_score,
                         c.data_coverage_end
                ORDER BY d30 DESC, total DESC
                LIMIT :lim
                """
            ),
            params,
        )
    ).all()
    items: list[CompetitorMetrics] = []
    for r in rows:
        d30, d30_prev = int(r[7] or 0), int(r[9] or 0)
        trend = None
        if d30_prev > 0:
            trend = (d30 - d30_prev) / d30_prev * 100.0
        elif d30 > 0:
            trend = 100.0
        items.append(
            CompetitorMetrics(
                company_id=r[0], legal_name=r[1], nif=r[2],
                monitoring_type=r[3], risk_score=r[4],
                data_coverage_end=r[5],
                total_processes=int(r[6] or 0),
                last_30d=d30, last_6m=int(r[8] or 0),
                trend_pct=round(trend, 1) if trend is not None else None,
            )
        )
    return CompetitorRanking(items=items)
