# -*- coding: utf-8 -*-
"""
配置模块 - LLM 预设和 System Prompt

包含:
- LLM_PRESETS: 各 LLM 提供商的配置
- SYSTEM_PROMPT: Agent 的系统提示词
- TOOL_DESCRIPTIONS: 工具的中文描述（用于确认消息）
- ERROR_SUGGESTIONS: 错误恢复建议映射
"""

from typing import Dict

# =============================================================================
# LLM 预设配置
# =============================================================================

LLM_PRESETS = {
    "qwen": {
        "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
        "env_key": "DASHSCOPE_API_KEY",
        "default_model": "qwen-plus"
    },
    "deepseek": {
        "base_url": "https://api.deepseek.com/v1",
        "env_key": "DEEPSEEK_API_KEY",
        "default_model": "deepseek-chat"
    },
    "zhipu": {
        "base_url": "https://open.bigmodel.cn/api/paas/v4",
        "env_key": "ZHIPU_API_KEY",
        "default_model": "glm-4-flash"
    },
    "openai": {
        "base_url": "https://api.openai.com/v1",
        "env_key": "OPENAI_API_KEY",
        "default_model": "gpt-4o-mini"
    }
}


# =============================================================================
# System Prompt
# =============================================================================

SYSTEM_PROMPT = """你是一个 SAP2000 结构分析软件的智能助手，专门帮助结构工程师高效使用 SAP2000。

## 核心能力

### 1. 模型查询
- 查询节点、杆件、面单元、索单元、连接单元信息
- 查询组、截面、材料、荷载模式、荷载工况、组合
- 获取选中对象、数据库表格

### 2. 模型创建与修改
- 创建/删除/修改节点、杆件、面单元、索单元、连接单元
- 设置节点约束、杆件端部释放、面单元截面
- 创建组并添加对象到组
- 创建刚性隔板约束

### 3. 荷载操作
- 添加/删除节点荷载（力、力矩）
- 添加/删除杆件均布荷载、集中荷载
- 添加/删除面单元均布荷载
- 创建/删除荷载模式

### 4. 分析与设计
- 运行结构分析
- 运行钢结构设计、混凝土设计
- 查看应力比、验算结果

### 5. 结果查询
- 节点位移、反力
- 杆件内力（轴力、剪力、弯矩）
- 模态周期、振型、质量参与系数
- 基底反力

### 6. 统计与绘图
- 统计用钢量（按截面、组分类）
- 统计用索量
- 绑制柱状图、饼图、折线图

### 7. 编辑操作
- 移动、线性复制、镜像复制、环形复制
- 分割杆件、合并节点

### 8. 批量操作
- batch_set_section: 批量修改截面
- batch_add_distributed_load: 批量添加均布荷载
- batch_set_restraint: 批量设置节点约束

### 9. 文件操作
- new_model: 新建空白模型
- open_model: 打开模型文件
- save_model: 保存模型
- unlock_model: 解锁模型

### 10. 选择操作
- select_all: 选择所有对象
- select_group: 按组选择
- select_by_property: 按截面/材料选择
- clear_selection: 清除选择

### 11. 知识库搜索
- search_sap_docs: 搜索 SAP2000 API 文档，获取详细用法

## 工作流程建议

### 查看结果的正确顺序
1. 先运行分析 (run_analysis)
2. 再运行设计 (run_steel_design)
3. 最后查看应力比 (get_stress_ratios)

### 常见任务流程
- **查询模型概况**: get_model_info → get_section_list → get_material_list
- **检查设计结果**: run_analysis → run_steel_design → get_stress_ratios
- **统计用钢量**: get_steel_usage → draw_chart (绘制饼图或柱状图)
- **批量修改截面**: get_section_list → batch_set_section

## 回复规范

1. **语言**: 使用中文回复
2. **格式**: 使用 Markdown 格式（表格、列表、代码块）
3. **数据展示**: 数据较多时用表格，简洁明了
4. **图片处理**: 工具返回的 "__image__" 字段不要输出，图片会自动显示
5. **错误处理**: 遇到错误时给出明确的解决建议

## 注意事项

1. 修改模型的操作会先询问用户确认
2. 模型锁定时需要先解锁 (unlock_model)
3. 不确定 API 用法时，使用 search_sap_docs 搜索文档
4. 批量操作比逐个操作更高效，优先使用批量工具

## 示例对话

### 示例1：批量修改截面
用户: 把"上弦杆"组的截面改成 H400x200x8x12
助手: 我将批量修改"上弦杆"组的杆件截面。
→ 调用 batch_set_section(group_name="上弦杆", section_name="H400x200x8x12")
结果: 已成功修改 X 根杆件的截面。

### 示例2：设计验算流程
用户: 帮我做一下钢结构设计验算
助手: 好的，我将按以下步骤执行设计验算：
1. 运行结构分析
2. 运行钢结构设计
3. 获取应力比结果
→ 调用 run_analysis()
→ 调用 run_steel_design()
→ 调用 get_stress_ratios()
结果: [展示应力比表格]

### 示例3：查询内力
用户: 1号杆件在恒载下的最大弯矩是多少
助手: 我来查询1号杆件在恒载工况下的内力。
→ 调用 get_frame_forces(frame_name="1", load_case="DEAD")
结果: 1号杆件最大弯矩 M3 = XXX kN·m，位于相对位置 0.5 处。

### 示例4：统计用钢量并绘图
用户: 统计一下用钢量，按截面分类画个饼图
助手: 我将统计用钢量并绑制饼图。
→ 调用 get_steel_usage(group_by="section")
→ 调用 draw_chart(chart_type="pie", ...)
结果: [展示饼图]

### 示例5：添加荷载
用户: 给"楼面梁"组的所有杆件加上 5kN/m 的活载
助手: 我将为"楼面梁"组批量添加均布荷载。
→ 调用 batch_add_distributed_load(group_name="楼面梁", load_pattern="LIVE", value=-5, direction="Gravity")
结果: 已为 X 根杆件添加荷载。

当前已连接到用户本地的 SAP2000 软件。"""


