// Provider Analytics Integration Tests
// Phase 7: Comprehensive tests for provider analytics functionality

#[cfg(test)]
mod provider_analytics_tests {
    use vapora_knowledge_graph::models::{
        ProviderAnalytics, ProviderCostForecast, ProviderEfficiency, ProviderTaskTypeMetrics,
    };

    #[test]
    fn test_provider_analytics_creation() {
        let analytics = ProviderAnalytics {
            provider: "claude".to_string(),
            total_cost_cents: 1000,
            total_tasks: 10,
            successful_tasks: 9,
            failed_tasks: 1,
            success_rate: 0.9,
            avg_cost_per_task_cents: 100.0,
            total_input_tokens: 50000,
            total_output_tokens: 25000,
            cost_per_1m_tokens: 13.3,
        };

        assert_eq!(analytics.provider, "claude");
        assert_eq!(analytics.total_tasks, 10);
        assert_eq!(analytics.successful_tasks, 9);
        assert_eq!(analytics.failed_tasks, 1);
        assert_eq!(analytics.success_rate, 0.9);
        assert_eq!(analytics.avg_cost_per_task_cents, 100.0);
        assert_eq!(analytics.total_input_tokens, 50000);
        assert_eq!(analytics.total_output_tokens, 25000);
        assert!((analytics.cost_per_1m_tokens - 13.3).abs() < 0.01);
    }

    #[test]
    fn test_provider_efficiency_calculation() {
        let efficiency = ProviderEfficiency {
            provider: "claude".to_string(),
            quality_score: 0.9,
            cost_score: 0.8,
            efficiency_ratio: 0.72,
            rank: 1,
        };

        assert_eq!(efficiency.provider, "claude");
        assert_eq!(efficiency.quality_score, 0.9);
        assert_eq!(efficiency.cost_score, 0.8);
        assert_eq!(efficiency.efficiency_ratio, 0.72);
        assert_eq!(efficiency.rank, 1);
        assert!(efficiency.efficiency_ratio > 0.7);
    }

    #[test]
    fn test_provider_efficiency_ranking_order() {
        let efficiencies = vec![
            ProviderEfficiency {
                provider: "claude".to_string(),
                quality_score: 0.95,
                cost_score: 0.9,
                efficiency_ratio: 0.855,
                rank: 1,
            },
            ProviderEfficiency {
                provider: "gpt-4".to_string(),
                quality_score: 0.85,
                cost_score: 0.8,
                efficiency_ratio: 0.68,
                rank: 2,
            },
            ProviderEfficiency {
                provider: "gemini".to_string(),
                quality_score: 0.75,
                cost_score: 0.95,
                efficiency_ratio: 0.7125,
                rank: 3,
            },
        ];

        // Verify ordering: highest efficiency_ratio should have lowest rank
        assert!(efficiencies[0].efficiency_ratio > efficiencies[1].efficiency_ratio);
        assert!(efficiencies[0].rank < efficiencies[1].rank);
        assert!(efficiencies[1].rank < efficiencies[2].rank);
    }

    #[test]
    fn test_provider_task_type_metrics() {
        let metrics = ProviderTaskTypeMetrics {
            provider: "claude".to_string(),
            task_type: "code_review".to_string(),
            total_cost_cents: 500,
            task_count: 5,
            success_rate: 1.0,
            avg_duration_ms: 2500.0,
        };

        assert_eq!(metrics.provider, "claude");
        assert_eq!(metrics.task_type, "code_review");
        assert_eq!(metrics.total_cost_cents, 500);
        assert_eq!(metrics.task_count, 5);
        assert_eq!(metrics.success_rate, 1.0);
        assert_eq!(metrics.avg_duration_ms, 2500.0);
        assert_eq!(metrics.total_cost_cents / metrics.task_count as u32, 100);
    }

