use axum::Extension;
use axum::Json;
use axum::extract::{FromRef, Path, State};
use sea_orm::{ConnectionTrait, DatabaseBackend, Statement};
use serde_json::{Value, json};
use uuid::Uuid;

use erp_core::error::AppError;
use erp_core::rbac::require_permission;
use erp_core::types::{ApiResponse, TenantContext};

use crate::state::AppState;

/// POST /api/v1/admin/tenants/:id/rotate-key
/// 密钥轮换 — 生成新 DEK，持久化到 tenant_crypto_keys，使缓存失效
pub async fn rotate_tenant_key<S>(
    State(state): State<AppState>,
    Extension(ctx): Extension<TenantContext>,
    Path(tenant_id): Path<Uuid>,
) -> Result<Json<ApiResponse<Value>>, AppError>
where
    AppState: FromRef<S>,
    S: Clone + Send + Sync + 'static,
{
    require_permission(&ctx, "tenant.manage")?;

    // 读取当前最大版本号
    let max_version: Option<i32> = {
        let row = state.db.query_one(Statement::from_sql_and_values(
            DatabaseBackend::Postgres,
            "SELECT COALESCE(MAX(key_version), 0) as v FROM tenant_crypto_keys WHERE tenant_id = $1 AND deleted_at IS NULL",
            [tenant_id.into()],
        )).await.map_err(|e| AppError::Internal(format!("查询密钥版本失败: {}", e)))?;
        row.and_then(|r| r.try_get_by_index::<i32>(0).ok())
    };
    let current_version = max_version.unwrap_or(0);
    let new_version = current_version + 1;

    // 将旧版本标记为不活跃
    state.db.execute(Statement::from_sql_and_values(
        DatabaseBackend::Postgres,
        "UPDATE tenant_crypto_keys SET is_active = false, updated_at = now() WHERE tenant_id = $1 AND is_active = true AND deleted_at IS NULL",
        [tenant_id.into()],
    )).await.map_err(|e| AppError::Internal(format!("停用旧 DEK 失败: {}", e)))?;

    // 生成新 DEK 并用 KEK 加密
    let kek = state.pii_crypto.kek();
    let (_new_dek, encrypted_dek) = erp_core::crypto::DekManager::generate_new_dek(kek)
        .map_err(|e| AppError::Internal(format!("生成新 DEK 失败: {}", e)))?;

    // 持久化新 DEK
    let new_id = Uuid::now_v7();
    state.db.execute(Statement::from_sql_and_values(
        DatabaseBackend::Postgres,
        "INSERT INTO tenant_crypto_keys (id, tenant_id, encrypted_dek, key_version, is_active, created_at, updated_at, version) VALUES ($1, $2, $3, $4, true, now(), now(), 1)",
        [new_id.into(), tenant_id.into(), encrypted_dek.into(), new_version.into()],
    )).await.map_err(|e| AppError::Internal(format!("存储新 DEK 失败: {}", e)))?;

    // 使 DEK 缓存失效
    state.pii_crypto.invalidate_dek(tenant_id);

    tracing::info!(
        tenant_id = %tenant_id,
        old_version = current_version,
        new_version = new_version,
        "密钥轮换完成（新 DEK 已持久化，缓存已清除）"
    );

    Ok(Json(ApiResponse::ok(json!({
        "message": "密钥轮换已完成",
        "tenant_id": tenant_id,
        "old_version": current_version,
        "new_version": new_version,
        "note": "后台重加密任务需要单独触发，旧数据仍可用旧 DEK 解密"
    }))))
}
