use axum::{extract::{Path, Query, State}, response::Json};
use chrono::NaiveDate;
use crate::error::{ApiError, Result};
use crate::models::{ApiResponse, ScheduleData, ConferenceData, Personnel, DateQuery};
use serde::Deserialize;
use crate::AppState;

pub async fn get_schedule(
    State(state): State<AppState>,
    Query(params): Query<DateQuery>,
) -> Result<Json<ApiResponse<ScheduleData>>> {
    let date_str = params.date.unwrap_or_else(|| "2025-06-14".to_string());
    let date = NaiveDate::parse_from_str(&date_str, "%Y-%m-%d")
        .map_err(|_| ApiError::BadRequest("Invalid date format. Use YYYY-MM-DD".to_string()))?;
    
    let schedule = crate::db::schedule::get_by_date(&state.pool, &date).await?;
    
    let personnel = if let Some(s) = schedule {
        Personnel {
            ss_leader: s.ss_leader.unwrap_or_default(),
            ss_teacher: s.ss_teacher.unwrap_or_default(),
            mission_story: s.mission_story.unwrap_or_default(),
            song_leader: s.song_leader.unwrap_or_default(),
            announcements: s.scripture.unwrap_or_default(), // Map scripture to announcements
            offering: s.offering.unwrap_or_default(),
            special_music: s.special_music.unwrap_or_default(),
            speaker: s.sermon_speaker.unwrap_or_default(),
        }
    } else {
        // Return empty data if no schedule found
        Personnel {
            ss_leader: String::new(),
            ss_teacher: String::new(),
            mission_story: String::new(),
            song_leader: String::new(),
            announcements: String::new(),
            offering: String::new(),
            special_music: String::new(),
            speaker: String::new(),
        }
    };

    let schedule_data = ScheduleData {
        date: date_str,
        personnel,
    };

    Ok(Json(ApiResponse {
        success: true,
        data: Some(schedule_data),
        message: None,
    }))
}

pub async fn get_conference_data(
    State(_state): State<AppState>,
    Query(params): Query<DateQuery>,
) -> Result<Json<ApiResponse<ConferenceData>>> {
    let date = params.date.unwrap_or_else(|| "2025-06-14".to_string());
    
    let conference_data = ConferenceData {
        date,
        offering_focus: "Women's Ministries".to_string(),
        sunset_tonight: "8:29 pm".to_string(),
        sunset_next_friday: "8:31 pm".to_string(),
    };

    Ok(Json(ApiResponse {
        success: true,
        data: Some(conference_data),
        message: None,
    }))
}

// Admin endpoints

#[derive(Debug, Deserialize)]
pub struct CreateScheduleRequest {
    pub date: String,
    pub song_leader: Option<String>,
    pub ss_teacher: Option<String>,
    pub ss_leader: Option<String>,
    pub mission_story: Option<String>,
    pub special_program: Option<String>,
    pub sermon_speaker: Option<String>,
    pub scripture: Option<String>,
    pub offering: Option<String>,
    pub deacons: Option<String>,
    pub special_music: Option<String>,
    pub childrens_story: Option<String>,
    pub afternoon_program: Option<String>,
}

pub async fn create_schedule(
    State(state): State<AppState>,
    Json(payload): Json<CreateScheduleRequest>,
) -> Result<Json<ApiResponse<crate::models::Schedule>>> {
    let date = NaiveDate::parse_from_str(&payload.date, "%Y-%m-%d")
        .map_err(|_| ApiError::BadRequest("Invalid date format. Use YYYY-MM-DD".to_string()))?;
    
    let schedule = crate::models::Schedule {
        id: uuid::Uuid::new_v4(),
        date,
        song_leader: payload.song_leader,
        ss_teacher: payload.ss_teacher,
        ss_leader: payload.ss_leader,
        mission_story: payload.mission_story,
        special_program: payload.special_program,
        sermon_speaker: payload.sermon_speaker,
        scripture: payload.scripture,
        offering: payload.offering,
        deacons: payload.deacons,
        special_music: payload.special_music,
        childrens_story: payload.childrens_story,
        afternoon_program: payload.afternoon_program,
        created_at: None,
        updated_at: None,
    };
    
    let created = crate::db::schedule::insert_or_update(&state.pool, &schedule).await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: Some(created),
        message: Some("Schedule created successfully".to_string()),
    }))
}

pub async fn update_schedule(
    State(state): State<AppState>,
    Path(date_str): Path<String>,
    Json(payload): Json<CreateScheduleRequest>,
) -> Result<Json<ApiResponse<crate::models::Schedule>>> {
    let date = NaiveDate::parse_from_str(&date_str, "%Y-%m-%d")
        .map_err(|_| ApiError::BadRequest("Invalid date format. Use YYYY-MM-DD".to_string()))?;
    
    let schedule = crate::models::Schedule {
        id: uuid::Uuid::new_v4(),
        date,
        song_leader: payload.song_leader,
        ss_teacher: payload.ss_teacher,
        ss_leader: payload.ss_leader,
        mission_story: payload.mission_story,
        special_program: payload.special_program,
        sermon_speaker: payload.sermon_speaker,
        scripture: payload.scripture,
        offering: payload.offering,
        deacons: payload.deacons,
        special_music: payload.special_music,
        childrens_story: payload.childrens_story,
        afternoon_program: payload.afternoon_program,
        created_at: None,
        updated_at: None,
    };
    
    let updated = crate::db::schedule::insert_or_update(&state.pool, &schedule).await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: Some(updated),
        message: Some("Schedule updated successfully".to_string()),
    }))
}

pub async fn delete_schedule(
    State(state): State<AppState>,
    Path(date_str): Path<String>,
) -> Result<Json<ApiResponse<()>>> {
    let date = NaiveDate::parse_from_str(&date_str, "%Y-%m-%d")
        .map_err(|_| ApiError::BadRequest("Invalid date format. Use YYYY-MM-DD".to_string()))?;
    
    sqlx::query!("DELETE FROM schedule WHERE date = $1", date)
        .execute(&state.pool)
        .await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: None,
        message: Some("Schedule deleted successfully".to_string()),
    }))
}

pub async fn list_schedules(
    State(state): State<AppState>,
) -> Result<Json<ApiResponse<Vec<crate::models::Schedule>>>> {
    let schedules = sqlx::query_as!(
        crate::models::Schedule,
        "SELECT * FROM schedule ORDER BY date"
    )
    .fetch_all(&state.pool)
    .await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: Some(schedules),
        message: None,
    }))
}