    #[test]
    fn test_provider_cost_forecast() {
        let forecast = ProviderCostForecast {
            provider: "claude".to_string(),
            current_daily_cost_cents: 500,
            projected_weekly_cost_cents: 3500,
            projected_monthly_cost_cents: 15000,
            trend: "stable".to_string(),
            confidence: 0.9,
        };

        assert_eq!(forecast.provider, "claude");
        assert_eq!(forecast.current_daily_cost_cents, 500);
        assert_eq!(forecast.projected_weekly_cost_cents, 3500);
        assert_eq!(forecast.projected_monthly_cost_cents, 15000);
        assert_eq!(forecast.trend, "stable");
        assert_eq!(forecast.confidence, 0.9);

        // Verify reasonable projections (weekly should be ~7x daily)
        let expected_weekly = forecast.current_daily_cost_cents as u32 * 7;
        assert!(
            (forecast.projected_weekly_cost_cents as i32 - expected_weekly as i32).abs() <= 100
        );
    }

    #[test]
    fn test_success_rate_calculation_with_zero_tasks() {
        let analytics = ProviderAnalytics {
            provider: "ollama".to_string(),
            total_cost_cents: 0,
            total_tasks: 0,
            successful_tasks: 0,
            failed_tasks: 0,
            success_rate: 0.0,
            avg_cost_per_task_cents: 0.0,
            total_input_tokens: 0,
            total_output_tokens: 0,
            cost_per_1m_tokens: 0.0,
        };

        // When there are no tasks, success rate should be 0
        assert_eq!(analytics.success_rate, 0.0);
        assert_eq!(analytics.avg_cost_per_task_cents, 0.0);
    }

    #[test]
    fn test_cost_per_token_calculation() {
        let total_tokens = 1_000_000u64;
        let cost_cents = 10u32;

        let cost_per_1m_tokens = (cost_cents as f64 * 1_000_000.0) / (total_tokens as f64);

        assert_eq!(cost_per_1m_tokens, 10.0);
    }

    #[test]
    fn test_cost_per_token_with_different_volumes() {
        // 1M tokens costs 10 cents
        let analytics1 = ProviderAnalytics {
            provider: "claude".to_string(),
            total_cost_cents: 10,
            total_tasks: 1,
            successful_tasks: 1,
            failed_tasks: 0,
            success_rate: 1.0,
            avg_cost_per_task_cents: 10.0,
            total_input_tokens: 500_000,
            total_output_tokens: 500_000,
            cost_per_1m_tokens: 10.0,
        };

        // 10M tokens costs 50 cents (same rate)
        let analytics2 = ProviderAnalytics {
            provider: "gpt-4".to_string(),
            total_cost_cents: 50,
            total_tasks: 1,
            successful_tasks: 1,
            failed_tasks: 0,
            success_rate: 1.0,
            avg_cost_per_task_cents: 50.0,
            total_input_tokens: 5_000_000,
            total_output_tokens: 5_000_000,
            cost_per_1m_tokens: 5.0, // 50 cents / 10M tokens = 5 cents per 1M
        };

        // Verify cost scaling
        assert!(analytics2.cost_per_1m_tokens < analytics1.cost_per_1m_tokens);
        assert_eq!(analytics2.total_cost_cents, 50);
    }

    #[test]
    fn test_efficiency_ratio_quality_vs_cost() {
        // High quality, high cost provider
        let high_quality_high_cost = ProviderEfficiency {
            provider: "claude".to_string(),
            quality_score: 0.95,
            cost_score: 0.5,         // Lower score because expensive
            efficiency_ratio: 0.475, // 0.95 * 0.5
            rank: 1,
        };

        // Lower quality, low cost provider
        let low_quality_low_cost = ProviderEfficiency {
            provider: "ollama".to_string(),
            quality_score: 0.7,
            cost_score: 0.95,        // Higher score because cheap
            efficiency_ratio: 0.665, // 0.7 * 0.95
            rank: 1,
        };

        // Even though Claude is higher quality, Ollama's cost efficiency might win
        // depending on the use case
        assert!(high_quality_high_cost.quality_score > low_quality_low_cost.quality_score);
        assert!(high_quality_high_cost.cost_score < low_quality_low_cost.cost_score);
    }

