use crate::AppState;
use axum::{
    extract::{Path, State},
    http::StatusCode,
    response::IntoResponse,
    routing::{get, patch},
    Json, Router,
};
use contracts::auth_middleware::{AuthUser, require_admin};
use uuid::Uuid;
use db::models::department::{DepartmentRepository, CreateDepartmentPayload};

pub fn router() -> Router<AppState> {
    Router::new()
        .route("/", get(list_departments).post(create_department))
        .route("/{id}", patch(update_department).delete(delete_department))
}

async fn list_departments(
    auth: AuthUser,
    State(state): State<AppState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
    if let Err(_) = require_admin(&auth) {
        return Err((StatusCode::FORBIDDEN, "Insufficient permissions".to_string()));
    }
    let departments = DepartmentRepository::list(&state.pool)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;

    Ok(Json(departments))
}

async fn create_department(
    auth: AuthUser,
    State(state): State<AppState>,
    Json(payload): Json<CreateDepartmentPayload>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
    if let Err(_) = require_admin(&auth) {
        return Err((StatusCode::FORBIDDEN, "Insufficient permissions".to_string()));
    }
    let department = DepartmentRepository::create(&state.pool, payload)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;

    Ok((StatusCode::CREATED, Json(department)))
}

async fn update_department(
    auth: AuthUser,
    Path(id): Path<Uuid>,
    State(state): State<AppState>,
    Json(payload): Json<serde_json::Value>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
    if let Err(_) = require_admin(&auth) {
        return Err((StatusCode::FORBIDDEN, "Insufficient permissions".to_string()));
    }
    let department = DepartmentRepository::update(&state.pool, id, payload)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;

    Ok(Json(department))
}

async fn delete_department(
    auth: AuthUser,
    Path(id): Path<Uuid>,
    State(state): State<AppState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
    if let Err(_) = require_admin(&auth) {
        return Err((StatusCode::FORBIDDEN, "Insufficient permissions".to_string()));
    }
    DepartmentRepository::delete(&state.pool, id)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;

    Ok(StatusCode::NO_CONTENT)
}
