use crate::agent::llm::ProviderRegistry;
use crate::agent::llm::{ChatMessage, LlmClient, LlmError};
use crate::agent::memory::MemoryStore;
use crate::agent::prompts::{build_project_context, system_prompt};
use crate::agent::tools::{execute_tool, tool_definitions, ToolContext};
use crate::config::AgentWorkerConfig;
use crate::db::Database;
use crate::types::*;
use tokio::sync::broadcast;
use uuid::Uuid;

/// Agent 运行时
pub struct AgentRuntime {
    db: &'static Database,
    project_id: Uuid,
    tx: broadcast::Sender<String>,
    llm: LlmClient,
    memory: MemoryStore,
    max_turns: u32,
}

/// Agent 运行结果
pub struct AgentRunResult {
    pub answer: String,
    pub turns: u32,
    pub tool_calls: Vec<ToolCallRecord>,
    pub created_nodes: Vec<NodeSummary>,
    pub created_edges: Vec<EdgeResponse>,
    pub created_intents: Vec<ExplorationIntent>,
}

impl AgentRuntime {
    /// 使用 ProviderRegistry 创建 AgentRuntime
    pub fn with_provider(
        db: &'static Database,
        project_id: Uuid,
        tx: broadcast::Sender<String>,
        registry: &ProviderRegistry,
        task_type: &str,
        workers: &[AgentWorkerConfig],
        max_turns: u32,
    ) -> Option<Self> {
        let llm = registry.get_client_for_task(task_type, workers)?;
        let effective_max_turns = workers
            .iter()
            .find(|w| w.task_type == task_type)
            .and_then(|w| w.max_turns)
            .unwrap_or(max_turns);
        Some(Self {
            db,
            project_id,
            tx: tx.clone(),
            llm,
            memory: MemoryStore::new(db, project_id),
            max_turns: effective_max_turns,
        })
    }

    /// 使用 API key 创建 AgentRuntime（legacy）
    pub fn new(
        db: &'static Database,
        project_id: Uuid,
        tx: broadcast::Sender<String>,
        api_key: String,
        max_turns: u32,
    ) -> Self {
        Self {
            db,
            project_id,
            tx: tx.clone(),
            llm: LlmClient::new(api_key),
            memory: MemoryStore::new(db, project_id),
            max_turns,
        }
    }

    /// 运行 Agent
    pub async fn run(
        &self,
        entry: &AgentEntry,
        message: &str,
    ) -> Result<AgentRunResult, AgentError> {
        // 1. 构建项目上下文
        let project_context = self.build_context()?;

        // 1.5 Stigmergy: Reason 模式下读取现有 Intent 避免重复
        let existing_intents = if matches!(entry, AgentEntry::Reason) {
            match self.db.list_intents(self.project_id, None, Some("open")) {
                Ok(intents) => intents,
                Err(_) => Vec::new(),
            }
        } else {
            Vec::new()
        };

        // 1.5b Stigmergy: Explore 模式下创建 Intent 标记
        let explore_intent_id = if matches!(entry, AgentEntry::Explore) {
            match self.db.create_intent(
                self.project_id,
                "auto",
                message,
                Some("agent exploring"),
            ) {
                Ok(intent) => {
                    let _ = self.db.claim_intent(&intent.id, "agent");
                    Some(intent.id)
                }
                Err(_) => None,
            }
        } else {
            None
        };
        
        let mut created_intents = Vec::new();
        let mut last_answer = String::new();

        // 2. 获取系统提示
        let mut system = system_prompt(entry, &project_context);
        // Stigmergy: Reason 模式下注入现有 Intent 到 system prompt
        if matches!(entry, AgentEntry::Reason) && !existing_intents.is_empty() {
            let intents_info = existing_intents.iter()
                .map(|i| format!("- [{}] {} (target: {}, priority: {})", i.id, i.direction, i.node_id, i.status.as_str()))
                .collect::<Vec<_>>()
                .join("\n");
            system = format!("{}\n\n## 现有探索方向（避免重复）\n{}", system, intents_info);
        }

        // 3. 加载历史记忆
        let history = self
            .memory
            .load_recent(20)
            .map_err(|e| AgentError::MemoryError(e))?;

        // 4. 构建消息列表
        let mut messages = vec![ChatMessage::system(system)];
        messages.extend(history);
        messages.push(ChatMessage::user(message));

        // 5. 获取工具定义
        let tools = tool_definitions();

        // 6. 运行 Agent 循环
        let mut turns = 0;
        let mut all_tool_calls = Vec::new();
        let mut created_nodes = Vec::new();
        let mut created_edges = Vec::new();

        loop {
            if turns >= self.max_turns {
                break;
            }

            // 调用 LLM
            let response = self
                .llm
                .chat(messages.clone(), Some(tools.clone()), 0.2, 4096)
                .await
                .map_err(|e| AgentError::LlmError(e))?;

            // 如果没有工具调用，返回最终答案
            if response.tool_calls.is_empty() {
                let answer = response.content.unwrap_or_default();
                last_answer = answer.clone();

                // 保存对话到记忆
                messages.push(ChatMessage::assistant(Some(answer.clone()), None));
                self.memory
                    .save_turn(&messages[1..]) // 跳过系统提示
                    .map_err(|e| AgentError::MemoryError(e))?;

                return Ok(AgentRunResult {
                    answer,
                    turns,
                    tool_calls: all_tool_calls,
                    created_nodes,
                    created_edges,
                    created_intents: Vec::new(),
                });
            }

            // 执行工具调用
            let assistant_msg =
                ChatMessage::assistant(response.content.clone(), Some(response.tool_calls.clone()));
            messages.push(assistant_msg);

            for tool_call in &response.tool_calls {
                let ctx = ToolContext {
                    db: self.db,
                    project_id: self.project_id,
                    tx: self.tx.clone(),
                };

                let result = execute_tool(&ctx, &tool_call.name, tool_call.arguments.clone());

                match result {
                    Ok(tool_result) => {
                        // 记录工具调用
                        all_tool_calls.push(ToolCallRecord {
                            id: tool_call.id.clone(),
                            name: tool_call.name.clone(),
                            arguments: tool_call.arguments.clone(),
                            result: Some(tool_result.output.clone()),
                            error: None,
                        });

                        // 收集创建的实体
                        for effect in &tool_result.side_effects {
                            match effect {
                                SideEffect::NodeCreated(node) => {
                                    created_nodes.push(NodeSummary {
                                        id: node.id,
                                        label: node.label.clone(),
                                        node_type: node.node_type.clone(),
                                        verdict: node
                                            .properties
                                            .get("verdict")
                                            .and_then(|v| v.as_str())
                                            .map(|s| s.to_string()),
                                        evidence: node
                                            .properties
                                            .get("evidence")
                                            .and_then(|v| v.as_str())
                                            .map(|s| s.to_string()),
                                    });
                                }
                                SideEffect::EdgeCreated(edge) => {
                                    created_edges.push(edge.clone());
                                }
                                _ => {}
                            }
                        }

                        // 添加工具结果到消息
                        let result_json =
                            serde_json::to_string(&tool_result.output).unwrap_or_default();
                        messages.push(ChatMessage::tool(&tool_call.id, result_json));
                    }
                    Err(e) => {
                        // 记录错误
                        all_tool_calls.push(ToolCallRecord {
                            id: tool_call.id.clone(),
                            name: tool_call.name.clone(),
                            arguments: tool_call.arguments.clone(),
                            result: None,
                            error: Some(e.to_string()),
                        });

                        // 添加错误消息
                        messages.push(ChatMessage::tool(&tool_call.id, format!("Error: {}", e)));
                    }
                }
            }

            turns += 1;
        }

        // Stigmergy: 清理 Explore 标记 & 解析 Reason 建议
        if let Some(intent_id) = &explore_intent_id {
            let _ = self.db.complete_intent(intent_id);
        }
        if matches!(entry, AgentEntry::Reason) {
            if let Some(intents) = Self::parse_intents_from_answer(&last_answer) {
                for intent in intents {
                    if let Ok(created) = self.db.create_intent(
                        self.project_id,
                        &intent.0,  // node_id
                        &intent.1,  // direction
                        intent.2.as_deref(),  // description
                    ) {
                        created_intents.push(created);
                    }
                }
            }
        }

        // 达到最大轮次，返回当前结果
        let answer = "达到最大轮数限制，任务未完成。".to_string();

        // 保存对话到记忆
        messages.push(ChatMessage::assistant(Some(answer.clone()), None));
        self.memory
            .save_turn(&messages[1..])
            .map_err(|e| AgentError::MemoryError(e))?;

        Ok(AgentRunResult {
            answer,
            turns,
            tool_calls: all_tool_calls,
            created_nodes,
            created_edges,
            created_intents: Vec::new(),
        })
    }

