//! 角色管理 API
//!
//! 提供角色的 CRUD 操作及角色权限分配接口：
//! - GET    /api/roles              — 角色列表
//! - POST   /api/roles              — 创建角色
//! - PUT    /api/roles/:id          — 更新角色
//! - DELETE /api/roles/:id          — 删除角色
//! - PUT    /api/roles/:id/permissions — 设置角色权限
//! - GET    /api/permissions        — 权限码列表

use axum::extract::{Path, State};
use axum::http::StatusCode;
use axum::Json;
use serde::Deserialize;
use serde_json::{json, Value};

use crate::error::AppError;
use crate::middleware::auth::CurrentUser;
use crate::tcp::commands::AppState;

/// 创建/更新角色请求体
#[derive(Debug, Deserialize)]
pub(crate) struct RoleInput {
    name: String,
    description: Option<String>,
}

/// 设置角色权限请求体
#[derive(Debug, Deserialize)]
pub(crate) struct SetPermissionsInput {
    /// 权限码列表
    permission_codes: Vec<String>,
}

/// GET /api/roles — 获取所有角色及其权限码
pub async fn list_roles(
    _user: CurrentUser,
    State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
    let pool = &state.mysql;
    // 查询所有角色
    let roles: Vec<(i64, String, Option<String>)> = sqlx::query_as(
        "SELECT id, name, description FROM roles ORDER BY id"
    )
    .fetch_all(pool)
    .await?;

    let mut result = Vec::new();
    for (id, name, description) in roles {
        // 查询该角色的权限码
        let perm_codes: Vec<(String,)> = sqlx::query_as(
            r#"
            SELECT p.code FROM permissions p
            INNER JOIN role_permissions rp ON rp.permission_id = p.id
            WHERE rp.role_id = ?
            ORDER BY p.code
            "#
        )
        .bind(id)
        .fetch_all(pool)
        .await?;

        result.push(json!({
            "id": id,
            "name": name,
            "description": description,
            "permission_codes": perm_codes.into_iter().map(|(c,)| c).collect::<Vec<_>>(),
        }));
    }

    Ok(Json(json!({ "code": 0, "data": result, "message": "ok" })))
}

/// POST /api/roles — 创建角色
pub async fn create_role(
    user: CurrentUser,
    State(state): State<AppState>,
    Json(input): Json<RoleInput>,
) -> Result<(StatusCode, Json<Value>), AppError> {
    let pool = &state.mysql;
    // 校验权限
    crate::middleware::auth::check_permission(&user, "role:create")?;

    if input.name.is_empty() || input.name.len() > 50 {
        return Err(AppError::BadRequest("角色名长度需在1-50字符之间".into()));
    }

    let result = sqlx::query(
        "INSERT INTO roles (name, description) VALUES (?, ?)"
    )
    .bind(&input.name)
    .bind(&input.description)
    .execute(pool)
    .await;

    match result {
        Ok(r) => {
            let id = r.last_insert_id() as i64;
            Ok((StatusCode::CREATED, Json(json!({
                "code": 0,
                "data": { "id": id, "name": input.name, "description": input.description },
                "message": "创建成功"
            }))))
        }
        Err(e) => {
            if e.to_string().contains("Duplicate") {
                Err(AppError::BadRequest(format!("角色名 '{}' 已存在", input.name)))
            } else {
                Err(AppError::Database(e))
            }
        }
    }
}

/// PUT /api/roles/:id — 更新角色
pub async fn update_role(
    user: CurrentUser,
    State(state): State<AppState>,
    Path(id): Path<i64>,
    Json(input): Json<RoleInput>,
) -> Result<Json<Value>, AppError> {
    let pool = &state.mysql;
    crate::middleware::auth::check_permission(&user, "role:edit")?;

    if input.name.is_empty() || input.name.len() > 50 {
        return Err(AppError::BadRequest("角色名长度需在1-50字符之间".into()));
    }

    let result = sqlx::query(
        "UPDATE roles SET name = ?, description = ? WHERE id = ?"
    )
    .bind(&input.name)
    .bind(&input.description)
    .bind(id)
    .execute(pool)
    .await?;

    if result.rows_affected() == 0 {
        return Err(AppError::NotFound("角色不存在".into()));
    }

    Ok(Json(json!({ "code": 0, "data": null, "message": "更新成功" })))
}

/// DELETE /api/roles/:id — 删除角色
pub async fn delete_role(
    user: CurrentUser,
    State(state): State<AppState>,
    Path(id): Path<i64>,
) -> Result<Json<Value>, AppError> {
    let pool = &state.mysql;
    crate::middleware::auth::check_permission(&user, "role:delete")?;

    // 检查是否有用户正在使用该角色
    let count: (i64,) = sqlx::query_as(
        "SELECT COUNT(*) FROM user_roles WHERE role_id = ?"
    )
    .bind(id)
    .fetch_one(pool)
    .await?;

    if count.0 > 0 {
        return Err(AppError::BadRequest(
            format!("该角色下还有 {} 个用户，请先移除", count.0)
        ));
    }

    let result = sqlx::query("DELETE FROM roles WHERE id = ?")
        .bind(id)
        .execute(pool)
        .await?;

    if result.rows_affected() == 0 {
        return Err(AppError::NotFound("角色不存在".into()));
    }

    Ok(Json(json!({ "code": 0, "data": null, "message": "删除成功" })))
}

/// PUT /api/roles/:id/permissions — 设置角色权限（全量替换）
pub async fn set_role_permissions(
    user: CurrentUser,
    State(state): State<AppState>,
    Path(role_id): Path<i64>,
    Json(input): Json<SetPermissionsInput>,
) -> Result<Json<Value>, AppError> {
    let pool = &state.mysql;
    crate::middleware::auth::check_permission(&user, "role:edit")?;

    // 检查角色是否存在
    let role_exists: Option<(i64,)> = sqlx::query_as(
        "SELECT id FROM roles WHERE id = ?"
    )
    .bind(role_id)
    .fetch_optional(pool)
    .await?;

    if role_exists.is_none() {
        return Err(AppError::NotFound("角色不存在".into()));
    }

    // 删除旧权限
    sqlx::query("DELETE FROM role_permissions WHERE role_id = ?")
        .bind(role_id)
        .execute(pool)
        .await?;

    // 批量插入新权限
    for code in &input.permission_codes {
        let perm: Option<(i64,)> = sqlx::query_as(
            "SELECT id FROM permissions WHERE code = ?"
        )
        .bind(code)
        .fetch_optional(pool)
        .await?;

        if let Some((perm_id,)) = perm {
            sqlx::query(
                "INSERT INTO role_permissions (role_id, permission_id) VALUES (?, ?)"
            )
            .bind(role_id)
            .bind(perm_id)
            .execute(pool)
            .await?;
        }
    }

    Ok(Json(json!({ "code": 0, "data": null, "message": "权限设置成功" })))
}

/// GET /api/permissions — 获取所有权限码列表
pub async fn list_permissions(
    _user: CurrentUser,
    State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
    let pool = &state.mysql;
    let perms: Vec<(i64, String, String)> = sqlx::query_as(
        "SELECT id, code, name FROM permissions ORDER BY code"
    )
    .fetch_all(pool)
    .await?;

    let data: Vec<Value> = perms.into_iter().map(|(id, code, name)| {
        json!({ "id": id, "code": code, "name": name })
    }).collect();

    Ok(Json(json!({ "code": 0, "data": data, "message": "ok" })))
}
