//! 审批 reason 拼装:工具调用 → 可读审批文案(含项目/任务 label 解析)。
//!
//! 拆自 audit.rs(本批 helper 抽离,行为零变更):
//! - `resolve_project_label` / `resolve_task_label`:id → 可读标签(三臂分流)
//! - `build_approval_reason`:按工具名 + args 拼审批 reason
//!
//! 仅被 `process_tool_calls`(audit/mod.rs)调用,无外部调用方。

use std::sync::Arc;

use df_ai::ai_tools::RiskLevel;
use df_storage::crud::{ProjectRepo, TaskRepo};
use df_storage::db::Database;

/// 查项目可读标签:id → "「项目名」(id=x)"。
///
/// AR-3：审批卡片需显示对象名而非裸 id（用户反馈"只返回 ID 不知道是什么数据"）。
/// 三臂区分：
/// - Ok(Some) → 项目名标签
/// - Ok(None) → "项目已不存在"（真不存在，项目已彻底清除/外部 id）
/// - Err      → 裸 id 回退 + warn 日志（DB 故障/锁/连接断，不误报"已不存在"误导用户）
pub(super) async fn resolve_project_label(db: &Arc<Database>, id: &str) -> String {
    if id.is_empty() {
        return String::new();
    }
    let repo = ProjectRepo::new(db);
    match repo.get_by_id(id).await {
        Ok(Some(p)) => format!("「{}」(id={})", p.name, id),
        Ok(None) => format!("(项目已不存在, id={})", id),
        Err(e) => {
            tracing::warn!("resolve_project_label: 查询项目 id={} 失败,回退裸 id: {}", id, e);
            format!("(id={})", id)
        }
    }
}

/// 查任务可读标签:id → "「任务标题」(id=x)",对齐 resolve_project_label 三臂语义。
///
/// advance_task 审批卡的 id 是 task_id,原 build_approval_reason 把 "id"
/// 统一走 resolve_project_label(查 projects 表),误把任务 id 当项目 id 解析,永远落到
/// "项目已不存在"。本方法改查 tasks 表,与 resolve_project_label 同 Ok(None)/Err 分流。
pub(super) async fn resolve_task_label(db: &Arc<Database>, id: &str) -> String {
    if id.is_empty() {
        return String::new();
    }
    let repo = TaskRepo::new(db);
    match repo.get_by_id(id).await {
        Ok(Some(t)) => format!("「{}」(id={})", t.title, id),
        Ok(None) => format!("(任务已不存在, id={})", id),
        Err(e) => {
            tracing::warn!("resolve_task_label: 查询任务 id={} 失败,回退裸 id: {}", id, e);
            format!("(id={})", id)
        }
    }
}

/// 拼审批 reason：按工具名 + args 取可读字段，让用户知道"审批要做什么"。
///
/// 主要审批工具特化（带对象名/标识）：
/// - delete_project/restore_project/purge_project → 查项目名拼"删除项目「名」(id=x)"
/// - update_project → 查项目名 + field
/// - bind_directory → path + 查项目名
/// - create_task → title + 查 project_id 项目名；create_project → name；create_idea → title
/// - run_workflow → name
/// args 无可读字段或工具未特化时，fallback 原 risk 模板（含风险等级提示）。
pub(super) async fn build_approval_reason(
    tool_name: &str,
    args: &serde_json::Value,
    risk_level: RiskLevel,
    db: &Arc<Database>,
) -> String {
    let s = |key: &str| args.get(key).and_then(|v| v.as_str()).unwrap_or("");
    // 优先级：tool_display_hint(轻量标签) → display_hint_for_tool(模板填充) → 硬编码 fallback
    let detail = if let Some(hint) = super::super::tool_registry::tool_display_hint(tool_name) {
        // 轻量命中：直接用中文动作前缀 + 风险后缀（不含参数细节）
        hint.to_string()
    } else if let Some((template, keys)) = super::super::tool_registry::display_hint_for_tool(tool_name) {
        // 按 keys 列表取参数值；含 "id"/"project_id" 的值走 resolve_project_label 解析
        let mut values = Vec::with_capacity(keys.len());
        for &key in keys {
            let val = s(key);
            if val.is_empty() { values.clear(); break; }
            match key {
                // advance_task 的 id 是 task_id(非项目 id),改查 tasks 表,避免误报"项目已不存在"
                "id" if tool_name == "advance_task" => values.push(resolve_task_label(db, &val).await),
                "id" | "project_id" => values.push(resolve_project_label(db, &val).await),
                _ => values.push(val.to_string()),
            }
        }
        // 任一关键参数为空则整条 fallback 为空串（与原行为一致）
        if values.is_empty() {
            String::new()
        } else {
            // 模板 {} 占位符按位置填充
            let mut result = template.to_string();
            for v in &values {
                result = result.replacen("{}", v, 1);
            }
            result
        }
    } else {
        // fallback：原有完整硬编码逻辑（保持行为不变）
        match tool_name {
            "delete_project" => {
                let id = s("id");
                if !id.is_empty() { format!("删除项目{}", resolve_project_label(db, id).await) } else { String::new() }
            }
            "restore_project" => {
                let id = s("id");
                if !id.is_empty() { format!("从回收站恢复项目{}", resolve_project_label(db, id).await) } else { String::new() }
            }
            "purge_project" => {
                let id = s("id");
                if !id.is_empty() { format!("永久删除项目及关联数据，不可恢复{}", resolve_project_label(db, id).await) } else { String::new() }
            }
            "update_project" => {
                let id = s("id");
                let field = s("field");
                if !id.is_empty() {
                    format!("修改项目{}字段「{}」", resolve_project_label(db, id).await, field)
                } else if !field.is_empty() {
                    format!("修改项目字段「{}」", field)
                } else { String::new() }
            }
            "bind_directory" => {
                let id = s("id");
                let path = s("path");
                if !path.is_empty() && !id.is_empty() {
                    format!("绑定目录：{}（项目{}）", path, resolve_project_label(db, id).await)
                } else if !path.is_empty() {
                    format!("绑定目录：{}", path)
                } else { String::new() }
            }
            "create_task" => {
                let title = s("title");
                let pid = s("project_id");
                if !title.is_empty() && !pid.is_empty() {
                    format!("创建任务：{}（项目{}）", title, resolve_project_label(db, pid).await)
                } else if !title.is_empty() {
                    format!("创建任务：{}", title)
                } else { String::new() }
            }
            "create_project" => {
                let name = s("name");
                if !name.is_empty() { format!("创建项目：「{}」", name) } else { String::new() }
            }
            "create_idea" => {
                let title = s("title");
                if !title.is_empty() { format!("捕获灵感：{}", title) } else { String::new() }
            }
            _ => String::new(),
        }
    };
    if detail.is_empty() {
        // fallback：无可读字段，保留风险等级提示模板
        match risk_level {
            RiskLevel::High => "高风险操作，必须人工批准".to_string(),
            _ => "创建操作，请确认是否执行".to_string(),
        }
    } else {
        // 拼上风险等级后缀（高风险标注，便于用户权衡）
        match risk_level {
            RiskLevel::High => format!("{}（高风险，需人工批准）", detail),
            _ => format!("{}（请确认是否执行）", detail),
        }
    }
}
