"""
License Limit Enforcement

Checks scans-per-day limits based on the user's license tier.
Used as a FastAPI dependency before scan endpoints execute.
"""

import logging
from datetime import datetime, timedelta, timezone

from fastapi import HTTPException
from sqlmodel import select, func

from app.models import ScanRecord
from app.config.pricing import get_tier_limit, get_tier

logger = logging.getLogger(__name__)


class LicenseLimitError(Exception):
    """Raised when a license limit is exceeded."""
    def __init__(self, message: str, limit_name: str, current: int, maximum: int):
        self.limit_name = limit_name
        self.current = current
        self.maximum = maximum
        super().__init__(message)


def get_user_tier(license_type: str) -> str:
    return "enterprise"


def check_scans_per_day(session, user_id: str, tier_name: str) -> None:
    """Check if the user has exceeded their daily scan limit.

    Args:
        session: Database session.
        user_id: The user's ID.
        tier_name: The pricing tier (trial, professional, enterprise).

    Raises:
        LicenseLimitError: If daily scan limit is exceeded.
    """
    limit = get_tier_limit(tier_name, "scans_per_day")

    # None means unlimited
    if limit is None:
        return

    # Count today's scans
    today_start = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
    statement = (
        select(func.count(ScanRecord.id))
        .where(
            ScanRecord.user_id == user_id,
            ScanRecord.timestamp >= today_start,
        )
    )
    today_count = session.exec(statement).one()

    if today_count >= limit:
        logger.warning(
            f"User {user_id} hit daily scan limit: {today_count}/{limit} (tier={tier_name})"
        )
        raise LicenseLimitError(
            f"Daily scan limit reached ({today_count}/{limit}). "
            f"Upgrade your plan for more scans.",
            limit_name="scans_per_day",
            current=today_count,
            maximum=limit,
        )


def enforce_scan_limits(
    session,
    user_id: str,
    license_type: str,
) -> None:
    """Run all limit checks before a scan executes.

    This is the main entry point called from scan endpoints.

    Args:
        session: Database session.
        user_id: The user's ID.
        license_type: License type from LicenseValidator (trial/professional/enterprise/development).

    Raises:
        HTTPException 429: If any limit is exceeded.
    """
    tier_name = get_user_tier(license_type)

    try:
        check_scans_per_day(session, user_id, tier_name)
    except LicenseLimitError as e:
        tier = get_tier(tier_name)
        raise HTTPException(
            status_code=429,
            detail={
                "message": str(e),
                "limit": e.limit_name,
                "current": e.current,
                "maximum": e.maximum,
                "tier": tier_name,
                "tier_display": tier.get("display_name", tier_name),
                "upgrade_available": tier_name != "enterprise",
            },
        )
