// Provider Analytics REST API Endpoints - Phase 7
// GET /api/v1/analytics/providers - Provider metrics and analysis

use axum::{
    extract::{Path, State},
    http::StatusCode,
    response::IntoResponse,
    Json,
};
use ontoref_derive::onto_api;
use serde::{Deserialize, Serialize};
use tracing::{debug, error};

use crate::api::AppState;

#[derive(Debug, Serialize, Deserialize)]
pub struct ProviderBreakdownResponse {
    pub success: bool,
    pub providers: Vec<ProviderBreakdown>,
    pub total_cost_cents: u32,
    pub error: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProviderBreakdown {
    pub provider: String,
    pub total_cost_cents: u32,
    pub percentage: f64,
    pub task_count: u64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProviderEfficiencyResponse {
    pub success: bool,
    pub providers: Vec<ProviderEfficiencyData>,
    pub error: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProviderEfficiencyData {
    pub rank: u32,
    pub provider: String,
    pub quality_score: f64,
    pub cost_score: f64,
    pub efficiency_ratio: f64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProviderAnalyticsData {
    pub success: bool,
    pub provider: String,
    pub total_cost_cents: u32,
    pub total_tasks: u64,
    pub successful_tasks: u64,
    pub failed_tasks: u64,
    pub success_rate: f64,
    pub avg_cost_per_task_cents: f64,
    pub total_input_tokens: u64,
    pub total_output_tokens: u64,
    pub cost_per_1m_tokens: f64,
    pub error: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ProviderCostForecastData {
    pub success: bool,
    pub provider: String,
    pub current_daily_cost_cents: u32,
    pub projected_weekly_cost_cents: u32,
    pub projected_monthly_cost_cents: u32,
    pub trend: String,
    pub confidence: f64,
    pub error: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TaskTypeMetricsResponse {
    pub success: bool,
    pub provider: String,
    pub task_type: String,
    pub total_cost_cents: u32,
    pub task_count: u64,
    pub success_rate: f64,
    pub avg_duration_ms: f64,
    pub error: Option<String>,
}

/// GET /api/v1/analytics/providers - Get cost breakdown by provider
#[onto_api(
    method = "GET",
    path = "/api/v1/analytics/providers",
    description = "Returns cost breakdown grouped by LLM provider with percentage share.",
    auth = "bearer",
    actors = "developer, ci, admin",
    tags = "analytics, providers, cost, read"
)]
pub async fn get_provider_cost_breakdown(State(state): State<AppState>) -> impl IntoResponse {
    debug!("GET /api/v1/analytics/providers - cost breakdown");

    match state
        .provider_analytics_service
        .get_cost_breakdown_by_provider()
        .await
    {
        Ok(breakdown) => {
            let total_cost: u32 = breakdown.values().sum();
            let mut providers: Vec<ProviderBreakdown> = breakdown
                .into_iter()
                .map(|(provider, cost)| ProviderBreakdown {
                    provider,
                    total_cost_cents: cost,
                    percentage: if total_cost > 0 {
                        (cost as f64 / total_cost as f64) * 100.0
                    } else {
                        0.0
                    },
                    task_count: 0,
                })
                .collect();

            providers.sort_by(|a, b| b.total_cost_cents.cmp(&a.total_cost_cents));

            (
                StatusCode::OK,
                Json(ProviderBreakdownResponse {
                    success: true,
                    providers,
                    total_cost_cents: total_cost,
                    error: None,
                }),
            )
                .into_response()
        }
        Err(e) => {
            error!("Failed to get provider cost breakdown: {}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ProviderBreakdownResponse {
                    success: false,
                    providers: vec![],
                    total_cost_cents: 0,
                    error: Some(format!("Failed to fetch provider breakdown: {}", e)),
                }),
            )
                .into_response()
        }
    }
}

/// GET /api/v1/analytics/providers/efficiency - Get provider efficiency ranking
#[onto_api(
    method = "GET",
    path = "/api/v1/analytics/providers/efficiency",
    description = "Returns providers ranked by efficiency ratio combining quality and cost scores.",
    auth = "bearer",
    actors = "developer, ci, admin",
    tags = "analytics, providers, read"
)]
pub async fn get_provider_efficiency(State(state): State<AppState>) -> impl IntoResponse {
    debug!("GET /api/v1/analytics/providers/efficiency");

    match state
        .provider_analytics_service
        .get_provider_efficiency_ranking()
        .await
    {
        Ok(efficiencies) => {
            let providers = efficiencies
                .into_iter()
                .map(|eff| ProviderEfficiencyData {
                    rank: eff.rank,
                    provider: eff.provider,
                    quality_score: eff.quality_score,
                    cost_score: eff.cost_score,
                    efficiency_ratio: eff.efficiency_ratio,
                })
                .collect();

            (
                StatusCode::OK,
                Json(ProviderEfficiencyResponse {
                    success: true,
                    providers,
                    error: None,
                }),
            )
                .into_response()
        }
        Err(e) => {
            error!("Failed to get provider efficiency: {}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ProviderEfficiencyResponse {
                    success: false,
                    providers: vec![],
                    error: Some(format!("Failed to fetch efficiency ranking: {}", e)),
                }),
            )
                .into_response()
        }
    }
}

