# app/modules/billing/definition.py
"""
Billing module definition.

Defines the billing module including its features, menu items,
route configurations, and scheduled tasks.
"""

import logging
from typing import Any

from app.modules.base import (
    MenuItemDefinition,
    MenuSectionDefinition,
    ModuleDefinition,
    PermissionDefinition,
    ScheduledTask,
)
from app.modules.enums import FrontendType

logger = logging.getLogger(__name__)


# =============================================================================
# Context Providers
# =============================================================================


def _get_platform_context(request: Any, db: Any, platform: Any) -> dict[str, Any]:
    """
    Provide billing context for platform/marketing pages.

    Returns pricing tier data for the marketing pricing page.
    """
    from app.core.config import settings
    from app.modules.billing.models import SubscriptionTier, TierCode
    from app.modules.billing.services.feature_aggregator import feature_aggregator

    language = getattr(request.state, "language", "fr") or "fr"

    tiers_db = (
        db.query(SubscriptionTier)
        .filter(
            SubscriptionTier.is_active == True,  # noqa: E712
            SubscriptionTier.is_public == True,  # noqa: E712
        )
        .order_by(SubscriptionTier.display_order)
        .all()
    )

    tiers = []
    for tier in tiers_db:
        feature_codes = sorted(tier.get_feature_codes())

        # Build features list from declarations for template rendering
        features = []
        for code in feature_codes:
            decl = feature_aggregator.get_declaration(code)
            if decl:
                features.append({
                    "code": code,
                    "name_key": decl.name_key,
                    "limit": tier.get_limit_for_feature(code),
                    "is_quantitative": decl.feature_type.value == "quantitative",
                })

        tiers.append({
            "code": tier.code,
            "name": tier.get_translated_name(language),
            "price_monthly": tier.price_monthly_cents / 100,
            "price_annual": (tier.price_annual_cents / 100)
            if tier.price_annual_cents
            else None,
            "feature_codes": feature_codes,
            "features": features,
            "products_limit": tier.get_limit_for_feature("products_limit"),
            "orders_per_month": tier.get_limit_for_feature("orders_per_month"),
            "team_members": tier.get_limit_for_feature("team_members"),
            "is_popular": tier.code == TierCode.PROFESSIONAL.value,
            "is_enterprise": tier.code == TierCode.ENTERPRISE.value,
        })

    return {
        "tiers": tiers,
        "trial_days": settings.stripe_trial_days,
        "stripe_publishable_key": settings.stripe_publishable_key,
    }


# =============================================================================
# Router Lazy Imports
# =============================================================================


def _get_admin_router():
    """Lazy import of admin router to avoid circular imports."""
    from app.modules.billing.routes.api.admin import router

    return router


def _get_store_router():
    """Lazy import of store router to avoid circular imports."""
    from app.modules.billing.routes.api.store import router

    return router


def _get_metrics_provider():
    """Lazy import of metrics provider to avoid circular imports."""
    from app.modules.billing.services.billing_metrics import billing_metrics_provider

    return billing_metrics_provider


def _get_feature_provider():
    """Lazy import of feature provider to avoid circular imports."""
    from app.modules.billing.services.billing_features import billing_feature_provider

    return billing_feature_provider


