#![allow(dead_code)]
use crate::auth::jwt::Claims;
use crate::config::AppState;
use crate::models::health_stats::HealthStatistic;
use axum::{
    extract::{Path, Query, State},
    http::StatusCode,
    response::IntoResponse,
    Extension, Json,
};
use mongodb::bson::oid::ObjectId;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
pub struct CreateHealthStatRequest {
    pub stat_type: String,
    pub value: serde_json::Value, // Support complex values like blood pressure
    pub unit: String,
    pub notes: Option<String>,
    pub recorded_at: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct UpdateHealthStatRequest {
    pub value: Option<serde_json::Value>,
    pub unit: Option<String>,
    pub notes: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct HealthTrendsQuery {
    pub stat_type: String,
    pub period: Option<String>, // "7d", "30d", etc.
}

pub async fn create_health_stat(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Json(req): Json<CreateHealthStatRequest>,
) -> impl IntoResponse {
    let repo = match state.health_stats_repo.as_ref() {
        Some(r) => r,
        None => {
            return (
                StatusCode::SERVICE_UNAVAILABLE,
                Json(serde_json::json!({ "error": "health stats unavailable" })),
            )
                .into_response()
        }
    };

    // Convert complex value to f64 or store as string
    let value_num = match req.value {
        serde_json::Value::Number(n) => n.as_f64().unwrap_or(0.0),
        serde_json::Value::Object(_) => {
            // For complex objects like blood pressure, use a default
            0.0
        }
        _ => 0.0,
    };

    let stat = HealthStatistic {
        id: None,
        user_id: claims.sub.clone(),
        stat_type: req.stat_type,
        value: value_num,
        unit: req.unit,
        notes: req.notes,
        recorded_at: req.recorded_at.unwrap_or_else(|| {
            use chrono::Utc;
            Utc::now().to_rfc3339()
        }),
    };

    match repo.create(&stat).await {
        Ok(created) => (StatusCode::CREATED, Json(created)).into_response(),
        Err(e) => {
            eprintln!("Error creating health stat: {:?}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                "Failed to create health stat",
            )
                .into_response()
        }
    }
}

pub async fn list_health_stats(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
) -> impl IntoResponse {
    let repo = match state.health_stats_repo.as_ref() {
        Some(r) => r,
        None => {
            return (
                StatusCode::SERVICE_UNAVAILABLE,
                Json(serde_json::json!({ "error": "health stats unavailable" })),
            )
                .into_response()
        }
    };
    match repo.find_by_user(&claims.sub).await {
        Ok(stats) => (StatusCode::OK, Json(stats)).into_response(),
        Err(e) => {
            eprintln!("Error fetching health stats: {:?}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                "Failed to fetch health stats",
            )
                .into_response()
        }
    }
}

pub async fn get_health_stat(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Path(id): Path<String>,
) -> impl IntoResponse {
    let repo = match state.health_stats_repo.as_ref() {
        Some(r) => r,
        None => {
            return (
                StatusCode::SERVICE_UNAVAILABLE,
                Json(serde_json::json!({ "error": "health stats unavailable" })),
            )
                .into_response()
        }
    };
    let object_id = match ObjectId::parse_str(&id) {
        Ok(oid) => oid,
        Err(_) => return (StatusCode::BAD_REQUEST, "Invalid ID").into_response(),
    };

    match repo.find_by_id(&object_id).await {
        Ok(Some(stat)) => {
            if stat.user_id != claims.sub {
                return (StatusCode::FORBIDDEN, "Access denied").into_response();
            }
            (StatusCode::OK, Json(stat)).into_response()
        }
        Ok(None) => (StatusCode::NOT_FOUND, "Health stat not found").into_response(),
        Err(e) => {
            eprintln!("Error fetching health stat: {:?}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                "Failed to fetch health stat",
            )
                .into_response()
        }
    }
}

pub async fn update_health_stat(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Path(id): Path<String>,
    Json(req): Json<UpdateHealthStatRequest>,
) -> impl IntoResponse {
    let repo = match state.health_stats_repo.as_ref() {
        Some(r) => r,
        None => {
            return (
                StatusCode::SERVICE_UNAVAILABLE,
                Json(serde_json::json!({ "error": "health stats unavailable" })),
            )
                .into_response()
        }
    };
    let object_id = match ObjectId::parse_str(&id) {
        Ok(oid) => oid,
        Err(_) => return (StatusCode::BAD_REQUEST, "Invalid ID").into_response(),
    };

    let mut stat = match repo.find_by_id(&object_id).await {
        Ok(Some(s)) => s,
        Ok(None) => return (StatusCode::NOT_FOUND, "Health stat not found").into_response(),
        Err(_) => {
            return (
                StatusCode::INTERNAL_SERVER_ERROR,
                "Failed to fetch health stat",
            )
                .into_response()
        }
    };

    if stat.user_id != claims.sub {
        return (StatusCode::FORBIDDEN, "Access denied").into_response();
    }

    if let Some(value) = req.value {
        let value_num = match value {
            serde_json::Value::Number(n) => n.as_f64().unwrap_or(0.0),
            _ => 0.0,
        };
        stat.value = value_num;
    }
    if let Some(unit) = req.unit {
        stat.unit = unit;
    }
    if let Some(notes) = req.notes {
        stat.notes = Some(notes);
    }

    match repo.update(&object_id, &stat).await {
        Ok(Some(updated)) => (StatusCode::OK, Json(updated)).into_response(),
        Ok(None) => (StatusCode::NOT_FOUND, "Failed to update").into_response(),
        Err(_) => (
            StatusCode::INTERNAL_SERVER_ERROR,
            "Failed to update health stat",
        )
            .into_response(),
    }
}

pub async fn delete_health_stat(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Path(id): Path<String>,
) -> impl IntoResponse {
    let repo = match state.health_stats_repo.as_ref() {
        Some(r) => r,
        None => {
            return (
                StatusCode::SERVICE_UNAVAILABLE,
                Json(serde_json::json!({ "error": "health stats unavailable" })),
            )
                .into_response()
        }
    };
    let object_id = match ObjectId::parse_str(&id) {
        Ok(oid) => oid,
        Err(_) => return (StatusCode::BAD_REQUEST, "Invalid ID").into_response(),
    };

    let stat = match repo.find_by_id(&object_id).await {
        Ok(Some(s)) => s,
        Ok(None) => return (StatusCode::NOT_FOUND, "Health stat not found").into_response(),
        Err(_) => {
            return (
                StatusCode::INTERNAL_SERVER_ERROR,
                "Failed to fetch health stat",
            )
                .into_response()
        }
    };

    if stat.user_id != claims.sub {
        return (StatusCode::FORBIDDEN, "Access denied").into_response();
    }

    match repo.delete(&object_id).await {
        Ok(true) => StatusCode::NO_CONTENT.into_response(),
        _ => (
            StatusCode::INTERNAL_SERVER_ERROR,
            "Failed to delete health stat",
        )
            .into_response(),
    }
}

pub async fn get_health_trends(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Query(query): Query<HealthTrendsQuery>,
) -> impl IntoResponse {
    let repo = match state.health_stats_repo.as_ref() {
        Some(r) => r,
        None => {
            return (
                StatusCode::SERVICE_UNAVAILABLE,
                Json(serde_json::json!({ "error": "health stats unavailable" })),
            )
                .into_response()
        }
    };
    match repo.find_by_user(&claims.sub).await {
        Ok(stats) => {
            // Filter by stat_type
            let filtered: Vec<HealthStatistic> = stats
                .into_iter()
                .filter(|s| s.stat_type == query.stat_type)
                .collect();

            // Calculate basic trend statistics
            if filtered.is_empty() {
                return (
                    StatusCode::OK,
                    Json(serde_json::json!({
                        "stat_type": query.stat_type,
                        "count": 0,
                        "data": []
                    })),
                )
                    .into_response();
            }

            let values: Vec<f64> = filtered.iter().map(|s| s.value).collect();
            let avg = values.iter().sum::<f64>() / values.len() as f64;
            let min = values.iter().fold(f64::INFINITY, |a, &b| a.min(b));
            let max = values.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b));

            let response = serde_json::json!({
                "stat_type": query.stat_type,
                "count": filtered.len(),
                "average": avg,
                "min": min,
                "max": max,
                "data": filtered
            });

            (StatusCode::OK, Json(response)).into_response()
        }
        Err(e) => {
            eprintln!("Error fetching health trends: {:?}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                "Failed to fetch health trends",
            )
                .into_response()
        }
    }
}
