"""
라이선스 제한 강제 — FastAPI Dependency 함수 모음.

사용법:
  from middleware.license_guard import check_institution_limit, check_server_limit, require_feature

  @router.post("/")
  async def create_inst(
      payload: ...,
      db: AsyncSession = Depends(get_db),
      _: None = Depends(check_institution_limit),
  ):
      ...
"""
from __future__ import annotations

from fastapi import Depends, HTTPException
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession

from database import get_db
from routers.license import get_license_status


async def _get_status(db: AsyncSession) -> dict:
    return await get_license_status(db)


# ── 기관 수 제한 ───────────────────────────────────────────────────────────────

async def check_institution_limit(db: AsyncSession = Depends(get_db)) -> None:
    """기관 수가 라이선스 한도에 도달하면 HTTP 403."""
    from models import Institution
    status = await _get_status(db)

    max_inst = (status.get("limits") or {}).get("max_institutions", 1)
    if max_inst == -1:
        return  # 무제한

    count_r = await db.execute(select(func.count()).select_from(Institution))
    count = count_r.scalar_one()

    if count >= max_inst:
        edition = status.get("edition", "COMMUNITY")
        raise HTTPException(
            status_code=403,
            detail=(
                f"라이선스 한도 초과: {edition} 에디션은 최대 {max_inst}개 기관까지 등록 가능합니다. "
                f"현재 {count}개 등록됨. 라이선스를 업그레이드하세요."
            ),
        )


# ── 서버 수 제한 ───────────────────────────────────────────────────────────────

async def check_server_limit(db: AsyncSession = Depends(get_db)) -> None:
    """서버 수가 라이선스 한도에 도달하면 HTTP 403."""
    from models import Server
    status = await _get_status(db)

    max_srv = (status.get("limits") or {}).get("max_servers", 20)
    if max_srv == -1:
        return

    count_r = await db.execute(select(func.count()).select_from(Server))
    count = count_r.scalar_one()

    if count >= max_srv:
        edition = status.get("edition", "COMMUNITY")
        raise HTTPException(
            status_code=403,
            detail=(
                f"라이선스 한도 초과: {edition} 에디션은 최대 {max_srv}개 서버까지 등록 가능합니다. "
                f"현재 {count}개 등록됨. 라이선스를 업그레이드하세요."
            ),
        )


# ── 사용자 수 제한 ─────────────────────────────────────────────────────────────

async def check_user_limit(db: AsyncSession = Depends(get_db)) -> None:
    """사용자 수가 라이선스 한도에 도달하면 HTTP 403."""
    from models import User
    status = await _get_status(db)

    max_usr = (status.get("limits") or {}).get("max_users", 10)
    if max_usr == -1:
        return

    count_r = await db.execute(select(func.count()).select_from(User))
    count = count_r.scalar_one()

    if count >= max_usr:
        edition = status.get("edition", "COMMUNITY")
        raise HTTPException(
            status_code=403,
            detail=(
                f"라이선스 한도 초과: {edition} 에디션은 최대 {max_usr}명 사용자까지 등록 가능합니다. "
                f"현재 {count}명 등록됨. 라이선스를 업그레이드하세요."
            ),
        )


# ── 기능 접근 제한 ─────────────────────────────────────────────────────────────

def require_feature(feature_name: str):
    """특정 기능이 현재 라이선스 에디션에 포함되어 있는지 검사하는 Dependency."""
    async def _check(db: AsyncSession = Depends(get_db)) -> None:
        status = await _get_status(db)
        features: list = (status.get("limits") or {}).get("features", [])
        if feature_name not in features:
            edition = status.get("edition", "COMMUNITY")
            raise HTTPException(
                status_code=403,
                detail=(
                    f"'{feature_name}' 기능은 현재 라이선스({edition})에서 지원되지 않습니다. "
                    "라이선스를 업그레이드하세요."
                ),
            )
    return _check


# ── 현재 사용량 조회 ────────────────────────────────────────────────────────────

async def get_license_usage(db: AsyncSession = Depends(get_db)) -> dict:
    """현재 기관/사용자/서버 사용량 반환."""
    from models import Institution, Server, User

    inst_r  = await db.execute(select(func.count()).select_from(Institution))
    user_r  = await db.execute(select(func.count()).select_from(User))
    srv_r   = await db.execute(select(func.count()).select_from(Server))

    return {
        "institutions": inst_r.scalar_one(),
        "users":        user_r.scalar_one(),
        "servers":      srv_r.scalar_one(),
    }
