"""
Centralized Subscription Plan Configuration
Owner: Tenant Service
Single source of truth for all subscription tiers, quotas, features, and limits
"""

from typing import Optional, Dict, Any, List
from enum import Enum
from decimal import Decimal


class SubscriptionTier(str, Enum):
    """Subscription tier enumeration"""
    STARTER = "starter"
    PROFESSIONAL = "professional"
    ENTERPRISE = "enterprise"


class BillingCycle(str, Enum):
    """Billing cycle options"""
    MONTHLY = "monthly"
    YEARLY = "yearly"


# ============================================================================
# PRICING CONFIGURATION
# ============================================================================

class PlanPricing:
    """Pricing for each subscription tier"""

    MONTHLY_PRICES = {
        SubscriptionTier.STARTER: Decimal("49.00"),
        SubscriptionTier.PROFESSIONAL: Decimal("149.00"),
        SubscriptionTier.ENTERPRISE: Decimal("499.00"),  # Base price, custom quotes available
    }

    YEARLY_PRICES = {
        SubscriptionTier.STARTER: Decimal("490.00"),      # ~17% discount (2 months free)
        SubscriptionTier.PROFESSIONAL: Decimal("1490.00"),  # ~17% discount
        SubscriptionTier.ENTERPRISE: Decimal("4990.00"),   # Base price, custom quotes available
    }

    @staticmethod
    def get_price(tier: str, billing_cycle: str = "monthly") -> Decimal:
        """Get price for tier and billing cycle"""
        tier_enum = SubscriptionTier(tier.lower())
        if billing_cycle == "yearly":
            return PlanPricing.YEARLY_PRICES[tier_enum]
        return PlanPricing.MONTHLY_PRICES[tier_enum]


# ============================================================================
# QUOTA LIMITS CONFIGURATION
# ============================================================================

