# app/modules/loyalty/services/loyalty_features.py
"""
Loyalty feature provider for the billing feature system.

Declares loyalty-related billable features (stamps, points, cards, wallets, etc.)
for feature gating.
"""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING

from app.modules.contracts.features import (
    FeatureDeclaration,
    FeatureScope,
    FeatureType,
    FeatureUsage,
)

if TYPE_CHECKING:
    from sqlalchemy.orm import Session

logger = logging.getLogger(__name__)


class LoyaltyFeatureProvider:
    """Feature provider for the loyalty module.

    Declares:
    - loyalty_stamps: stamp-based loyalty programs
    - loyalty_points: points-based loyalty programs
    - loyalty_hybrid: combined stamps and points
    - loyalty_cards: customer card management
    - loyalty_enrollment: customer enrollment
    - loyalty_staff_pins: staff PIN management
    - loyalty_anti_fraud: cooldown and daily limits
    - loyalty_google_wallet: Google Wallet passes
    - loyalty_apple_wallet: Apple Wallet passes
    - loyalty_stats: dashboard statistics
    - loyalty_reports: transaction reports
    """

    @property
    def feature_category(self) -> str:
        return "loyalty"

    def get_feature_declarations(self) -> list[FeatureDeclaration]:
        return [
            FeatureDeclaration(
                code="loyalty_stamps",
                name_key="loyalty.features.loyalty_stamps.name",
                description_key="loyalty.features.loyalty_stamps.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="stamp",
                display_order=10,
            ),
            FeatureDeclaration(
                code="loyalty_points",
                name_key="loyalty.features.loyalty_points.name",
                description_key="loyalty.features.loyalty_points.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="coins",
                display_order=20,
            ),
            FeatureDeclaration(
                code="loyalty_hybrid",
                name_key="loyalty.features.loyalty_hybrid.name",
                description_key="loyalty.features.loyalty_hybrid.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="layers",
                display_order=30,
            ),
            FeatureDeclaration(
                code="loyalty_cards",
                name_key="loyalty.features.loyalty_cards.name",
                description_key="loyalty.features.loyalty_cards.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="credit-card",
                display_order=40,
            ),
            FeatureDeclaration(
                code="loyalty_enrollment",
                name_key="loyalty.features.loyalty_enrollment.name",
                description_key="loyalty.features.loyalty_enrollment.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="user-plus",
                display_order=50,
            ),
            FeatureDeclaration(
                code="loyalty_staff_pins",
                name_key="loyalty.features.loyalty_staff_pins.name",
                description_key="loyalty.features.loyalty_staff_pins.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="shield",
                display_order=60,
            ),
            FeatureDeclaration(
                code="loyalty_anti_fraud",
                name_key="loyalty.features.loyalty_anti_fraud.name",
                description_key="loyalty.features.loyalty_anti_fraud.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="lock",
                display_order=70,
            ),
            FeatureDeclaration(
                code="loyalty_google_wallet",
                name_key="loyalty.features.loyalty_google_wallet.name",
                description_key="loyalty.features.loyalty_google_wallet.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="smartphone",
                display_order=80,
            ),
            FeatureDeclaration(
                code="loyalty_apple_wallet",
                name_key="loyalty.features.loyalty_apple_wallet.name",
                description_key="loyalty.features.loyalty_apple_wallet.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="smartphone",
                display_order=85,
            ),
            FeatureDeclaration(
                code="loyalty_stats",
                name_key="loyalty.features.loyalty_stats.name",
                description_key="loyalty.features.loyalty_stats.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="bar-chart",
                display_order=90,
            ),
            FeatureDeclaration(
                code="loyalty_reports",
                name_key="loyalty.features.loyalty_reports.name",
                description_key="loyalty.features.loyalty_reports.description",
                category="loyalty",
                feature_type=FeatureType.BINARY,
                scope=FeatureScope.MERCHANT,
                ui_icon="file-text",
                display_order=100,
            ),
        ]

    def get_store_usage(
        self,
        db: Session,
        store_id: int,
    ) -> list[FeatureUsage]:
        if db is None:
            return []

        from sqlalchemy import func

        from app.modules.loyalty.models import LoyaltyCard, StaffPin

        active_cards = (
            db.query(func.count(LoyaltyCard.id))
            .filter(
                LoyaltyCard.enrolled_at_store_id == store_id,
                LoyaltyCard.is_active == True,
            )
            .scalar()
            or 0
        )

        active_pins = (
            db.query(func.count(StaffPin.id))
            .filter(
                StaffPin.store_id == store_id,
                StaffPin.is_active == True,
            )
            .scalar()
            or 0
        )

        return [
            FeatureUsage(feature_code="loyalty_cards", current_usage=active_cards),
            FeatureUsage(feature_code="loyalty_staff_pins", current_usage=active_pins),
        ]

    def get_merchant_usage(
        self,
        db: Session,
        merchant_id: int,
        platform_id: int,
    ) -> list[FeatureUsage]:
        if db is None:
            return []

        from sqlalchemy import func

        from app.modules.loyalty.models import (
            AppleDeviceRegistration,
            LoyaltyCard,
            StaffPin,
        )

        active_cards = (
            db.query(func.count(LoyaltyCard.id))
            .filter(
                LoyaltyCard.merchant_id == merchant_id,
                LoyaltyCard.is_active == True,
            )
            .scalar()
            or 0
        )

        active_pins = (
            db.query(func.count(StaffPin.id))
            .filter(
                StaffPin.merchant_id == merchant_id,
                StaffPin.is_active == True,
            )
            .scalar()
            or 0
        )

        apple_registrations = (
            db.query(func.count(AppleDeviceRegistration.id))
            .join(LoyaltyCard)
            .filter(LoyaltyCard.merchant_id == merchant_id)
            .scalar()
            or 0
        )

        google_wallets = (
            db.query(func.count(LoyaltyCard.id))
            .filter(
                LoyaltyCard.merchant_id == merchant_id,
                LoyaltyCard.google_object_id.isnot(None),
            )
            .scalar()
            or 0
        )

        return [
            FeatureUsage(feature_code="loyalty_cards", current_usage=active_cards),
            FeatureUsage(feature_code="loyalty_staff_pins", current_usage=active_pins),
            FeatureUsage(feature_code="loyalty_apple_wallet", current_usage=apple_registrations),
            FeatureUsage(feature_code="loyalty_google_wallet", current_usage=google_wallets),
        ]


# Singleton instance for module registration
loyalty_feature_provider = LoyaltyFeatureProvider()

__all__ = [
    "LoyaltyFeatureProvider",
    "loyalty_feature_provider",
]
