use crate::error::ApiError;
use crate::models::{PaginationParams, CreateEventRequest};
use axum::{
    extract::{Path, Query, State},
    Json,
};
use serde::Deserialize;
use uuid::Uuid;

// New imports for WebP and multipart support
use axum::extract::Multipart;
use crate::utils::{
    images::convert_to_webp,
    common::ListQueryParams,
    response::success_response,
    multipart_helpers::process_event_multipart,
    pagination::PaginationHelper,
    urls::UrlBuilder,
    converters::convert_event_to_v1,
};
use tokio::fs;

use crate::{
    services::EventService,
    error::Result,
    models::{Event, PendingEvent, ApiResponse, PaginatedResponse},
    AppState, db,
};

// Use shared ListQueryParams instead of custom EventQuery
// #[derive(Deserialize)]
// pub struct EventQuery {
//     page: Option<i32>,
//     per_page: Option<i32>,
// }

pub async fn list(
    State(state): State<AppState>,
    Query(query): Query<ListQueryParams>,
) -> Result<Json<ApiResponse<PaginatedResponse<Event>>>> {
    let pagination = PaginationHelper::from_query(query.page, query.per_page);
    let url_builder = UrlBuilder::new();
    
    // Use service layer for business logic
    let events = EventService::list_v1(&state.pool, &url_builder).await?;
    let total = events.len() as i64;
    
    // Apply pagination in memory (could be moved to service layer)
    let start = pagination.offset as usize;
    let end = std::cmp::min(start + pagination.per_page as usize, events.len());
    let paginated_events = if start < events.len() {
        events[start..end].to_vec()
    } else {
        Vec::new()
    };
    
    let response = pagination.create_response(paginated_events, total);
    Ok(success_response(response))
}

pub async fn submit(
    State(state): State<AppState>,
    multipart: Multipart,
) -> Result<Json<ApiResponse<PendingEvent>>> {
    // Use shared multipart processor
    let (request, image_data, thumbnail_data) = process_event_multipart(multipart).await?;

    // Use service layer for business logic
    let url_builder = UrlBuilder::new();
    let converted_pending_event = EventService::submit_for_approval(&state.pool, request, &url_builder).await?;

    // Process images if provided using shared utilities
    if let Some(image_bytes) = image_data {
        let event_id = converted_pending_event.id;
        let image_filename = format!("{}.webp", event_id);
        let image_path = format!("uploads/events/{}", image_filename);
        
        // Ensure directory exists
        fs::create_dir_all("uploads/events").await?;
        
        // Convert and save image using shared converter
        let webp_data = convert_to_webp(&image_bytes)?;
        fs::write(&image_path, webp_data).await?;
        
        // Update database with image URL
        let full_url = format!("https://api.rockvilletollandsda.church/{}", image_path);
        let _ = sqlx::query!(
            "UPDATE pending_events SET image = $1 WHERE id = $2",
            full_url,
            event_id
        ).execute(&state.pool).await;
    }

    if let Some(thumb_bytes) = thumbnail_data {
        let event_id = converted_pending_event.id;
        let thumb_filename = format!("thumb_{}.webp", event_id);
        let thumb_path = format!("uploads/events/{}", thumb_filename);
        
        // Convert and save thumbnail using shared converter
        let webp_data = convert_to_webp(&thumb_bytes)?;
        fs::write(&thumb_path, webp_data).await?;
        
        // Update database with thumbnail URL
        let full_url = format!("https://api.rockvilletollandsda.church/{}", thumb_path);
        let _ = sqlx::query!(
            "UPDATE pending_events SET thumbnail = $1 WHERE id = $2",
            full_url,
            event_id
        ).execute(&state.pool).await;
    }

    // Send email notification to admin
    let mailer = state.mailer.clone();
    let event_for_email = converted_pending_event.clone();
    tokio::spawn(async move {
        if let Err(e) = mailer.send_event_submission_notification(&event_for_email).await {
            tracing::error!("Failed to send email: {:?}", e);
        } else {
            tracing::info!("Email sent for event: {}", event_for_email.title);
        }
    });
    
    Ok(success_response(converted_pending_event))
}

pub async fn upcoming(
    State(state): State<AppState>,
    Query(_query): Query<ListQueryParams>,
) -> Result<Json<ApiResponse<Vec<Event>>>> {
    let url_builder = UrlBuilder::new();
    let events = EventService::get_upcoming_v1(&state.pool, 50, &url_builder).await?;
    Ok(success_response(events))
}