/// GET /api/v1/analytics/providers/:provider - Get detailed analytics for a
/// provider
#[onto_api(
    method = "GET",
    path = "/api/v1/analytics/providers/:provider",
    description = "Returns detailed cost and success-rate analytics for a single LLM provider.",
    auth = "bearer",
    actors = "developer, ci, admin",
    params = "provider:string:required:Provider name (e.g. openai, anthropic)",
    tags = "analytics, providers, read"
)]
pub async fn get_provider_analytics(
    State(state): State<AppState>,
    Path(provider): Path<String>,
) -> impl IntoResponse {
    debug!("GET /api/v1/analytics/providers/{} - analytics", provider);

    match state
        .provider_analytics_service
        .get_provider_analytics(&provider)
        .await
    {
        Ok(analytics) => (
            StatusCode::OK,
            Json(ProviderAnalyticsData {
                success: true,
                provider: analytics.provider,
                total_cost_cents: analytics.total_cost_cents,
                total_tasks: analytics.total_tasks,
                successful_tasks: analytics.successful_tasks,
                failed_tasks: analytics.failed_tasks,
                success_rate: analytics.success_rate,
                avg_cost_per_task_cents: analytics.avg_cost_per_task_cents,
                total_input_tokens: analytics.total_input_tokens,
                total_output_tokens: analytics.total_output_tokens,
                cost_per_1m_tokens: analytics.cost_per_1m_tokens,
                error: None,
            }),
        )
            .into_response(),
        Err(e) => {
            error!("Failed to get provider analytics: {}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ProviderAnalyticsData {
                    success: false,
                    provider,
                    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,
                    error: Some(format!("Failed to fetch provider analytics: {}", e)),
                }),
            )
                .into_response()
        }
    }
}

/// GET /api/v1/analytics/providers/:provider/forecast - Get cost forecast for a
/// provider
#[onto_api(
    method = "GET",
    path = "/api/v1/analytics/providers/:provider/forecast",
    description = "Returns weekly and monthly cost forecast for a provider based on recent usage \
                   trend.",
    auth = "bearer",
    actors = "developer, ci, admin",
    params = "provider:string:required:Provider name (e.g. openai, anthropic)",
    tags = "analytics, providers, cost, read"
)]
pub async fn get_provider_forecast(
    State(state): State<AppState>,
    Path(provider): Path<String>,
) -> impl IntoResponse {
    debug!("GET /api/v1/analytics/providers/{}/forecast", provider);

    match state
        .provider_analytics_service
        .forecast_provider_costs(&provider)
        .await
    {
        Ok(forecast) => (
            StatusCode::OK,
            Json(ProviderCostForecastData {
                success: true,
                provider: forecast.provider,
                current_daily_cost_cents: forecast.current_daily_cost_cents,
                projected_weekly_cost_cents: forecast.projected_weekly_cost_cents,
                projected_monthly_cost_cents: forecast.projected_monthly_cost_cents,
                trend: forecast.trend,
                confidence: forecast.confidence,
                error: None,
            }),
        )
            .into_response(),
        Err(e) => {
            error!("Failed to get provider forecast: {}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(ProviderCostForecastData {
                    success: false,
                    provider,
                    current_daily_cost_cents: 0,
                    projected_weekly_cost_cents: 0,
                    projected_monthly_cost_cents: 0,
                    trend: "unknown".to_string(),
                    confidence: 0.0,
                    error: Some(format!("Failed to fetch forecast: {}", e)),
                }),
            )
                .into_response()
        }
    }
}

/// GET /api/v1/analytics/providers/:provider/tasks/:task_type - Provider
/// performance by task type
#[onto_api(
    method = "GET",
    path = "/api/v1/analytics/providers/:provider/tasks/:task_type",
    description = "Returns a provider's performance metrics scoped to a specific task type.",
    auth = "bearer",
    actors = "developer, ci, admin",
    params = "provider:string:required:Provider name; task_type:string:required:Task type name",
    tags = "analytics, providers, tasks, read"
)]
pub async fn get_provider_task_type_metrics(
    State(state): State<AppState>,
    Path((provider, task_type)): Path<(String, String)>,
) -> impl IntoResponse {
    debug!(
        "GET /api/v1/analytics/providers/{}/tasks/{} - metrics",
        provider, task_type
    );

    match state
        .provider_analytics_service
        .get_provider_task_type_metrics(&provider, &task_type)
        .await
    {
        Ok(metrics) => (
            StatusCode::OK,
            Json(TaskTypeMetricsResponse {
                success: true,
                provider: metrics.provider,
                task_type: metrics.task_type,
                total_cost_cents: metrics.total_cost_cents,
                task_count: metrics.task_count,
                success_rate: metrics.success_rate,
                avg_duration_ms: metrics.avg_duration_ms,
                error: None,
            }),
        )
            .into_response(),
        Err(e) => {
            error!("Failed to get task type metrics: {}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(TaskTypeMetricsResponse {
                    success: false,
                    provider,
                    task_type,
                    total_cost_cents: 0,
                    task_count: 0,
                    success_rate: 0.0,
                    avg_duration_ms: 0.0,
                    error: Some(format!("Failed to fetch task metrics: {}", e)),
                }),
            )
                .into_response()
        }
    }
}