    /// 构建项目上下文
    fn build_context(&self) -> Result<String, AgentError> {
        let nodes = self
            .db
            .list_nodes(self.project_id)
            .map_err(|e| AgentError::DatabaseError(e.to_string()))?;

        let edges = self
            .db
            .list_edges(self.project_id)
            .map_err(|e| AgentError::DatabaseError(e.to_string()))?;

        let node_summaries: Vec<NodeSummary> = nodes.iter().map(|n| NodeSummary::from(n)).collect();

        let edge_count = edges.len();
        let edge_responses: Vec<EdgeResponse> = edges.into_iter().map(EdgeResponse::from).collect();

        let stats = ProjectStats {
            node_count: nodes.len(),
            edge_count,
        };

        Ok(build_project_context(
            &node_summaries,
            &edge_responses,
            &stats,
        ))
    }

    /// 从 Reason 回答中解析建议的 Intent
    fn parse_intents_from_answer(answer: &str) -> Option<Vec<(String, String, Option<String>)>> {
        // 查找 JSON 代码块
        let json_start = answer.rfind("```json")?;
        let json_content = answer.get(json_start + 7..)?;
        let json_end = json_content.find("```")?;
        let json_str = &json_content[..json_end].trim();
        
        let parsed: serde_json::Value = serde_json::from_str(json_str).ok()?;
        let intents = parsed.get("intents")?.as_array()?;
        
        let mut result = Vec::new();
        for intent in intents {
            let direction = intent.get("direction")?.as_str()?.to_string();
            let target_node = intent.get("target_node")
                .and_then(|v| v.as_str())
                .unwrap_or("unknown")
                .to_string();
            let priority = intent.get("priority")
                .and_then(|v| v.as_str())
                .map(|s| s.to_string());
            result.push((target_node, direction, priority));
        }
        
        if result.is_empty() { None } else { Some(result) }
    }
}

/// Agent 错误类型
#[derive(Debug)]
pub enum AgentError {
    LlmError(LlmError),
    MemoryError(String),
    DatabaseError(String),
}

impl std::fmt::Display for AgentError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            AgentError::LlmError(e) => write!(f, "LLM error: {}", e),
            AgentError::MemoryError(e) => write!(f, "Memory error: {}", e),
            AgentError::DatabaseError(e) => write!(f, "Database error: {}", e),
        }
    }
}
