use axum::{extract::State, http::StatusCode, response::Json};

use crate::modes::server::common::{ApiResponse, AppState, StatusInfoResponse};

#[utoipa::path(
    get,
    path = "/api/status",
    operation_id = "keep_status",
    summary = "Get system status",
    description = "Retrieve system status including database info, storage paths, compression engines, and metadata plugins.",
    responses(
        (status = 200, description = "System status retrieved", body = StatusInfoResponse),
        (status = 401, description = "Unauthorized"),
        (status = 500, description = "Internal server error")
    ),
    security(
        ("bearerAuth" = [])
    ),
    tag = "status"
)]
/// Axum handler for the /api/status GET endpoint.
///
/// Generates and returns comprehensive system status using the StatusService.
/// Includes paths, plugins, compression info, and configuration details.
///
/// # Arguments
///
/// * `State(state)` - The shared AppState containing settings, DB, and paths.
///
/// # Returns
///
/// * `Ok(Json<StatusInfoResponse>)` - Success response with status data.
/// * `Err(StatusCode)` - HTTP error status (e.g., 500 for internal errors; 401 if auth fails elsewhere).
///
/// # Errors
///
/// Returns StatusCode::INTERNAL_SERVER_ERROR if status generation panics or fails (current impl assumes success).
/// Auth errors are handled by middleware before reaching this handler.
///
/// # Examples
///
/// ```ignore
/// // In an Axum app:
/// async fn app() -> Result<Json<StatusInfoResponse>, StatusCode> {
///     handle_status(State(app_state)).await
/// }
/// ```
pub async fn handle_status(
    State(state): State<AppState>,
) -> Result<Json<StatusInfoResponse>, StatusCode> {
    // Get database path
    let db_path = state
        .db
        .lock()
        .await
        .path()
        .unwrap_or("unknown")
        .to_string();

    // Use the status service to generate status info showing configured plugins
    let status_service = crate::services::status_service::StatusService::new();
    let mut cmd = state.cmd.lock().await;
    let status_info = status_service
        .generate_status(
            &mut cmd,
            &state.settings,
            state.data_dir.clone(),
            db_path.into(),
        )
        .map_err(|e| {
            log::warn!("Failed to generate status: {e}");
            StatusCode::INTERNAL_SERVER_ERROR
        })?;

    let response = StatusInfoResponse {
        success: true,
        data: Some(status_info),
        error: None,
    };

    Ok(Json(response))
}

#[derive(Debug, serde::Serialize, serde::Deserialize, utoipa::ToSchema)]
pub struct PluginsStatusResponse {
    pub meta_plugins: std::collections::HashMap<String, crate::common::status::MetaPluginInfo>,
    pub filter_plugins: Vec<crate::common::status::FilterPluginInfo>,
    pub compression: Vec<crate::common::status::CompressionInfo>,
}

#[utoipa::path(
    get,
    path = "/api/plugins/status",
    operation_id = "keep_plugins_status",
    summary = "Get plugins status",
    description = "Retrieve detailed status of all available plugins including meta, filter, and compression plugins.",
    responses(
        (status = 200, description = "Plugins status retrieved", body = ApiResponse<PluginsStatusResponse>),
        (status = 401, description = "Unauthorized"),
        (status = 500, description = "Internal server error")
    ),
    security(
        ("bearerAuth" = [])
    ),
    tag = "status"
)]
pub async fn handle_plugins_status(
    State(state): State<AppState>,
) -> Result<Json<crate::modes::server::common::ApiResponse<PluginsStatusResponse>>, StatusCode> {
    let db_path = state
        .db
        .lock()
        .await
        .path()
        .unwrap_or("unknown")
        .to_string();

    let status_service = crate::services::status_service::StatusService::new();
    let mut cmd = state.cmd.lock().await;
    let status_info = status_service
        .generate_status(
            &mut cmd,
            &state.settings,
            state.data_dir.clone(),
            db_path.into(),
        )
        .map_err(|e| {
            log::warn!("Failed to generate status: {e}");
            StatusCode::INTERNAL_SERVER_ERROR
        })?;

    let response_data = PluginsStatusResponse {
        meta_plugins: status_info.meta_plugins,
        filter_plugins: status_info.filter_plugins,
        compression: status_info.compression,
    };

    let response = crate::modes::server::common::ApiResponse::<PluginsStatusResponse> {
        success: true,
        data: Some(response_data),
        error: None,
    };

    Ok(Json(response))
}
