//! Pricing Tiers
//!
//! Define different pricing tiers: Free, Standard, Premium, Enterprise

use crate::SynorDecimal;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};

/// Pricing tier definition
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PricingTier {
    /// Tier name/identifier
    pub name: String,
    /// Display name
    pub display_name: String,
    /// Monthly base fee (0 for free tier)
    pub monthly_fee: SynorDecimal,
    /// Discount percentage on usage
    pub discount_percentage: SynorDecimal,
    /// Priority support included
    pub priority_support: bool,
    /// SLA guarantee percentage
    pub sla_percentage: SynorDecimal,
    /// Custom domain limit (0 = unlimited)
    pub custom_domain_limit: u32,
    /// API rate limit (requests/minute)
    pub api_rate_limit: u32,
    /// Features included
    pub features: Vec<String>,
    /// Minimum commitment (months, 0 = no commitment)
    pub min_commitment_months: u32,
}

impl PricingTier {
    /// Free tier
    pub fn free() -> Self {
        Self {
            name: "free".to_string(),
            display_name: "Free".to_string(),
            monthly_fee: Decimal::ZERO,
            discount_percentage: Decimal::ZERO,
            priority_support: false,
            sla_percentage: Decimal::new(95, 0), // 95% SLA
            custom_domain_limit: 1,
            api_rate_limit: 100,
            features: vec![
                "0.5 GB Storage".to_string(),
                "1 GB Hosting Bandwidth".to_string(),
                "1M Database Queries".to_string(),
                "100 CPU Core-Hours".to_string(),
                "Community Support".to_string(),
            ],
            min_commitment_months: 0,
        }
    }

    /// Standard tier
    pub fn standard() -> Self {
        Self {
            name: "standard".to_string(),
            display_name: "Standard".to_string(),
            monthly_fee: Decimal::new(10, 0), // 10 SYNOR/month
            discount_percentage: Decimal::new(10, 0), // 10% discount
            priority_support: false,
            sla_percentage: Decimal::new(99, 0), // 99% SLA
            custom_domain_limit: 5,
            api_rate_limit: 1000,
            features: vec![
                "Everything in Free".to_string(),
                "10% Usage Discount".to_string(),
                "5 Custom Domains".to_string(),
                "Email Support".to_string(),
                "99% SLA Guarantee".to_string(),
            ],
            min_commitment_months: 0,
        }
    }

    /// Premium tier
    pub fn premium() -> Self {
        Self {
            name: "premium".to_string(),
            display_name: "Premium".to_string(),
            monthly_fee: Decimal::new(50, 0), // 50 SYNOR/month
            discount_percentage: Decimal::new(20, 0), // 20% discount
            priority_support: true,
            sla_percentage: Decimal::new(999, 1), // 99.9% SLA
            custom_domain_limit: 20,
            api_rate_limit: 5000,
            features: vec![
                "Everything in Standard".to_string(),
                "20% Usage Discount".to_string(),
                "20 Custom Domains".to_string(),
                "Priority Support".to_string(),
                "99.9% SLA Guarantee".to_string(),
                "Advanced Analytics".to_string(),
            ],
            min_commitment_months: 0,
        }
    }

    /// Enterprise tier
    pub fn enterprise() -> Self {
        Self {
            name: "enterprise".to_string(),
            display_name: "Enterprise".to_string(),
            monthly_fee: Decimal::new(500, 0), // 500 SYNOR/month (or custom)
            discount_percentage: Decimal::new(30, 0), // 30% discount
            priority_support: true,
            sla_percentage: Decimal::new(9999, 2), // 99.99% SLA
            custom_domain_limit: 0, // Unlimited
            api_rate_limit: 0, // Unlimited
            features: vec![
                "Everything in Premium".to_string(),
                "30%+ Usage Discount".to_string(),
                "Unlimited Custom Domains".to_string(),
                "Dedicated Support".to_string(),
                "99.99% SLA Guarantee".to_string(),
                "Custom Integrations".to_string(),
                "Volume Pricing".to_string(),
                "Invoice Billing".to_string(),
            ],
            min_commitment_months: 12,
        }
    }

    /// Create custom tier
    pub fn custom(
        name: impl Into<String>,
        display_name: impl Into<String>,
        monthly_fee: SynorDecimal,
        discount_percentage: SynorDecimal,
    ) -> Self {
        Self {
            name: name.into(),
            display_name: display_name.into(),
            monthly_fee,
            discount_percentage,
            priority_support: discount_percentage >= Decimal::new(20, 0),
            sla_percentage: Decimal::new(99, 0),
            custom_domain_limit: 10,
            api_rate_limit: 2000,
            features: vec!["Custom tier".to_string()],
            min_commitment_months: 0,
        }
    }