# =============================================================================
# 工具描述（用于确认消息）
# =============================================================================

TOOL_DESCRIPTIONS = {
    # 节点操作
    "create_point": "创建节点",
    "delete_point": "删除节点",
    "set_point_restraint": "设置节点约束",
    "modify_joint_coordinate": "修改节点坐标",
    "batch_modify_joints": "批量修改节点坐标",
    "merge_points": "合并节点",
    # 杆件操作
    "create_frame": "创建杆件",
    "delete_frame": "删除杆件",
    "set_frame_section": "修改杆件截面",
    "set_frame_release": "设置杆件端部释放",
    "divide_frame": "分割杆件",
    # 面单元操作
    "create_area": "创建面单元",
    "delete_area": "删除面单元",
    "set_area_section": "设置面单元截面",
    "add_area_to_group_tool": "添加面单元到组",
    # 索/连接单元操作
    "create_cable": "创建索单元",
    "delete_cable": "删除索单元",
    "create_link": "创建连接单元",
    "delete_link": "删除连接单元",
    # 荷载操作
    "add_point_load": "添加节点荷载",
    "delete_point_load": "删除节点荷载",
    "add_frame_distributed_load": "添加杆件均布荷载",
    "add_frame_point_load": "添加杆件集中荷载",
    "delete_frame_load": "删除杆件荷载",
    "add_area_load": "添加面荷载",
    "delete_area_load": "删除面荷载",
    "create_load_pattern": "创建荷载模式",
    "delete_load_pattern": "删除荷载模式",
    # 分析设计
    "run_analysis": "运行分析",
    "run_steel_design": "运行钢结构设计",
    # 组操作
    "create_group": "创建组",
    "add_frame_to_group": "添加杆件到组",
    "add_selected_to_group": "添加选中对象到组",
    # 文件操作
    "save_model": "保存模型",
    "unlock_model": "解锁模型",
    "new_model": "新建模型",
    "open_model": "打开模型",
    # 编辑操作
    "move_selected_objects": "移动选中对象",
    "replicate_linear": "线性复制",
    "replicate_mirror": "镜像复制",
    "replicate_radial": "环形复制",
    # 约束操作
    "create_diaphragm_constraint": "创建刚性隔板约束",
    "assign_point_constraint": "分配节点约束",
    # 撤回操作
    "undo_last_operation": "撤回上一步操作",
    "clear_operation_history": "清空操作历史",
    # 批量操作
    "batch_set_section": "批量修改截面",
    "batch_add_distributed_load": "批量添加均布荷载",
    "batch_set_restraint": "批量设置节点约束",
    # 选择操作
    "select_all": "选择所有对象",
    "clear_selection": "清除选择",
    "select_group": "按组选择",
    "select_by_property": "按属性选择",
}


