"""领域中心 + 领域追踪 API"""

import uuid
from datetime import datetime, timedelta

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

from app.compat import UTC
from app.core.cache import cache
from app.core.permissions import get_current_user
from app.db import get_db
from app.models.interaction import UserSubscription
from app.models.literature import GlobalLiterature, GlobalLiteratureTag, GlobalTag

router = APIRouter()

DOMAIN_CENTER_CACHE_PREFIX = "domain_center:"
DOMAIN_CENTER_CACHE_TTL = 300  # 5 minutes

def uid(u: dict) -> uuid.UUID: return uuid.UUID(u["sub"])


@router.get("/center", summary="领域中心")
async def domain_center(db: AsyncSession = Depends(get_db), user: dict = Depends(get_current_user)):
    """领域中心：用户关注的所有领域 + 最新动态（缓存 5 分钟）"""
    user_id = uid(user)
    cache_key = f"{DOMAIN_CENTER_CACHE_PREFIX}{user_id}"
    cached = await cache.get(cache_key)
    if cached:
        return cached
    result = await db.execute(
        select(UserSubscription, GlobalTag)
        .join(GlobalTag)
        .where(UserSubscription.user_id == uid(user), UserSubscription.is_active == True)
    )
    subscriptions = result.all()
    if not subscriptions:
        return {"domains": [], "by_category": {}, "total_subscriptions": 0}

    tag_ids = [tag.id for _, tag in subscriptions]
    week_ago = datetime.now(UTC) - timedelta(days=7)

    # Batch total counts per tag (1 query instead of N)
    total_counts_raw = await db.execute(
        select(GlobalLiteratureTag.tag_id, func.count(GlobalLiteratureTag.literature_id))
        .where(GlobalLiteratureTag.tag_id.in_(tag_ids))
        .group_by(GlobalLiteratureTag.tag_id)
    )
    total_counts = dict(total_counts_raw.all())

    # Batch recent 7-day counts per tag (1 query instead of N)
    recent_counts_raw = await db.execute(
        select(GlobalLiteratureTag.tag_id, func.count(GlobalLiteratureTag.literature_id))
        .join(GlobalLiterature, GlobalLiteratureTag.literature_id == GlobalLiterature.id)
        .where(GlobalLiteratureTag.tag_id.in_(tag_ids), GlobalLiterature.created_at >= week_ago)
        .group_by(GlobalLiteratureTag.tag_id)
    )
    recent_counts = dict(recent_counts_raw.all())

    domains = []
    for sub, tag in subscriptions:
        domains.append({
            "tag_id": str(tag.id), "name": tag.name_zh, "path": tag.path,
            "category": tag.tag_category, "match_mode": sub.match_mode,
            "recent_count": recent_counts.get(tag.id, 0), "total_count": total_counts.get(tag.id, 0),
        })

    cats = {}
    for d in domains:
        cats.setdefault(d["category"], []).append(d)

    data = {"domains": domains, "by_category": cats, "total_subscriptions": len(domains)}
    await cache.set(cache_key, data, ttl=DOMAIN_CENTER_CACHE_TTL)
    return data


@router.get("/trends/{tag_id}", summary="领域趋势")
async def domain_trends(
    tag_id: str,
    weeks: int = Query(8, ge=1, le=52),
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    """领域追踪：某标签下文献增长趋势（周级别）"""
    tag_uuid = uuid.UUID(tag_id)
    now = datetime.now(UTC)
    week_range = now - timedelta(days=weeks * 7)

    # Single query: group by date, aggregate to weeks in Python
    counts_raw = await db.execute(
        select(
            func.date(GlobalLiterature.created_at).label('created_date'),
            func.count(GlobalLiteratureTag.literature_id),
        )
        .join(GlobalLiterature)
        .where(GlobalLiteratureTag.tag_id == tag_uuid, GlobalLiterature.created_at >= week_range)
        .group_by(func.date(GlobalLiterature.created_at))
    )
    date_counts_raw = {row[0]: row[1] for row in counts_raw}
    from datetime import date as date_type
    date_counts = {}
    for k, v in date_counts_raw.items():
        if isinstance(k, str):
            k = date_type.fromisoformat(k)
        date_counts[k] = v

    data = []
    for w in range(weeks - 1, -1, -1):
        week_start = now - timedelta(days=now.weekday(), weeks=w)
        week_end = week_start + timedelta(days=6)
        count = sum(c for d, c in date_counts.items() if week_start.date() <= d <= week_end.date())
        data.append({
            "week_start": week_start.strftime("%Y-%m-%d"),
            "week_end": week_end.strftime("%Y-%m-%d"),
            "count": count,
        })

    tag = (await db.execute(select(GlobalTag).where(GlobalTag.id == tag_uuid))).scalar()
    return {
        "tag_id": tag_id,
        "tag_name": tag.name_zh if tag else "",
        "trends": data,
        "total": sum(d["count"] for d in data),
    }


@router.get("/trends/public/{tag_id}", summary="公开趋势")
async def public_domain_trends(
    tag_id: str,
    weeks: int = Query(8, ge=1, le=52),
    db: AsyncSession = Depends(get_db),
):
    """公开领域追踪（无需登录）"""
    tag_uuid = uuid.UUID(tag_id)
    now = datetime.now(UTC)
    week_range = now - timedelta(days=weeks * 7)

    counts_raw = await db.execute(
        select(
            func.date(GlobalLiterature.created_at).label('created_date'),
            func.count(GlobalLiteratureTag.literature_id),
        )
        .join(GlobalLiterature)
        .where(GlobalLiteratureTag.tag_id == tag_uuid, GlobalLiterature.created_at >= week_range)
        .group_by(func.date(GlobalLiterature.created_at))
    )
    from datetime import date as date_type
    date_counts = {}
    for row in counts_raw:
        d = row[0]
        if isinstance(d, str):
            d = date_type.fromisoformat(d)
        date_counts[d] = row[1]

    data = []
    for w in range(weeks - 1, -1, -1):
        week_start = now - timedelta(days=now.weekday(), weeks=w)
        week_end = week_start + timedelta(days=6)
        count = sum(c for d, c in date_counts.items() if week_start.date() <= d <= week_end.date())
        data.append({"week_start": week_start.strftime("%Y-%m-%d"), "week_end": week_end.strftime("%Y-%m-%d"), "count": count})

    tag = (await db.execute(select(GlobalTag).where(GlobalTag.id == tag_uuid))).scalar()
    return {"tag_id": tag_id, "tag_name": tag.name_zh if tag else "", "trends": data, "total": sum(d["count"] for d in data)}


@router.get("/hot-domains", summary="热门领域")
async def hot_domains(db: AsyncSession = Depends(get_db)):
    """热门领域：近7天文献最多的一级标签 Top 10"""
    week_ago = datetime.now(UTC) - timedelta(days=7)
    result = await db.execute(
        select(GlobalTag.id, GlobalTag.name_zh, GlobalTag.path, GlobalTag.tag_category,
               func.count(GlobalLiteratureTag.literature_id).label("cnt"))
        .join(GlobalLiteratureTag)
        .join(GlobalLiterature)
        .where(GlobalLiterature.created_at >= week_ago, GlobalTag.level == 2)
        .group_by(GlobalTag.id).order_by(text("cnt DESC")).limit(10)
    )
    items = [{"name": n, "path": p, "category": c, "weekly_count": cnt, "tag_id": str(tid)}
             for tid, n, p, c, cnt in result]
    return {"items": items, "total": len(items)}