# Billing module definition
billing_module = ModuleDefinition(
    code="billing",
    name="Billing & Subscriptions",
    description=(
        "Core subscription management, tier limits, store billing, and invoice history. "
        "Provides tier-based feature gating used throughout the platform. "
        "Uses the payments module for actual payment processing."
    ),
    version="1.0.0",
    requires=["payments"],  # Depends on payments module (also core) for payment processing
    features=[
        "subscription_management",  # Manage subscription tiers
        "billing_history",  # View invoices and payment history
        "invoice_generation",  # Generate and download invoices
        "subscription_analytics",  # Subscription stats and metrics
        "trial_management",  # Manage store trial periods
        "limit_overrides",  # Override tier limits per store
    ],
    # Module-driven permissions
    permissions=[
        PermissionDefinition(
            id="billing.view_tiers",
            label_key="billing.permissions.view_tiers",
            description_key="billing.permissions.view_tiers_desc",
            category="billing",
        ),
        PermissionDefinition(
            id="billing.manage_tiers",
            label_key="billing.permissions.manage_tiers",
            description_key="billing.permissions.manage_tiers_desc",
            category="billing",
        ),
        PermissionDefinition(
            id="billing.view_subscriptions",
            label_key="billing.permissions.view_subscriptions",
            description_key="billing.permissions.view_subscriptions_desc",
            category="billing",
        ),
        PermissionDefinition(
            id="billing.manage_subscriptions",
            label_key="billing.permissions.manage_subscriptions",
            description_key="billing.permissions.manage_subscriptions_desc",
            category="billing",
        ),
        PermissionDefinition(
            id="billing.view_invoices",
            label_key="billing.permissions.view_invoices",
            description_key="billing.permissions.view_invoices_desc",
            category="billing",
        ),
    ],
    menu_items={
        FrontendType.ADMIN: [
            "subscription-tiers",  # Manage tier definitions
            "subscriptions",  # View/manage store subscriptions
            "billing-history",  # View all invoices
        ],
        FrontendType.STORE: [
            "billing",  # Store billing dashboard
            "invoices",  # Store invoice history
        ],
        FrontendType.MERCHANT: [
            "subscriptions",  # Merchant subscriptions
            "invoices",  # Merchant billing history
        ],
    },
    # New module-driven menu definitions
    menus={
        FrontendType.ADMIN: [
            MenuSectionDefinition(
                id="billing",
                label_key="billing.menu.billing_subscriptions",
                icon="credit-card",
                order=50,
                items=[
                    MenuItemDefinition(
                        id="subscription-tiers",
                        label_key="billing.menu.subscription_tiers",
                        icon="tag",
                        route="/admin/subscription-tiers",
                        order=10,
                    ),
                    MenuItemDefinition(
                        id="subscriptions",
                        label_key="billing.menu.merchant_subscriptions",
                        icon="credit-card",
                        route="/admin/subscriptions",
                        order=20,
                    ),
                    MenuItemDefinition(
                        id="billing-history",
                        label_key="billing.menu.billing_history",
                        icon="document-text",
                        route="/admin/billing-history",
                        order=30,
                    ),
                ],
            ),
        ],
        FrontendType.MERCHANT: [
            MenuSectionDefinition(
                id="billing",
                label_key="billing.menu.billing_subscriptions",
                icon="credit-card",
                order=50,
                items=[
                    MenuItemDefinition(
                        id="subscriptions",
                        label_key="billing.menu.subscriptions",
                        icon="clipboard-list",
                        route="/merchants/billing/subscriptions",
                        order=10,
                        is_mandatory=True,
                    ),
                    MenuItemDefinition(
                        id="invoices",
                        label_key="billing.menu.billing_history",
                        icon="currency-euro",
                        route="/merchants/billing/invoices",
                        order=20,
                    ),
                ],
            ),
        ],
        FrontendType.STORE: [
            MenuSectionDefinition(
                id="sales",
                label_key="billing.menu.sales_orders",
                icon="currency-euro",
                order=20,
                items=[
                    MenuItemDefinition(
                        id="invoices",
                        label_key="billing.menu.invoices",
                        icon="currency-euro",
                        route="/store/{store_code}/invoices",
                        order=30,
                        requires_permission="billing.view_invoices",
                    ),
                ],
            ),
            MenuSectionDefinition(
                id="account",
                label_key="billing.menu.account_settings",
                icon="credit-card",
                order=900,
                items=[
                    MenuItemDefinition(
                        id="billing",
                        label_key="billing.menu.billing",
                        icon="credit-card",
                        route="/store/{store_code}/billing",
                        order=30,
                        requires_permission="billing.view_subscriptions",
                    ),
                ],
            ),
        ],
    },
    is_core=True,  # Core module - tier limits and subscription management are fundamental
    # Context providers for dynamic page context
    context_providers={
        FrontendType.PLATFORM: _get_platform_context,
    },
    # =========================================================================
    # Self-Contained Module Configuration
    # =========================================================================
    is_self_contained=True,
    services_path="app.modules.billing.services",
    models_path="app.modules.billing.models",
    schemas_path="app.modules.billing.schemas",
    exceptions_path="app.modules.billing.exceptions",
    tasks_path="app.modules.billing.tasks",
    migrations_path="migrations",
    # =========================================================================
    # Scheduled Tasks
    # =========================================================================
    scheduled_tasks=[
        ScheduledTask(
            name="billing.reset_period_counters",
            task="app.modules.billing.tasks.subscription.reset_period_counters",
            schedule="5 0 * * *",  # Daily at 00:05
            options={"queue": "scheduled"},
        ),
        ScheduledTask(
            name="billing.check_trial_expirations",
            task="app.modules.billing.tasks.subscription.check_trial_expirations",
            schedule="0 1 * * *",  # Daily at 01:00
            options={"queue": "scheduled"},
        ),
        ScheduledTask(
            name="billing.sync_stripe_status",
            task="app.modules.billing.tasks.subscription.sync_stripe_status",
            schedule="30 * * * *",  # Hourly at :30
            options={"queue": "scheduled"},
        ),
        ScheduledTask(
            name="billing.cleanup_stale_subscriptions",
            task="app.modules.billing.tasks.subscription.cleanup_stale_subscriptions",
            schedule="0 3 * * 0",  # Weekly on Sunday at 03:00
            options={"queue": "scheduled"},
        ),
    ],
    # Feature provider for feature flags
    feature_provider=_get_feature_provider,
    # Metrics provider for subscription metrics
    metrics_provider=_get_metrics_provider,
)


def get_billing_module_with_routers() -> ModuleDefinition:
    """
    Get billing module with routers attached.

    This function attaches the routers lazily to avoid circular imports
    during module initialization.
    """
    billing_module.admin_router = _get_admin_router()
    billing_module.store_router = _get_store_router()
    return billing_module


__all__ = ["billing_module", "get_billing_module_with_routers"]