# =============================================================================
# 错误建议映射 - 提供智能错误恢复建议
# =============================================================================

ERROR_SUGGESTIONS: Dict[str, str] = {
    # 模型状态错误
    "模型已锁定": "模型处于锁定状态，请先调用 unlock_model 解锁模型后再试。",
    "model is locked": "模型处于锁定状态，请先调用 unlock_model 解锁模型后再试。",
    "locked": "模型可能已锁定，建议先调用 unlock_model 解锁。",
    
    # 分析相关错误
    "分析未运行": "请先调用 run_analysis 运行结构分析，然后再查询结果。",
    "no results": "没有分析结果，请先调用 run_analysis 运行分析。",
    "analysis has not been run": "分析尚未运行，请先调用 run_analysis。",
    "设计未运行": "请先调用 run_steel_design 运行钢结构设计。",
    
    # 对象不存在错误
    "未找到截面": "指定的截面不存在，建议先调用 get_section_list 查看可用截面列表。",
    "section not found": "截面不存在，请调用 get_section_list 查看可用截面。",
    "未找到组": "指定的组不存在，建议先调用 get_group_list 查看可用组列表。",
    "group not found": "组不存在，请调用 get_group_list 查看可用组。",
    "未找到杆件": "指定的杆件不存在，建议先调用 get_frame_list 查看杆件列表。",
    "frame not found": "杆件不存在，请调用 get_frame_list 查看杆件列表。",
    "未找到节点": "指定的节点不存在，建议先调用 get_point_list 查看节点列表。",
    "point not found": "节点不存在，请调用 get_point_list 查看节点列表。",
    "未找到荷载模式": "指定的荷载模式不存在，建议先调用 get_load_pattern_list 查看可用荷载模式。",
    "load pattern not found": "荷载模式不存在，请调用 get_load_pattern_list 查看。",
    "未找到工况": "指定的荷载工况不存在，建议先调用 get_load_case_list 查看可用工况。",
    
    # 连接错误
    "连接失败": "与 SAP2000 的连接已断开，请确保 SAP2000 正在运行，然后调用 check_connection 检查连接。",
    "connection failed": "连接失败，请确保 SAP2000 正在运行。",
    "sap2000 未启动": "SAP2000 未启动，请先启动 SAP2000 软件。",
    "com error": "COM 通信错误，请确保 SAP2000 正在运行且未被其他程序占用。",
    
    # 参数错误
    "参数错误": "参数格式不正确，请检查输入参数。",
    "invalid parameter": "参数无效，请检查参数类型和取值范围。",
    "参数不能为空": "必填参数缺失，请提供完整的参数。",
    
    # 权限错误
    "没有选中对象": "当前没有选中任何对象，请先使用 select_group 或 select_by_property 选择对象。",
    "no selection": "没有选中对象，请先选择要操作的对象。",
}


def get_error_suggestion(error_message: str) -> str:
    """
    根据错误消息获取恢复建议
    
    Args:
        error_message: 错误消息
        
    Returns:
        恢复建议，如果没有匹配则返回空字符串
    """
    error_lower = error_message.lower()
    for key, suggestion in ERROR_SUGGESTIONS.items():
        if key.lower() in error_lower:
            return suggestion
    return ""


def get_tool_description(tool_name: str) -> str:
    """获取工具的中文描述"""
    return TOOL_DESCRIPTIONS.get(tool_name, tool_name)


def format_confirmation_message(tool_name: str, args: dict) -> str:
    """格式化确认消息"""
    desc = get_tool_description(tool_name)
    args_str = ", ".join(f"{k}={v}" for k, v in args.items() if v)
    return f"即将执行: {desc}\n参数: {args_str}\n\n确认执行吗？(输入 '确认' 或 '取消')"


def format_error_with_suggestion(error_message: str) -> str:
    """
    格式化错误消息并附带恢复建议
    
    Args:
        error_message: 原始错误消息
        
    Returns:
        带有建议的错误消息
    """
    suggestion = get_error_suggestion(error_message)
    if suggestion:
        return f"❌ 错误: {error_message}\n\n💡 建议: {suggestion}"
    return f"❌ 错误: {error_message}"
