//! 操作日志 API
//!
//! 提供操作日志查询接口，支持按用户、操作类型、时间范围过滤和分页：
//! - GET /api/operation-logs — 操作日志列表

use axum::extract::{Query, 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 LogQuery {
    #[allow(dead_code)]
    user_id: Option<i64>,
    action: Option<String>,
    start_time: Option<String>,
    end_time: Option<String>,
    page: Option<u32>,
    page_size: Option<u32>,
}

/// GET /api/operation-logs — 操作日志列表（分页）
///
/// 支持 user_id / action / start_time / end_time 过滤。
pub async fn list_operation_logs(
    user: CurrentUser,
    State(state): State<AppState>,
    Query(query): Query<LogQuery>,
) -> Result<Json<Value>, AppError> {
    auth::check_permission(&user, "operation_log:view")?;

    let pool = &state.mysql;
    let page = query.page.unwrap_or(1).max(1);
    let page_size = query.page_size.unwrap_or(20).min(100);
    let offset = (page - 1) * page_size;

    // 动态构建 WHERE 条件（使用 ? 占位符防止 SQL 注入）
    let mut conditions: Vec<String> = Vec::new();
    let mut bind_values: Vec<String> = Vec::new();

    if let Some(uid) = query.user_id {
        conditions.push("o.user_id = ?".to_string());
        bind_values.push(uid.to_string());
    }
    if let Some(ref act) = query.action
        && !act.is_empty()
    {
        conditions.push("o.action = ?".to_string());
        bind_values.push(act.clone());
    }
    if let Some(ref t) = query.start_time
        && !t.is_empty()
    {
        conditions.push("o.created_at >= ?".to_string());
        bind_values.push(t.clone());
    }
    if let Some(ref t) = query.end_time
        && !t.is_empty()
    {
        conditions.push("o.created_at <= ?".to_string());
        bind_values.push(t.clone());
    }

    // 追加组织过滤
    let (org_cond, org_binds) = auth::org_condition_for_logs(&user, "o");
    if !org_cond.is_empty() {
        conditions.push(org_cond.trim_start_matches(" AND ").to_string());
        bind_values.extend(org_binds);
    }

    let where_clause = if conditions.is_empty() {
        String::new()
    } else {
        format!("WHERE {}", conditions.join(" AND "))
    };

    // 查询总数
    let count_sql = format!("SELECT COUNT(*) FROM operation_logs o {}", where_clause);
    let mut count_query = sqlx::query_scalar::<_, i64>(&count_sql);
    for val in &bind_values {
        count_query = count_query.bind(val);
    }
    let total = count_query.fetch_one(pool).await?;

    // 查询列表（关联用户姓名）
    let list_sql = format!(
        r#"SELECT o.id, o.user_id, u.name AS user_name, o.action, o.target_type, o.target_id, o.detail, o.created_at
           FROM operation_logs o
           LEFT JOIN users u ON u.id = o.user_id
           {}
           ORDER BY o.id DESC
           LIMIT ? OFFSET ?"#,
        where_clause
    );

    #[derive(sqlx::FromRow)]
    struct LogRow {
        id: i64,
        user_id: i64,
        user_name: Option<String>,
        action: String,
        target_type: Option<String>,
        target_id: Option<i64>,
        detail: Option<String>,
        created_at: String,
    }

    let mut list_query = sqlx::query_as::<_, LogRow>(&list_sql);
    for val in &bind_values {
        list_query = list_query.bind(val);
    }
    let rows = list_query
        .bind(page_size)
        .bind(offset)
        .fetch_all(pool)
        .await?;

    let list: Vec<Value> = rows
        .into_iter()
        .map(|r| {
            json!({
                "id": r.id,
                "user_id": r.user_id,
                "user_name": r.user_name.unwrap_or_else(|| format!("#{}", r.user_id)),
                "action": r.action,
                "target_type": r.target_type,
                "target_id": r.target_id,
                "detail": r.detail,
                "created_at": r.created_at,
            })
        })
        .collect();

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