    /// Check if this tier has a feature
    pub fn has_feature(&self, feature: &str) -> bool {
        self.features.iter().any(|f| f.to_lowercase().contains(&feature.to_lowercase()))
    }

    /// Calculate effective monthly cost including usage discount
    pub fn effective_cost(&self, base_usage: SynorDecimal) -> SynorDecimal {
        let discount_rate = self.discount_percentage / Decimal::ONE_HUNDRED;
        let discounted_usage = base_usage * (Decimal::ONE - discount_rate);
        self.monthly_fee + discounted_usage
    }

    /// Check if an upgrade to another tier makes sense
    pub fn should_upgrade_to(&self, other: &PricingTier, monthly_usage: SynorDecimal) -> bool {
        let current_cost = self.effective_cost(monthly_usage);
        let other_cost = other.effective_cost(monthly_usage);

        // Upgrade if other tier is cheaper or offers significant benefits
        other_cost < current_cost || (other.sla_percentage > self.sla_percentage && other_cost <= current_cost * Decimal::new(12, 1))
    }
}

/// Tier comparison for upgrade recommendations
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TierComparison {
    pub current_tier: String,
    pub recommended_tier: String,
    pub current_monthly_cost: SynorDecimal,
    pub recommended_monthly_cost: SynorDecimal,
    pub monthly_savings: SynorDecimal,
    pub additional_benefits: Vec<String>,
}

/// Compare tiers based on usage
pub fn compare_tiers(
    current: &PricingTier,
    all_tiers: &[PricingTier],
    monthly_usage: SynorDecimal,
) -> Option<TierComparison> {
    let current_cost = current.effective_cost(monthly_usage);

    // Find most cost-effective tier
    let mut best_tier: Option<&PricingTier> = None;
    let mut best_cost = current_cost;

    for tier in all_tiers {
        if tier.name == current.name {
            continue;
        }

        let tier_cost = tier.effective_cost(monthly_usage);
        if tier_cost < best_cost {
            best_cost = tier_cost;
            best_tier = Some(tier);
        }
    }

    best_tier.map(|recommended| {
        let recommended_cost = recommended.effective_cost(monthly_usage);
        let savings = current_cost - recommended_cost;

        // Find additional benefits
        let additional_benefits: Vec<_> = recommended
            .features
            .iter()
            .filter(|f| !current.has_feature(f))
            .cloned()
            .collect();

        TierComparison {
            current_tier: current.name.clone(),
            recommended_tier: recommended.name.clone(),
            current_monthly_cost: current_cost,
            recommended_monthly_cost: recommended_cost,
            monthly_savings: savings,
            additional_benefits,
        }
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use rust_decimal_macros::dec;

    #[test]
    fn test_free_tier() {
        let tier = PricingTier::free();
        assert_eq!(tier.monthly_fee, Decimal::ZERO);
        assert_eq!(tier.discount_percentage, Decimal::ZERO);
    }

    #[test]
    fn test_standard_tier() {
        let tier = PricingTier::standard();
        assert_eq!(tier.monthly_fee, dec!(10));
        assert_eq!(tier.discount_percentage, dec!(10));
        assert!(!tier.priority_support);
    }

    #[test]
    fn test_premium_tier() {
        let tier = PricingTier::premium();
        assert_eq!(tier.monthly_fee, dec!(50));
        assert_eq!(tier.discount_percentage, dec!(20));
        assert!(tier.priority_support);
    }

    #[test]
    fn test_effective_cost() {
        let free = PricingTier::free();
        let premium = PricingTier::premium();

        // With 200 SYNOR usage
        let free_cost = free.effective_cost(dec!(200));
        let premium_cost = premium.effective_cost(dec!(200));

        // Free: 0 + 200 = 200
        // Premium: 50 + (200 * 0.80) = 50 + 160 = 210
        assert_eq!(free_cost, dec!(200));
        assert_eq!(premium_cost, dec!(210));

        // With 500 SYNOR usage, premium becomes cheaper
        let free_cost_high = free.effective_cost(dec!(500));
        let premium_cost_high = premium.effective_cost(dec!(500));

        // Free: 0 + 500 = 500
        // Premium: 50 + (500 * 0.80) = 50 + 400 = 450
        assert_eq!(free_cost_high, dec!(500));
        assert_eq!(premium_cost_high, dec!(450));

        assert!(premium_cost_high < free_cost_high);
    }

    #[test]
    fn test_tier_comparison() {
        let tiers = vec![
            PricingTier::free(),
            PricingTier::standard(),
            PricingTier::premium(),
        ];

        let free = &tiers[0];

        // High usage - should recommend upgrade
        let comparison = compare_tiers(free, &tiers, dec!(500));
        assert!(comparison.is_some());

        let comp = comparison.unwrap();
        assert_eq!(comp.current_tier, "free");
        assert!(comp.monthly_savings > Decimal::ZERO);
    }
}