class QuotaLimits:
    """
    Resource quotas and limits for each subscription tier
    None = Unlimited
    """

    # ===== Team & Organization Limits =====
    MAX_USERS = {
        SubscriptionTier.STARTER: 5,
        SubscriptionTier.PROFESSIONAL: 20,
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    MAX_LOCATIONS = {
        SubscriptionTier.STARTER: 1,
        SubscriptionTier.PROFESSIONAL: 3,
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    # ===== Product & Inventory Limits =====
    MAX_PRODUCTS = {
        SubscriptionTier.STARTER: 50,
        SubscriptionTier.PROFESSIONAL: 500,
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    MAX_RECIPES = {
        SubscriptionTier.STARTER: 25,
        SubscriptionTier.PROFESSIONAL: 250,
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    MAX_SUPPLIERS = {
        SubscriptionTier.STARTER: 10,
        SubscriptionTier.PROFESSIONAL: 100,
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    # ===== ML & Analytics Quotas (Daily Limits) =====
    TRAINING_JOBS_PER_DAY = {
        SubscriptionTier.STARTER: 1,
        SubscriptionTier.PROFESSIONAL: 5,
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    FORECAST_GENERATION_PER_DAY = {
        SubscriptionTier.STARTER: 10,
        SubscriptionTier.PROFESSIONAL: 100,
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    # ===== Data Limits =====
    DATASET_SIZE_ROWS = {
        SubscriptionTier.STARTER: 1000,
        SubscriptionTier.PROFESSIONAL: 10000,
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    FORECAST_HORIZON_DAYS = {
        SubscriptionTier.STARTER: 7,
        SubscriptionTier.PROFESSIONAL: 90,
        SubscriptionTier.ENTERPRISE: 365,
    }

    HISTORICAL_DATA_ACCESS_DAYS = {
        SubscriptionTier.STARTER: 30,    # 1 month
        SubscriptionTier.PROFESSIONAL: 365,  # 1 year
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    # ===== Import/Export Limits =====
    BULK_IMPORT_ROWS = {
        SubscriptionTier.STARTER: 100,
        SubscriptionTier.PROFESSIONAL: 1000,
        SubscriptionTier.ENTERPRISE: 10000,
    }

    BULK_EXPORT_ROWS = {
        SubscriptionTier.STARTER: 1000,
        SubscriptionTier.PROFESSIONAL: 10000,
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    # ===== Integration Limits =====
    POS_SYNC_INTERVAL_MINUTES = {
        SubscriptionTier.STARTER: 60,      # Hourly
        SubscriptionTier.PROFESSIONAL: 15,  # Every 15 minutes
        SubscriptionTier.ENTERPRISE: 5,     # Every 5 minutes (near real-time)
    }

    API_CALLS_PER_HOUR = {
        SubscriptionTier.STARTER: 100,
        SubscriptionTier.PROFESSIONAL: 1000,
        SubscriptionTier.ENTERPRISE: 10000,
    }

    WEBHOOK_ENDPOINTS = {
        SubscriptionTier.STARTER: 2,
        SubscriptionTier.PROFESSIONAL: 10,
        SubscriptionTier.ENTERPRISE: None,  # Unlimited
    }

    # ===== Storage Limits =====
    FILE_STORAGE_GB = {
        SubscriptionTier.STARTER: 1,
        SubscriptionTier.PROFESSIONAL: 10,
        SubscriptionTier.ENTERPRISE: 100,
    }

    REPORT_RETENTION_DAYS = {
        SubscriptionTier.STARTER: 30,
        SubscriptionTier.PROFESSIONAL: 180,
        SubscriptionTier.ENTERPRISE: 365,
    }

    @staticmethod
    def get_limit(quota_type: str, tier: str) -> Optional[int]:
        """
        Get quota limit for a specific type and tier

        Args:
            quota_type: Quota type (e.g., 'MAX_USERS')
            tier: Subscription tier

        Returns:
            Optional[int]: Limit value or None for unlimited
        """
        tier_enum = SubscriptionTier(tier.lower())

        quota_map = {
            'MAX_USERS': QuotaLimits.MAX_USERS,
            'MAX_LOCATIONS': QuotaLimits.MAX_LOCATIONS,
            'MAX_PRODUCTS': QuotaLimits.MAX_PRODUCTS,
            'MAX_RECIPES': QuotaLimits.MAX_RECIPES,
            'MAX_SUPPLIERS': QuotaLimits.MAX_SUPPLIERS,
            'TRAINING_JOBS_PER_DAY': QuotaLimits.TRAINING_JOBS_PER_DAY,
            'FORECAST_GENERATION_PER_DAY': QuotaLimits.FORECAST_GENERATION_PER_DAY,
            'DATASET_SIZE_ROWS': QuotaLimits.DATASET_SIZE_ROWS,
            'FORECAST_HORIZON_DAYS': QuotaLimits.FORECAST_HORIZON_DAYS,
            'HISTORICAL_DATA_ACCESS_DAYS': QuotaLimits.HISTORICAL_DATA_ACCESS_DAYS,
            'BULK_IMPORT_ROWS': QuotaLimits.BULK_IMPORT_ROWS,
            'BULK_EXPORT_ROWS': QuotaLimits.BULK_EXPORT_ROWS,
            'POS_SYNC_INTERVAL_MINUTES': QuotaLimits.POS_SYNC_INTERVAL_MINUTES,
            'API_CALLS_PER_HOUR': QuotaLimits.API_CALLS_PER_HOUR,
            'WEBHOOK_ENDPOINTS': QuotaLimits.WEBHOOK_ENDPOINTS,
            'FILE_STORAGE_GB': QuotaLimits.FILE_STORAGE_GB,
            'REPORT_RETENTION_DAYS': QuotaLimits.REPORT_RETENTION_DAYS,
        }

        quotas = quota_map.get(quota_type, {})
        return quotas.get(tier_enum)


# ============================================================================
# FEATURE ACCESS CONFIGURATION
# ============================================================================

class PlanFeatures:
    """
    Feature availability by subscription tier
    Each tier includes all features from lower tiers
    """

    # ===== Core Features (All Tiers) =====
    CORE_FEATURES = [
        'inventory_management',
        'sales_tracking',
        'basic_recipes',
        'production_planning',
        'basic_reporting',
        'mobile_app_access',
        'email_support',
        'easy_step_by_step_onboarding',  # NEW: Value-add onboarding
    ]

    # ===== Starter Tier Features =====
    STARTER_FEATURES = CORE_FEATURES + [
        'basic_forecasting',
        'demand_prediction',
        'waste_tracking',
        'order_management',
        'customer_management',
        'supplier_management',
        'batch_tracking',
        'expiry_alerts',
    ]

    # ===== Professional Tier Features =====
    PROFESSIONAL_FEATURES = STARTER_FEATURES + [
        # Advanced Analytics
        'advanced_analytics',
        'custom_reports',
        'sales_analytics',
        'supplier_performance',
        'waste_analysis',
        'profitability_analysis',

        # External Data Integration
        'weather_data_integration',
        'traffic_data_integration',

        # Multi-location
        'multi_location_support',
        'location_comparison',
        'inventory_transfer',

        # Advanced Forecasting
        'batch_scaling',
        'recipe_feasibility_check',
        'seasonal_patterns',
        'longer_forecast_horizon',

        # Scenario Analysis (Professional+)
        'scenario_modeling',
        'what_if_analysis',
        'risk_assessment',

        # Integration
        'pos_integration',
        'accounting_export',
        'basic_api_access',

        # Support
        'priority_email_support',
        'phone_support',
    ]

    # ===== Enterprise Tier Features =====
    ENTERPRISE_FEATURES = PROFESSIONAL_FEATURES + [
        # Advanced ML & AI
        'advanced_ml_parameters',
        'model_artifacts_access',
        'custom_algorithms',

        # Advanced Integration
        'full_api_access',
        'unlimited_webhooks',
        'erp_integration',
        'custom_integrations',

        # Enterprise Features
        'multi_tenant_management',
        'white_label_option',
        'custom_branding',
        'sso_saml',
        'advanced_permissions',
        'audit_logs_export',
        'compliance_reports',

        # Advanced Analytics
        'benchmarking',
        'competitive_analysis',
        'market_insights',
        'predictive_maintenance',

        # Premium Support
        'dedicated_account_manager',
        'priority_support',
        '24_7_support',
        'custom_training',
        'onsite_support',  # Optional add-on
    ]

    @staticmethod
    def get_features(tier: str) -> List[str]:
        """Get all features for a tier"""
        tier_enum = SubscriptionTier(tier.lower())

        feature_map = {
            SubscriptionTier.STARTER: PlanFeatures.STARTER_FEATURES,
            SubscriptionTier.PROFESSIONAL: PlanFeatures.PROFESSIONAL_FEATURES,
            SubscriptionTier.ENTERPRISE: PlanFeatures.ENTERPRISE_FEATURES,
        }

        return feature_map.get(tier_enum, PlanFeatures.CORE_FEATURES)

    @staticmethod
    def has_feature(tier: str, feature: str) -> bool:
        """Check if a tier has access to a feature"""
        features = PlanFeatures.get_features(tier)
        return feature in features

    @staticmethod
    def requires_professional_tier(feature: str) -> bool:
        """Check if feature requires Professional+ tier"""
        return (
            feature not in PlanFeatures.STARTER_FEATURES and
            feature in PlanFeatures.PROFESSIONAL_FEATURES
        )

    @staticmethod
    def requires_enterprise_tier(feature: str) -> bool:
        """Check if feature requires Enterprise tier"""
        return (
            feature not in PlanFeatures.PROFESSIONAL_FEATURES and
            feature in PlanFeatures.ENTERPRISE_FEATURES
        )


# ============================================================================
# SUBSCRIPTION PLAN METADATA
# ============================================================================

class SubscriptionPlanMetadata:
    """Complete metadata for each subscription plan"""

    PLANS = {
        SubscriptionTier.STARTER: {
            "name": "Starter",
            "description": "Perfect for small bakeries getting started",
            "tagline": "Essential tools for small operations",
            "popular": False,
            "monthly_price": PlanPricing.MONTHLY_PRICES[SubscriptionTier.STARTER],
            "yearly_price": PlanPricing.YEARLY_PRICES[SubscriptionTier.STARTER],
            "trial_days": 14,
            "features": PlanFeatures.STARTER_FEATURES,
            "limits": {
                "users": QuotaLimits.MAX_USERS[SubscriptionTier.STARTER],
                "locations": QuotaLimits.MAX_LOCATIONS[SubscriptionTier.STARTER],
                "products": QuotaLimits.MAX_PRODUCTS[SubscriptionTier.STARTER],
                "forecasts_per_day": QuotaLimits.FORECAST_GENERATION_PER_DAY[SubscriptionTier.STARTER],
            },
            "support": "Email support (48h response)",
            "recommended_for": "Single location, up to 5 team members",
        },
        SubscriptionTier.PROFESSIONAL: {
            "name": "Professional",
            "description": "For growing bakeries with multiple locations",
            "tagline": "Advanced features & analytics",
            "popular": True,  # Most popular plan
            "monthly_price": PlanPricing.MONTHLY_PRICES[SubscriptionTier.PROFESSIONAL],
            "yearly_price": PlanPricing.YEARLY_PRICES[SubscriptionTier.PROFESSIONAL],
            "trial_days": 14,
            "features": PlanFeatures.PROFESSIONAL_FEATURES,
            "limits": {
                "users": QuotaLimits.MAX_USERS[SubscriptionTier.PROFESSIONAL],
                "locations": QuotaLimits.MAX_LOCATIONS[SubscriptionTier.PROFESSIONAL],
                "products": QuotaLimits.MAX_PRODUCTS[SubscriptionTier.PROFESSIONAL],
                "forecasts_per_day": QuotaLimits.FORECAST_GENERATION_PER_DAY[SubscriptionTier.PROFESSIONAL],
            },
            "support": "Priority email + phone support (24h response)",
            "recommended_for": "Multi-location operations, up to 20 team members",
        },
        SubscriptionTier.ENTERPRISE: {
            "name": "Enterprise",
            "description": "For large bakery chains and franchises",
            "tagline": "Unlimited scale & custom solutions",
            "popular": False,
            "monthly_price": PlanPricing.MONTHLY_PRICES[SubscriptionTier.ENTERPRISE],
            "yearly_price": PlanPricing.YEARLY_PRICES[SubscriptionTier.ENTERPRISE],
            "trial_days": 30,
            "features": PlanFeatures.ENTERPRISE_FEATURES,
            "limits": {
                "users": "Unlimited",
                "locations": "Unlimited",
                "products": "Unlimited",
                "forecasts_per_day": "Unlimited",
            },
            "support": "24/7 dedicated support + account manager",
            "recommended_for": "Enterprise operations, unlimited scale",
            "custom_pricing": True,
            "contact_sales": True,
        },
    }

    @staticmethod
    def get_plan_info(tier: str) -> Dict[str, Any]:
        """Get complete plan information"""
        tier_enum = SubscriptionTier(tier.lower())
        return SubscriptionPlanMetadata.PLANS.get(tier_enum, {})

    @staticmethod
    def get_all_plans() -> Dict[SubscriptionTier, Dict[str, Any]]:
        """Get information for all plans"""
        return SubscriptionPlanMetadata.PLANS


# ============================================================================
# HELPER FUNCTIONS
# ============================================================================

def get_training_job_quota(tier: str) -> Optional[int]:
    """Get training job daily quota for tier"""
    return QuotaLimits.get_limit('TRAINING_JOBS_PER_DAY', tier)


def get_forecast_quota(tier: str) -> Optional[int]:
    """Get forecast generation daily quota for tier"""
    return QuotaLimits.get_limit('FORECAST_GENERATION_PER_DAY', tier)


def get_dataset_size_limit(tier: str) -> Optional[int]:
    """Get dataset size limit for tier"""
    return QuotaLimits.get_limit('DATASET_SIZE_ROWS', tier)


def get_forecast_horizon_limit(tier: str) -> int:
    """Get forecast horizon limit for tier"""
    return QuotaLimits.get_limit('FORECAST_HORIZON_DAYS', tier) or 7


def get_historical_data_limit(tier: str) -> Optional[int]:
    """Get historical data access limit for tier"""
    return QuotaLimits.get_limit('HISTORICAL_DATA_ACCESS_DAYS', tier)


def can_access_feature(tier: str, feature: str) -> bool:
    """Check if tier can access a feature"""
    return PlanFeatures.has_feature(tier, feature)


def get_tier_comparison() -> Dict[str, Any]:
    """
    Get feature comparison across all tiers
    Useful for pricing pages
    """
    return {
        "tiers": ["starter", "professional", "enterprise"],
        "features": {
            "core": PlanFeatures.CORE_FEATURES,
            "starter_only": list(set(PlanFeatures.STARTER_FEATURES) - set(PlanFeatures.CORE_FEATURES)),
            "professional_only": list(set(PlanFeatures.PROFESSIONAL_FEATURES) - set(PlanFeatures.STARTER_FEATURES)),
            "enterprise_only": list(set(PlanFeatures.ENTERPRISE_FEATURES) - set(PlanFeatures.PROFESSIONAL_FEATURES)),
        },
        "pricing": {
            tier.value: {
                "monthly": float(PlanPricing.MONTHLY_PRICES[tier]),
                "yearly": float(PlanPricing.YEARLY_PRICES[tier]),
            }
            for tier in SubscriptionTier
        },
    }
