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::designation::{DesignationRepository, CreateDesignationPayload};

pub fn router() -> Router<AppState> {
    Router::new()
        .route("/", get(list_all_designations).post(create_designation))
        .route("/department/{dept_id}", get(list_by_department))
        .route("/{id}", patch(update_designation).delete(delete_designation))
}

async fn list_all_designations(
    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 designations = DesignationRepository::list_all(&state.pool)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;

    Ok(Json(designations))
}

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

    Ok(Json(designations))
}

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

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

async fn update_designation(
    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 designation = DesignationRepository::update(&state.pool, id, payload)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;

    Ok(Json(designation))
}

async fn delete_designation(
    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()));
    }
    DesignationRepository::delete(&state.pool, id)
        .await
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?;

    Ok(StatusCode::NO_CONTENT)
}
