# app/modules/billing/routes/api/vendor_features.py
"""
Vendor features API endpoints.

Provides feature availability information for the frontend to:
- Show/hide UI elements based on tier
- Display upgrade prompts for unavailable features
- Load feature metadata for dynamic rendering

Endpoints:
- GET /features/available - List of feature codes (for quick checks)
- GET /features - Full feature list with availability and metadata
- GET /features/{code} - Single feature details with upgrade info
- GET /features/categories - List feature categories

All routes require module access control for the 'billing' module.
"""

import logging

from fastapi import APIRouter, Depends, Query
from pydantic import BaseModel
from sqlalchemy.orm import Session

from app.api.deps import get_current_vendor_api, require_module_access
from app.core.database import get_db
from app.modules.billing.exceptions import FeatureNotFoundError
from app.modules.billing.services.feature_service import feature_service
from app.modules.enums import FrontendType
from models.schema.auth import UserContext

vendor_features_router = APIRouter(
    prefix="/features",
    dependencies=[Depends(require_module_access("billing", FrontendType.VENDOR))],
)
logger = logging.getLogger(__name__)


# ============================================================================
# Response Schemas
# ============================================================================


class FeatureCodeListResponse(BaseModel):
    """Simple list of available feature codes for quick checks."""

    features: list[str]
    tier_code: str
    tier_name: str


class FeatureResponse(BaseModel):
    """Full feature information."""

    code: str
    name: str
    description: str | None = None
    category: str
    ui_location: str | None = None
    ui_icon: str | None = None
    ui_route: str | None = None
    ui_badge_text: str | None = None
    is_available: bool
    minimum_tier_code: str | None = None
    minimum_tier_name: str | None = None


class FeatureListResponse(BaseModel):
    """List of features with metadata."""

    features: list[FeatureResponse]
    available_count: int
    total_count: int
    tier_code: str
    tier_name: str


class FeatureDetailResponse(BaseModel):
    """Single feature detail with upgrade info."""

    code: str
    name: str
    description: str | None = None
    category: str
    ui_location: str | None = None
    ui_icon: str | None = None
    ui_route: str | None = None
    is_available: bool
    # Upgrade info (only if not available)
    upgrade_tier_code: str | None = None
    upgrade_tier_name: str | None = None
    upgrade_tier_price_monthly_cents: int | None = None


class CategoryListResponse(BaseModel):
    """List of feature categories."""

    categories: list[str]


class FeatureGroupedResponse(BaseModel):
    """Features grouped by category."""

    categories: dict[str, list[FeatureResponse]]
    available_count: int
    total_count: int


class FeatureCheckResponse(BaseModel):
    """Quick feature availability check response."""

    has_feature: bool
    feature_code: str


# ============================================================================
# Endpoints
# ============================================================================


