use axum::{
    extract::{Path, Query, State},
    Json,
};
use serde::Deserialize;
use uuid::Uuid;

use crate::{
    db,
    error::Result,
    models::{Bulletin, CreateBulletinRequest, ApiResponse, PaginatedResponse},
    AppState,
};

#[derive(Deserialize)]
pub struct ListQuery {
    page: Option<i32>,
    per_page: Option<i32>,
    active_only: Option<bool>,
}

pub async fn list(
    State(state): State<AppState>,
    Query(query): Query<ListQuery>,
) -> Result<Json<ApiResponse<PaginatedResponse<Bulletin>>>> {
    let page = query.page.unwrap_or(1);
    let per_page_i32 = query.per_page.unwrap_or(25).min(100);
    let per_page = per_page_i32 as i64;  // Convert to i64 for database
    let active_only = query.active_only.unwrap_or(false);
    
    let (bulletins, total) = db::bulletins::list(&state.pool, page, per_page, active_only).await?;
    
    let response = PaginatedResponse {
        items: bulletins,
        total,
        page,
        per_page: per_page_i32,  // Convert back to i32 for response
        has_more: (page as i64 * per_page) < total,
    };

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

pub async fn current(
    State(state): State<AppState>,
) -> Result<Json<ApiResponse<Bulletin>>> {
    let bulletin = db::bulletins::get_current(&state.pool).await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: bulletin,
        message: None,
    }))
}

pub async fn get(
    State(state): State<AppState>,
    Path(id): Path<Uuid>,
) -> Result<Json<ApiResponse<Bulletin>>> {
    let bulletin = db::bulletins::get_by_id(&state.pool, &id).await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: bulletin,
        message: None,
    }))
}

pub async fn create(
    State(state): State<AppState>,
    Json(req): Json<CreateBulletinRequest>,
) -> Result<Json<ApiResponse<Bulletin>>> {
    let bulletin = db::bulletins::create(&state.pool, req).await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: Some(bulletin),
        message: Some("Bulletin created successfully".to_string()),
    }))
}

pub async fn update(
    State(state): State<AppState>,
    Path(id): Path<Uuid>,
    Json(req): Json<CreateBulletinRequest>,
) -> Result<Json<ApiResponse<Bulletin>>> {
    let bulletin = db::bulletins::update(&state.pool, &id, req).await?;
    
    Ok(Json(ApiResponse {
        success: true,
        data: bulletin,
        message: Some("Bulletin updated successfully".to_string()),
    }))
}

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

// Stub functions for routes that don't apply to bulletins
pub async fn upcoming(State(_state): State<AppState>) -> Result<Json<ApiResponse<String>>> {
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Upcoming not available for bulletins".to_string()),
        message: None,
    }))
}

pub async fn featured(State(_state): State<AppState>) -> Result<Json<ApiResponse<String>>> {
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Featured not available for bulletins".to_string()),
        message: None,
    }))
}

pub async fn submit(State(_state): State<AppState>) -> Result<Json<ApiResponse<String>>> {
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Submit not available for bulletins".to_string()),
        message: None,
    }))
}

pub async fn list_pending(State(_state): State<AppState>) -> Result<Json<ApiResponse<String>>> {
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Pending not available for bulletins".to_string()),
        message: None,
    }))
}

pub async fn approve(State(_state): State<AppState>) -> Result<Json<ApiResponse<String>>> {
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Approve not available for bulletins".to_string()),
        message: None,
    }))
}

pub async fn reject(State(_state): State<AppState>) -> Result<Json<ApiResponse<String>>> {
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Reject not available for bulletins".to_string()),
        message: None,
    }))
}

pub async fn get_schedules(State(_state): State<AppState>) -> Result<Json<ApiResponse<String>>> {
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Schedules not available for bulletins".to_string()),
        message: None,
    }))
}

pub async fn update_schedules(State(_state): State<AppState>) -> Result<Json<ApiResponse<String>>> {
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Update schedules not available for bulletins".to_string()),
        message: None,
    }))
}

pub async fn get_app_version(State(_state): State<AppState>) -> Result<Json<ApiResponse<String>>> {
    Ok(Json(ApiResponse {
        success: true,
        data: Some("App version not available for bulletins".to_string()),
        message: None,
    }))
}

pub async fn upload(State(_state): State<AppState>) -> Result<Json<ApiResponse<String>>> {
    Ok(Json(ApiResponse {
        success: true,
        data: Some("Upload not available for bulletins".to_string()),
        message: None,
    }))
}
