//! 用户权限管理 API
//!
//! 提供用户角色分配和权限范围配置：
//! - GET  /api/users/:id/permissions — 获取用户权限（含角色和权限码）
//! - PUT  /api/users/:id/roles       — 设置用户角色
//! - PUT  /api/users/:id/scopes      — 设置用户权限范围（组织/项目/设备级）
//! - GET  /api/users/:id/scopes      — 获取用户权限范围

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

use crate::error::AppError;
use crate::middleware::auth::{self, CurrentUser};
use crate::commands::AppState;

/// 设置用户角色请求体
#[derive(Debug, Deserialize)]
pub(crate) struct SetRolesInput {
    /// 角色ID列表
    role_ids: Vec<i64>,
}

/// 权限范围条目
#[derive(Debug, Deserialize)]
pub(crate) struct ScopeEntry {
    /// 范围类型：1组织 2项目 3设备
    scope_type: i8,
    /// 对应的组织/项目/设备ID
    scope_id: i64,
    /// 权限类型：1查看 2操作
    permission_type: i8,
}

/// 设置用户权限范围请求体
#[derive(Debug, Deserialize)]
pub(crate) struct SetScopesInput {
    scopes: Vec<ScopeEntry>,
}

/// GET /api/users/:id/permissions — 获取用户权限详情
#[allow(clippy::type_complexity)]
pub async fn get_user_permissions(
    current_user: CurrentUser,
    State(state): State<AppState>,
    Path(user_id): Path<i64>,
) -> Result<Json<Value>, AppError> {
    let pool = &state.mysql;
    auth::check_permission(&current_user, "user:view")?;

    // 查询用户基本信息
    let user_row: Option<(i64, String, Option<String>, i32, Option<i64>)> = sqlx::query_as(
        "SELECT id, name, phone, role, organization_id FROM users WHERE id = ?"
    )
    .bind(user_id)
    .fetch_optional(pool)
    .await?;

    let user_row = user_row.ok_or_else(|| AppError::NotFound("用户不存在".into()))?;

    // 查询用户角色
    let roles: Vec<(i64, String, Option<String>)> = sqlx::query_as(
        r#"
        SELECT r.id, r.name, r.description
        FROM roles r
        INNER JOIN user_roles ur ON ur.role_id = r.id
        WHERE ur.user_id = ?
        ORDER BY r.id
        "#
    )
    .bind(user_id)
    .fetch_all(pool)
    .await?;

    // 查询用户权限码
    let perm_codes = auth::load_user_permissions(pool, user_id).await?;

    // 查询用户权限范围
    let scopes: Vec<(i64, i8, i64, i8)> = sqlx::query_as(
        "SELECT id, scope_type, scope_id, permission_type FROM user_scopes WHERE user_id = ?"
    )
    .bind(user_id)
    .fetch_all(pool)
    .await?;

    let roles_data: Vec<Value> = roles.into_iter().map(|(id, name, desc)| {
        json!({ "id": id, "name": name, "description": desc })
    }).collect();

    let scopes_data: Vec<Value> = scopes.into_iter().map(|(id, st, sid, pt)| {
        json!({
            "id": id,
            "scope_type": st,
            "scope_id": sid,
            "permission_type": pt,
        })
    }).collect();

    Ok(Json(json!({
        "code": 0,
        "data": {
            "user_id": user_row.0,
            "name": user_row.1,
            "phone": user_row.2,
            "role_level": user_row.3,
            "organization_id": user_row.4,
            "roles": roles_data,
            "permission_codes": perm_codes,
            "scopes": scopes_data,
        },
        "message": "ok"
    })))
}

/// PUT /api/users/:id/roles — 设置用户角色（全量替换）
pub async fn set_user_roles(
    current_user: CurrentUser,
    State(state): State<AppState>,
    Path(user_id): Path<i64>,
    Json(input): Json<SetRolesInput>,
) -> Result<Json<Value>, AppError> {
    let pool = &state.mysql;
    auth::check_permission(&current_user, "user:edit")?;

    // 不允许修改自己的角色
    if user_id == current_user.user_id {
        return Err(AppError::BadRequest("不能修改自己的角色".into()));
    }

    // 检查用户是否存在
    let user_exists: Option<(i64,)> = sqlx::query_as(
        "SELECT id FROM users WHERE id = ?"
    )
    .bind(user_id)
    .fetch_optional(pool)
    .await?;

    if user_exists.is_none() {
        return Err(AppError::NotFound("用户不存在".into()));
    }

    // 删除旧角色
    sqlx::query("DELETE FROM user_roles WHERE user_id = ?")
        .bind(user_id)
        .execute(pool)
        .await?;

    // 插入新角色
    for role_id in &input.role_ids {
        // 验证角色存在
        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_some() {
            sqlx::query(
                "INSERT INTO user_roles (user_id, role_id) VALUES (?, ?)"
            )
            .bind(user_id)
            .bind(role_id)
            .execute(pool)
            .await?;
        }
    }

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

/// PUT /api/users/:id/scopes — 设置用户权限范围（全量替换）
pub async fn set_user_scopes(
    current_user: CurrentUser,
    State(state): State<AppState>,
    Path(user_id): Path<i64>,
    Json(input): Json<SetScopesInput>,
) -> Result<Json<Value>, AppError> {
    let pool = &state.mysql;
    auth::check_permission(&current_user, "user:edit")?;

    // 校验 scope_type 和 permission_type 范围
    for scope in &input.scopes {
        if ![1, 2, 3].contains(&scope.scope_type) {
            return Err(AppError::BadRequest(
                "scope_type 必须为 1(组织)/2(项目)/3(设备)".into()
            ));
        }
        if ![1, 2].contains(&scope.permission_type) {
            return Err(AppError::BadRequest(
                "permission_type 必须为 1(查看)/2(操作)".into()
            ));
        }
    }

    // 删除旧范围
    sqlx::query("DELETE FROM user_scopes WHERE user_id = ?")
        .bind(user_id)
        .execute(pool)
        .await?;

    // 插入新范围
    for scope in &input.scopes {
        sqlx::query(
            "INSERT INTO user_scopes (user_id, scope_type, scope_id, permission_type) VALUES (?, ?, ?, ?)"
        )
        .bind(user_id)
        .bind(scope.scope_type)
        .bind(scope.scope_id)
        .bind(scope.permission_type)
        .execute(pool)
        .await?;
    }

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

/// GET /api/users/:id/scopes — 获取用户权限范围
pub async fn get_user_scopes(
    current_user: CurrentUser,
    State(state): State<AppState>,
    Path(user_id): Path<i64>,
) -> Result<Json<Value>, AppError> {
    let pool = &state.mysql;
    auth::check_permission(&current_user, "user:view")?;

    let scopes: Vec<(i64, i8, i64, i8)> = sqlx::query_as(
        "SELECT id, scope_type, scope_id, permission_type FROM user_scopes WHERE user_id = ?"
    )
    .bind(user_id)
    .fetch_all(pool)
    .await?;

    let data: Vec<Value> = scopes.into_iter().map(|(id, st, sid, pt)| {
        json!({
            "id": id,
            "scope_type": st,
            "scope_id": sid,
            "permission_type": pt,
        })
    }).collect();

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