@vendor_features_router.get("/available", response_model=FeatureCodeListResponse)
def get_available_features(
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Get list of feature codes available to vendor.

    This is a lightweight endpoint for quick feature checks.
    Use this to populate a frontend feature store on app init.

    Returns:
        List of feature codes the vendor has access to
    """
    vendor_id = current_user.token_vendor_id

    # Get subscription for tier info
    from app.modules.billing.services.subscription_service import subscription_service

    subscription = subscription_service.get_or_create_subscription(db, vendor_id)
    tier = subscription.tier_obj

    # Get available features
    feature_codes = feature_service.get_available_feature_codes(db, vendor_id)

    return FeatureCodeListResponse(
        features=feature_codes,
        tier_code=subscription.tier,
        tier_name=tier.name if tier else subscription.tier.title(),
    )


@vendor_features_router.get("", response_model=FeatureListResponse)
def get_features(
    category: str | None = Query(None, description="Filter by category"),
    include_unavailable: bool = Query(True, description="Include features not available to vendor"),
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Get all features with availability status and metadata.

    This is a comprehensive endpoint for building feature-gated UIs.
    Each feature includes:
    - Availability status
    - UI metadata (icon, route, location)
    - Minimum tier required

    Args:
        category: Filter to specific category (orders, inventory, etc.)
        include_unavailable: Whether to include locked features

    Returns:
        List of features with metadata and availability
    """
    vendor_id = current_user.token_vendor_id

    # Get subscription for tier info
    from app.modules.billing.services.subscription_service import subscription_service

    subscription = subscription_service.get_or_create_subscription(db, vendor_id)
    tier = subscription.tier_obj

    # Get features
    features = feature_service.get_vendor_features(
        db,
        vendor_id,
        category=category,
        include_unavailable=include_unavailable,
    )

    available_count = sum(1 for f in features if f.is_available)

    return FeatureListResponse(
        features=[
            FeatureResponse(
                code=f.code,
                name=f.name,
                description=f.description,
                category=f.category,
                ui_location=f.ui_location,
                ui_icon=f.ui_icon,
                ui_route=f.ui_route,
                ui_badge_text=f.ui_badge_text,
                is_available=f.is_available,
                minimum_tier_code=f.minimum_tier_code,
                minimum_tier_name=f.minimum_tier_name,
            )
            for f in features
        ],
        available_count=available_count,
        total_count=len(features),
        tier_code=subscription.tier,
        tier_name=tier.name if tier else subscription.tier.title(),
    )


@vendor_features_router.get("/categories", response_model=CategoryListResponse)
def get_feature_categories(
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Get list of feature categories.

    Returns:
        List of category names
    """
    categories = feature_service.get_categories(db)
    return CategoryListResponse(categories=categories)


@vendor_features_router.get("/grouped", response_model=FeatureGroupedResponse)
def get_features_grouped(
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Get features grouped by category.

    Useful for rendering feature comparison tables or settings pages.
    """
    vendor_id = current_user.token_vendor_id

    grouped = feature_service.get_features_grouped_by_category(db, vendor_id)

    # Convert to response format
    categories_response = {}
    total = 0
    available = 0

    for category, features in grouped.items():
        categories_response[category] = [
            FeatureResponse(
                code=f.code,
                name=f.name,
                description=f.description,
                category=f.category,
                ui_location=f.ui_location,
                ui_icon=f.ui_icon,
                ui_route=f.ui_route,
                ui_badge_text=f.ui_badge_text,
                is_available=f.is_available,
                minimum_tier_code=f.minimum_tier_code,
                minimum_tier_name=f.minimum_tier_name,
            )
            for f in features
        ]
        total += len(features)
        available += sum(1 for f in features if f.is_available)

    return FeatureGroupedResponse(
        categories=categories_response,
        available_count=available,
        total_count=total,
    )


@vendor_features_router.get("/{feature_code}", response_model=FeatureDetailResponse)
def get_feature_detail(
    feature_code: str,
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Get detailed information about a specific feature.

    Includes upgrade information if the feature is not available.
    Use this for upgrade prompts and feature explanation modals.

    Args:
        feature_code: The feature code

    Returns:
        Feature details with upgrade info if locked
    """
    vendor_id = current_user.token_vendor_id

    # Get feature
    feature = feature_service.get_feature_by_code(db, feature_code)
    if not feature:
        raise FeatureNotFoundError(feature_code)

    # Check availability
    is_available = feature_service.has_feature(db, vendor_id, feature_code)

    # Get upgrade info if not available
    upgrade_tier_code = None
    upgrade_tier_name = None
    upgrade_tier_price = None

    if not is_available:
        upgrade_info = feature_service.get_feature_upgrade_info(db, feature_code)
        if upgrade_info:
            upgrade_tier_code = upgrade_info.required_tier_code
            upgrade_tier_name = upgrade_info.required_tier_name
            upgrade_tier_price = upgrade_info.required_tier_price_monthly_cents

    return FeatureDetailResponse(
        code=feature.code,
        name=feature.name,
        description=feature.description,
        category=feature.category,
        ui_location=feature.ui_location,
        ui_icon=feature.ui_icon,
        ui_route=feature.ui_route,
        is_available=is_available,
        upgrade_tier_code=upgrade_tier_code,
        upgrade_tier_name=upgrade_tier_name,
        upgrade_tier_price_monthly_cents=upgrade_tier_price,
    )


@vendor_features_router.get("/check/{feature_code}", response_model=FeatureCheckResponse)
def check_feature(
    feature_code: str,
    current_user: UserContext = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Quick check if vendor has access to a feature.

    Returns simple boolean response for inline checks.

    Args:
        feature_code: The feature code

    Returns:
        has_feature and feature_code
    """
    vendor_id = current_user.token_vendor_id
    has_feature = feature_service.has_feature(db, vendor_id, feature_code)

    return FeatureCheckResponse(has_feature=has_feature, feature_code=feature_code)
