"""纳入篇数额度模型 — 按月统计 + 方案配额校验"""

from fastapi import Depends, HTTPException
from sqlalchemy import func, select

from app.core.plans import PLANS
from app.core.tenant_context import tenant_ctx
from app.db import get_db

# 方案配额常量
QUOTA_PLANS = {
    "free": {"monthly_included": 100, "active_projects": 3},
    "pro": {"monthly_included": 500, "active_projects": 999},
    "team": {"monthly_included": 5000, "active_projects": 999},
    "enterprise": {"monthly_included": -1, "active_projects": -1},
}


async def check_included_quota(db=None) -> dict:
    """检查当前租户的纳入篇数额度。

    返回 {used, limit, remaining, exceeded}。
    exceeded=True 且 limit>=0 时表示超限。
    """
    if db is None:
        from app.db import async_session
        async with async_session() as db:
            return await _check_quota_impl(db)
    return await _check_quota_impl(db)


async def _check_quota_impl(db):
    raw_tid = tenant_ctx.get()
    if not raw_tid:
        return {"used": 0, "limit": 100, "remaining": 100, "exceeded": False}

    import uuid

    from app.models.review import ReviewLiterature, SystematicReview
    from app.models.user import Tenant

    tid = uuid.UUID(raw_tid) if isinstance(raw_tid, str) else raw_tid

    # 获取方案类型
    result = await db.execute(select(Tenant.plan_type).where(Tenant.id == tid))
    plan_type = result.scalar() or "free"
    plan_limits = QUOTA_PLANS.get(plan_type, QUOTA_PLANS["free"])
    limit = plan_limits["monthly_included"]
    if limit < 0:
        return {"used": 0, "limit": -1, "remaining": -1, "exceeded": False}

    # 统计当月纳入数
    from app.compat import UTC
    from datetime import datetime

    now = datetime.now(UTC)
    first_of_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
    count_result = await db.execute(
        select(func.count(ReviewLiterature.id))
        .select_from(ReviewLiterature)
        .join(SystematicReview, ReviewLiterature.review_id == SystematicReview.id)
        .where(
            SystematicReview.tenant_id == tid,
            ReviewLiterature.stage == "included",
            ReviewLiterature.updated_at >= first_of_month,
        )
    )
    used = count_result.scalar() or 0
    remaining = max(0, limit - used)
    exceeded = used >= limit

    return {"used": used, "limit": limit, "remaining": remaining, "exceeded": exceeded}


async def check_active_project_quota(db=None) -> dict:
    """检查当前租户的活跃项目数配额。"""
    if db is None:
        from app.db import async_session
        async with async_session() as db:
            return await _check_project_quota_impl(db)
    return await _check_project_quota_impl(db)


async def _check_project_quota_impl(db):
    raw_tid = tenant_ctx.get()
    if not raw_tid:
        return {"active": 0, "limit": 3, "exceeded": False}

    import uuid

    from app.models.review import SystematicReview
    from app.models.user import Tenant

    tid = uuid.UUID(raw_tid) if isinstance(raw_tid, str) else raw_tid

    result = await db.execute(select(Tenant.plan_type).where(Tenant.id == tid))
    plan_type = result.scalar() or "free"
    limit = QUOTA_PLANS.get(plan_type, QUOTA_PLANS["free"])["active_projects"]
    if limit < 0:
        return {"active": 0, "limit": -1, "exceeded": False}

    count_result = await db.execute(
        select(func.count(SystematicReview.id)).where(
            SystematicReview.tenant_id == tid,
            SystematicReview.status.in_(["draft", "active"]),
        )
    )
    active = count_result.scalar() or 0
    return {"active": active, "limit": limit, "exceeded": active >= limit}


class RequireIncludedQuota:
    """FastAPI 依赖：校验纳入配额，超限返回 403"""

    async def __call__(self, db=Depends(get_db)):
        quota = await check_included_quota(db)
        if quota["exceeded"] and quota["limit"] >= 0:
            raise HTTPException(
                status_code=403,
                detail={
                    "code": "QUOTA_EXCEEDED",
                    "message": f"月纳入配额已用完 ({quota['used']}/{quota['limit']})。"
                               "请升级方案或关闭已完成项目释放额度。",
                    "quota": quota,
                },
            )
        return quota


class RequireActiveProjectQuota:
    """FastAPI 依赖：校验活跃项目数配额"""

    async def __call__(self, db=Depends(get_db)):
        pq = await check_active_project_quota(db)
        if pq["exceeded"] and pq["limit"] >= 0:
            raise HTTPException(
                status_code=403,
                detail={
                    "code": "PROJECT_QUOTA_EXCEEDED",
                    "message": f"活跃项目数已达上限 ({pq['active']}/{pq['limit']})。"
                               "请归档已完成项目后再创建新项目。",
                    "quota": pq,
                },
            )
        return pq