    #[test]
    fn test_forecast_trend_detection() {
        // Stable trend: costs are relatively consistent
        let stable_forecast = ProviderCostForecast {
            provider: "claude".to_string(),
            current_daily_cost_cents: 500,
            projected_weekly_cost_cents: 3500,
            projected_monthly_cost_cents: 15000,
            trend: "stable".to_string(),
            confidence: 0.9,
        };

        // Increasing trend: costs are growing
        let increasing_forecast = ProviderCostForecast {
            provider: "gpt-4".to_string(),
            current_daily_cost_cents: 600,
            projected_weekly_cost_cents: 5200,
            projected_monthly_cost_cents: 20000,
            trend: "increasing".to_string(),
            confidence: 0.85,
        };

        // Decreasing trend: costs are declining
        let decreasing_forecast = ProviderCostForecast {
            provider: "gemini".to_string(),
            current_daily_cost_cents: 300,
            projected_weekly_cost_cents: 1750,
            projected_monthly_cost_cents: 7500,
            trend: "decreasing".to_string(),
            confidence: 0.7,
        };

        assert_eq!(stable_forecast.trend, "stable");
        assert_eq!(increasing_forecast.trend, "increasing");
        assert_eq!(decreasing_forecast.trend, "decreasing");

        // Higher confidence when more data available
        assert!(stable_forecast.confidence > increasing_forecast.confidence);
        assert!(increasing_forecast.confidence > decreasing_forecast.confidence);
    }

    #[test]
    fn test_forecast_confidence_based_on_data_volume() {
        // High confidence with 7+ days of data
        let high_confidence = ProviderCostForecast {
            provider: "claude".to_string(),
            current_daily_cost_cents: 500,
            projected_weekly_cost_cents: 3500,
            projected_monthly_cost_cents: 15000,
            trend: "stable".to_string(),
            confidence: 0.9,
        };

        // Medium confidence with 3-6 days of data
        let medium_confidence = ProviderCostForecast {
            provider: "gpt-4".to_string(),
            current_daily_cost_cents: 400,
            projected_weekly_cost_cents: 2800,
            projected_monthly_cost_cents: 12000,
            trend: "stable".to_string(),
            confidence: 0.7,
        };

        // Low confidence with < 3 days of data
        let low_confidence = ProviderCostForecast {
            provider: "gemini".to_string(),
            current_daily_cost_cents: 300,
            projected_weekly_cost_cents: 2100,
            projected_monthly_cost_cents: 9000,
            trend: "insufficient_data".to_string(),
            confidence: 0.3,
        };

        assert!(high_confidence.confidence > medium_confidence.confidence);
        assert!(medium_confidence.confidence > low_confidence.confidence);
    }

    #[test]
    fn test_provider_comparison_cost_quality_tradeoff() {
        // Claude: High quality, high cost
        let claude = ProviderEfficiency {
            provider: "claude".to_string(),
            quality_score: 0.95,
            cost_score: 0.6,
            efficiency_ratio: 0.57,
            rank: 2,
        };

        // GPT-4: High quality, medium cost
        let gpt4 = ProviderEfficiency {
            provider: "gpt-4".to_string(),
            quality_score: 0.90,
            cost_score: 0.7,
            efficiency_ratio: 0.63,
            rank: 1,
        };

        // Gemini: Good quality, low cost
        let gemini = ProviderEfficiency {
            provider: "gemini".to_string(),
            quality_score: 0.80,
            cost_score: 0.85,
            efficiency_ratio: 0.68,
            rank: 1,
        };

        // Ollama: Lower quality, free
        let ollama = ProviderEfficiency {
            provider: "ollama".to_string(),
            quality_score: 0.6,
            cost_score: 1.0,
            efficiency_ratio: 0.6,
            rank: 4,
        };

        // Verify quality ordering
        assert!(claude.quality_score > gpt4.quality_score);
        assert!(gpt4.quality_score > gemini.quality_score);
        assert!(gemini.quality_score > ollama.quality_score);

        // Verify cost score ordering (higher = cheaper)
        assert!(ollama.cost_score > gemini.cost_score);
        assert!(gemini.cost_score > gpt4.cost_score);
        assert!(gpt4.cost_score > claude.cost_score);
    }