pub async fn featured(
    State(state): State<AppState>,
    Query(_query): Query<ListQueryParams>,
) -> Result<Json<ApiResponse<Vec<Event>>>> {
    let url_builder = UrlBuilder::new();
    let events = EventService::get_featured_v1(&state.pool, 10, &url_builder).await?;
    Ok(success_response(events))
}

pub async fn get(
    State(state): State<AppState>,
    Path(id): Path<Uuid>,
) -> Result<Json<ApiResponse<Event>>> {
    let url_builder = UrlBuilder::new();
    let event = EventService::get_by_id_v1(&state.pool, &id, &url_builder).await?
        .ok_or_else(|| ApiError::NotFound("Event not found".to_string()))?;
    Ok(success_response(event))
}

pub async fn create(
    State(state): State<AppState>,
    Json(req): Json<CreateEventRequest>,
) -> Result<Json<ApiResponse<Event>>> {
    let url_builder = UrlBuilder::new();
    let event = EventService::create(&state.pool, req, &url_builder).await?;
    Ok(success_response(event))
}

pub async fn update(
    Path(id): Path<Uuid>,
    State(state): State<AppState>,
    Json(req): Json<CreateEventRequest>,
) -> Result<Json<ApiResponse<Event>>> {
    let event = EventService::update_event(&state.pool, &id, req).await?;
    let url_builder = UrlBuilder::new();
    let converted_event = convert_event_to_v1(event, &url_builder)?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: Some(converted_event),
        message: Some("Event updated successfully".to_string()),
    }))
}

pub async fn delete(
    Path(id): Path<Uuid>,
    State(state): State<AppState>,
) -> Result<Json<ApiResponse<String>>> {
    EventService::delete_event(&state.pool, &id).await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Event deleted successfully".to_string()),
        message: Some("Event deleted successfully".to_string()),
    }))
}

pub async fn list_pending(
    Query(params): Query<PaginationParams>,
    State(state): State<AppState>,
) -> Result<Json<ApiResponse<Vec<PendingEvent>>>> {
    let url_builder = UrlBuilder::new();
    let page = params.page.unwrap_or(1) as i32;
    let per_page = params.per_page.unwrap_or(10) as i32;
    let events = EventService::list_pending_v1(&state.pool, page, per_page, &url_builder).await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: Some(events),
        message: None,
    }))
}

pub async fn approve(
    Path(id): Path<Uuid>,
    State(state): State<AppState>,
    Json(req): Json<ApproveRejectRequest>,
) -> Result<Json<ApiResponse<Event>>> {
    let pending_event = db::events::get_pending_by_id(&state.pool, &id).await?
        .ok_or_else(|| ApiError::NotFound("Pending event not found".to_string()))?;
    
    let event = EventService::approve_pending_event(&state.pool, &id).await?;
    
    if let Some(_submitter_email) = &pending_event.submitter_email {
        let _ = state.mailer.send_event_approval_notification(&pending_event, req.admin_notes.as_deref()).await;
    }
    
    Ok(Json(ApiResponse {
        success: true,
        data: Some(event),
        message: Some("Event approved successfully".to_string()),
    }))
}

pub async fn reject(
    Path(id): Path<Uuid>,
    State(state): State<AppState>,
    Json(req): Json<ApproveRejectRequest>,
) -> Result<Json<ApiResponse<String>>> {
    let pending_event = db::events::get_pending_by_id(&state.pool, &id).await?
        .ok_or_else(|| ApiError::NotFound("Pending event not found".to_string()))?;
    
    EventService::reject_pending_event(&state.pool, &id, req.admin_notes.clone()).await?;
    
    if let Some(_submitter_email) = &pending_event.submitter_email {
        let _ = state.mailer.send_event_rejection_notification(&pending_event, req.admin_notes.as_deref()).await;
    }
    
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Event rejected".to_string()),
        message: Some("Event rejected successfully".to_string()),
    }))
}


#[derive(Debug, Deserialize)]
pub struct ApproveRejectRequest {
    pub admin_notes: Option<String>,
}

pub async fn delete_pending(
    Path(id): Path<Uuid>,
    State(state): State<AppState>,
) -> Result<Json<ApiResponse<String>>> {
    EventService::delete_pending_event(&state.pool, &id).await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Pending event deleted successfully".to_string()),
        message: Some("Pending event deleted successfully".to_string()),
    }))
}
