#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(unused_variables)]
use axum::{
    extract::{Extension, Json, Path, Query, State},
    http::StatusCode,
};
use mongodb::bson::oid::ObjectId;
use std::time::SystemTime;

use crate::{
    auth::jwt::Claims, // Fixed: import from auth::jwt instead of handlers::auth
    config::AppState,
    models::medication::{
        CreateMedicationRequest, LogDoseRequest, Medication, MedicationRepository,
        UpdateMedicationRequest,
    },
};

#[derive(serde::Deserialize)]
pub struct ListMedicationsQuery {
    pub profile_id: Option<String>,
    pub active: Option<bool>,
    pub limit: Option<i64>,
}

pub async fn create_medication(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Json(req): Json<CreateMedicationRequest>,
) -> Result<Json<Medication>, StatusCode> {
    let database = state.db.get_database();
    let repo = MedicationRepository::new(database.collection("medications"));

    let now = SystemTime::now();
    let medication_id = uuid::Uuid::new_v4().to_string();

    // Build medication data JSON
    let medication_data_value = serde_json::json!({
        "name": req.name,
        "dosage": req.dosage,
        "frequency": req.frequency,
        "route": req.route,
        "reason": req.reason,
        "instructions": req.instructions,
        "sideEffects": req.side_effects.unwrap_or_default(),
        "prescribedBy": req.prescribed_by,
        "prescribedDate": req.prescribed_date,
        "startDate": req.start_date,
        "endDate": req.end_date,
        "notes": req.notes,
        "tags": req.tags.unwrap_or_default(),
    });

    let medication_data = crate::models::health_data::EncryptedField {
        data: medication_data_value.to_string(),
        encrypted: false,
        iv: String::new(),
        auth_tag: String::new(),
    };

    let medication = Medication {
        id: None,
        medication_id,
        user_id: claims.sub,
        profile_id: req.profile_id.clone(),
        medication_data,
        reminders: req
            .reminder_times
            .unwrap_or_default()
            .into_iter()
            .map(|time| crate::models::medication::MedicationReminder {
                reminder_id: uuid::Uuid::new_v4().to_string(),
                scheduled_time: time,
            })
            .collect(),
        created_at: now.into(),
        updated_at: now.into(),
        pill_identification: req.pill_identification, // Phase 2.8
    };

    match repo.create(medication).await {
        Ok(med) => Ok(Json(med)),
        Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
    }
}

pub async fn list_medications(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Query(query): Query<ListMedicationsQuery>,
) -> Result<Json<Vec<Medication>>, StatusCode> {
    let database = state.db.get_database();
    let repo = MedicationRepository::new(database.collection("medications"));

    let _limit = query.limit.unwrap_or(100);

    match repo.find_by_user(&claims.sub).await {
        Ok(medications) => Ok(Json(medications)),
        Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
    }
}

pub async fn get_medication(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Path(id): Path<String>,
) -> Result<Json<Medication>, StatusCode> {
    let database = state.db.get_database();
    let repo = MedicationRepository::new(database.collection("medications"));

    match ObjectId::parse_str(&id) {
        Ok(oid) => match repo.find_by_id(&oid).await {
            Ok(Some(medication)) => Ok(Json(medication)),
            Ok(None) => Err(StatusCode::NOT_FOUND),
            Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
        },
        Err(_) => Err(StatusCode::BAD_REQUEST),
    }
}

pub async fn update_medication(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Path(id): Path<String>,
    Json(req): Json<UpdateMedicationRequest>,
) -> Result<Json<Medication>, StatusCode> {
    let database = state.db.get_database();
    let repo = MedicationRepository::new(database.collection("medications"));

    match ObjectId::parse_str(&id) {
        Ok(oid) => match repo.update(&oid, req).await {
            Ok(Some(medication)) => Ok(Json(medication)),
            Ok(None) => Err(StatusCode::NOT_FOUND),
            Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
        },
        Err(_) => Err(StatusCode::BAD_REQUEST),
    }
}

pub async fn delete_medication(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Path(id): Path<String>,
) -> Result<StatusCode, StatusCode> {
    let database = state.db.get_database();
    let repo = MedicationRepository::new(database.collection("medications"));

    match ObjectId::parse_str(&id) {
        Ok(oid) => match repo.delete(&oid).await {
            Ok(true) => Ok(StatusCode::NO_CONTENT),
            Ok(false) => Err(StatusCode::NOT_FOUND),
            Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
        },
        Err(_) => Err(StatusCode::BAD_REQUEST),
    }
}

pub async fn log_dose(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Path(id): Path<String>,
    Json(req): Json<LogDoseRequest>,
) -> Result<StatusCode, StatusCode> {
    let database = state.db.get_database();

    let now = SystemTime::now();

    let dose = crate::models::medication::MedicationDose {
        id: None,
        medication_id: id.clone(),
        user_id: claims.sub.clone(),
        logged_at: now.into(),
        scheduled_time: req.scheduled_time,
        taken: req.taken.unwrap_or(true),
        notes: req.notes,
    };

    match database
        .collection("medication_doses")
        .insert_one(dose.clone(), None)
        .await
    {
        Ok(_) => Ok(StatusCode::CREATED),
        Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
    }
}

pub async fn get_adherence(
    State(state): State<AppState>,
    Extension(claims): Extension<Claims>,
    Path(id): Path<String>,
) -> Result<Json<crate::models::medication::AdherenceStats>, StatusCode> {
    let database = state.db.get_database();
    let repo = MedicationRepository::new(database.collection("medications"));

    match repo.calculate_adherence(&id, 30).await {
        Ok(stats) => Ok(Json(stats)),
        Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
    }
}