    #[test]
    fn test_multiple_task_types_per_provider() {
        let code_review = ProviderTaskTypeMetrics {
            provider: "claude".to_string(),
            task_type: "code_review".to_string(),
            total_cost_cents: 500,
            task_count: 5,
            success_rate: 1.0,
            avg_duration_ms: 2500.0,
        };

        let documentation = ProviderTaskTypeMetrics {
            provider: "claude".to_string(),
            task_type: "documentation".to_string(),
            total_cost_cents: 300,
            task_count: 10,
            success_rate: 0.9,
            avg_duration_ms: 1500.0,
        };

        let testing = ProviderTaskTypeMetrics {
            provider: "claude".to_string(),
            task_type: "testing".to_string(),
            total_cost_cents: 200,
            task_count: 8,
            success_rate: 0.875,
            avg_duration_ms: 3000.0,
        };

        // Verify same provider, different task types
        assert_eq!(code_review.provider, documentation.provider);
        assert_eq!(documentation.provider, testing.provider);
        assert_ne!(code_review.task_type, documentation.task_type);
        assert_ne!(documentation.task_type, testing.task_type);

        // Verify varying success rates across task types
        assert!(code_review.success_rate > documentation.success_rate);
        assert!(documentation.success_rate > testing.success_rate);
    }

    #[test]
    fn test_provider_cost_tracking_over_time() {
        // Day 1: $5
        let day1 = ProviderAnalytics {
            provider: "claude".to_string(),
            total_cost_cents: 500,
            total_tasks: 10,
            successful_tasks: 10,
            failed_tasks: 0,
            success_rate: 1.0,
            avg_cost_per_task_cents: 50.0,
            total_input_tokens: 100_000,
            total_output_tokens: 50_000,
            cost_per_1m_tokens: 3.33,
        };

        // Day 2: $7 (cumulative: $12)
        let day2 = ProviderAnalytics {
            provider: "claude".to_string(),
            total_cost_cents: 700,
            total_tasks: 14,
            successful_tasks: 14,
            failed_tasks: 0,
            success_rate: 1.0,
            avg_cost_per_task_cents: 50.0,
            total_input_tokens: 140_000,
            total_output_tokens: 70_000,
            cost_per_1m_tokens: 3.33,
        };

        // Day 3: $6 (cumulative: $18)
        let day3 = ProviderAnalytics {
            provider: "claude".to_string(),
            total_cost_cents: 600,
            total_tasks: 12,
            successful_tasks: 12,
            failed_tasks: 0,
            success_rate: 1.0,
            avg_cost_per_task_cents: 50.0,
            total_input_tokens: 120_000,
            total_output_tokens: 60_000,
            cost_per_1m_tokens: 3.33,
        };

        // Verify cost progression
        assert!(day2.total_cost_cents > day1.total_cost_cents);
        assert!(day3.total_cost_cents > day1.total_cost_cents);
        assert!(day2.total_tasks > day1.total_tasks);

        // Verify average cost per task consistency
        assert!((day1.avg_cost_per_task_cents - day2.avg_cost_per_task_cents).abs() < 0.01);
        assert!((day2.avg_cost_per_task_cents - day3.avg_cost_per_task_cents).abs() < 0.01);
    }

    #[test]
    fn test_provider_with_high_failure_rate() {
        let failing_provider = ProviderAnalytics {
            provider: "unstable".to_string(),
            total_cost_cents: 1000,
            total_tasks: 100,
            successful_tasks: 50,
            failed_tasks: 50,
            success_rate: 0.5,
            avg_cost_per_task_cents: 10.0,
            total_input_tokens: 500_000,
            total_output_tokens: 250_000,
            cost_per_1m_tokens: 1.33,
        };

        let reliable_provider = ProviderAnalytics {
            provider: "reliable".to_string(),
            total_cost_cents: 2000,
            total_tasks: 100,
            successful_tasks: 95,
            failed_tasks: 5,
            success_rate: 0.95,
            avg_cost_per_task_cents: 20.0,
            total_input_tokens: 500_000,
            total_output_tokens: 250_000,
            cost_per_1m_tokens: 2.67,
        };

        // Even though unstable provider is cheaper per task,
        // reliability matters for efficiency
        assert!(
            failing_provider.avg_cost_per_task_cents < reliable_provider.avg_cost_per_task_cents
        );
        assert!(failing_provider.success_rate < reliable_provider.success_rate);

        // Quality score should reflect reliability
        // In a real scenario, this would impact efficiency_ratio
        assert!(reliable_provider.success_rate > failing_provider.success_rate);
    }
}
