#!/usr/bin/env python3
"""
子代理协调模块
协调子代理执行工作流任务
"""

import json
import importlib
import asyncio
import threading
from pathlib import Path
from typing import Dict, List, Optional, Any, Callable
from dataclasses import dataclass, field
from enum import Enum
import logging
import time

logger = logging.getLogger(__name__)


class TaskStatus(Enum):
    """任务状态"""
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    SKIPPED = "skipped"


class AgentType(Enum):
    """代理类型"""
    LORE_BIBLE_MANAGER = "lore_bible_manager"
    CONFLICT_DETECTOR = "conflict_detector"
    PROFILE_SESSION = "profile_session"
    PROFILE_GENERATOR = "profile_generator"


@dataclass
class TaskResult:
    """任务结果"""
    task_id: str
    status: TaskStatus
    outputs: Dict[str, Any] = field(default_factory=dict)
    error: Optional[str] = None
    start_time: float = 0
    end_time: float = 0
    duration: float = 0


@dataclass
class WorkflowTask:
    """工作流任务定义"""
    id: str
    name: str
    description: str
    agent_type: str
    inputs: List[str]
    outputs: List[str]
    depends_on: List[str] = field(default_factory=list)
    condition: Optional[str] = None
    timeout: int = 60
    retry_count: int = 1
    interactive: bool = False


class SubagentOrchestrator:
    """子代理协调器"""

    def __init__(self, workspace: str, config_file: Optional[str] = None):
        """初始化协调器

        Args:
            workspace: 工作目录
            config_file: 工作流配置文件路径
        """
        self.workspace = workspace
        self.config_file = config_file or str(Path(__file__).parent.parent / "config" / "workflow_tasks.json")
        self.workflows = self._load_workflows()
        self.tasks: Dict[str, WorkflowTask] = {}
        self.results: Dict[str, TaskResult] = {}
        self.context: Dict[str, Any] = {"workspace": workspace}
        self.agents: Dict[str, Any] = {}

    def _load_workflows(self) -> Dict:
        """加载工作流配置

        Returns:
            工作流配置字典
        """
        try:
            with open(self.config_file, 'r', encoding='utf-8') as f:
                config = json.load(f)
            logger.info(f"加载工作流配置: {self.config_file}")
            return config
        except Exception as e:
            logger.error(f"加载工作流配置失败: {e}")
            return {"workflows": {}, "agents": {}}

    def _initialize_agent(self, agent_type: str) -> Optional[Any]:
        """初始化代理实例

        Args:
            agent_type: 代理类型

        Returns:
            代理实例，失败返回None
        """
        if agent_type in self.agents:
            return self.agents[agent_type]

        agent_config = self.workflows.get("agents", {}).get(agent_type)
        if not agent_config:
            logger.error(f"未找到代理配置: {agent_type}")
            return None

        try:
            module_name = agent_config["module"]
            class_name = agent_config["class"]

            # 动态导入模块
            module = importlib.import_module(module_name.replace('/', '.'))
            agent_class = getattr(module, class_name)

            # 实例化代理
            if agent_type == AgentType.LORE_BIBLE_MANAGER.value:
                agent = agent_class(self.workspace)
            elif agent_type == AgentType.CONFLICT_DETECTOR.value:
                agent = agent_class()
            elif agent_type == AgentType.PROFILE_GENERATOR.value:
                agent = agent_class()
            elif agent_type == AgentType.PROFILE_SESSION.value:
                agent = None  # 会话需要特殊处理
            else:
                agent = agent_class()

            self.agents[agent_type] = agent
            logger.info(f"初始化代理: {agent_type}")
            return agent

        except Exception as e:
            logger.error(f"初始化代理失败 {agent_type}: {e}")
            return None

    def _execute_task(self, task: WorkflowTask) -> TaskResult:
        """执行单个任务

        Args:
            task: 任务定义

        Returns:
            任务结果
        """
        result = TaskResult(task_id=task.id, status=TaskStatus.RUNNING)
        result.start_time = time.time()

        try:
            logger.info(f"开始执行任务: {task.name} ({task.id})")

            # 检查条件
            if task.condition:
                if not self._evaluate_condition(task.condition):
                    result.status = TaskStatus.SKIPPED
                    result.outputs = {"skipped": True, "reason": "条件不满足"}
                    logger.info(f"跳过任务 {task.id}: 条件不满足")
                    return result

            # 准备输入参数
            inputs = self._prepare_inputs(task.inputs)

            # 执行任务
            if task.agent_type == AgentType.LORE_BIBLE_MANAGER.value:
                outputs = self._execute_lore_bible_task(task.id, inputs)
            elif task.agent_type == AgentType.CONFLICT_DETECTOR.value:
                outputs = self._execute_conflict_detector_task(task.id, inputs)
            elif task.agent_type == AgentType.PROFILE_SESSION.value:
                outputs = self._execute_profile_session_task(task.id, inputs)
            elif task.agent_type == AgentType.PROFILE_GENERATOR.value:
                outputs = self._execute_profile_generator_task(task.id, inputs)
            else:
                raise ValueError(f"未知的代理类型: {task.agent_type}")

            # 验证输出
            self._validate_outputs(task.outputs, outputs)

            # 更新上下文
            self.context.update(outputs)

            result.status = TaskStatus.COMPLETED
            result.outputs = outputs
            logger.info(f"任务完成: {task.name}")

        except Exception as e:
            result.status = TaskStatus.FAILED
            result.error = str(e)
            logger.error(f"任务失败 {task.id}: {e}")

        finally:
            result.end_time = time.time()
            result.duration = result.end_time - result.start_time

        return result

    def _prepare_inputs(self, input_keys: List[str]) -> Dict[str, Any]:
        """准备输入参数

        Args:
            input_keys: 输入键列表

        Returns:
            输入参数字典
        """
        inputs = {}
        for key in input_keys:
            if key in self.context:
                inputs[key] = self.context[key]
            else:
                # 尝试从结果中获取
                for task_id, result in self.results.items():
                    if key in result.outputs:
                        inputs[key] = result.outputs[key]
                        break
                else:
                    logger.warning(f"未找到输入参数: {key}")
                    inputs[key] = None

        return inputs

    def _validate_outputs(self, expected_outputs: List[str], actual_outputs: Dict[str, Any]):
        """验证输出参数

        Args:
            expected_outputs: 期望的输出键列表
            actual_outputs: 实际的输出字典
        """
        for output_key in expected_outputs:
            if output_key not in actual_outputs:
                logger.warning(f"任务缺少输出: {output_key}")

    def _evaluate_condition(self, condition: str) -> bool:
        """评估条件表达式

        Args:
            condition: 条件表达式

        Returns:
            条件是否满足
        """
        try:
            # 简单的条件评估
            if condition == "user_confirmed == true":
                return self.context.get("user_confirmed", False) is True
            elif condition == "is_valid == true":
                return self.context.get("is_valid", False) is True
            else:
                # 尝试评估Python表达式
                local_vars = {**self.context}
                for task_id, result in self.results.items():
                    local_vars.update(result.outputs)

                return eval(condition, {}, local_vars)
        except Exception as e:
            logger.warning(f"评估条件失败 '{condition}': {e}")
            return False

    def _execute_lore_bible_task(self, task_id: str, inputs: Dict) -> Dict:
        """执行LoreBible管理任务

        Args:
            task_id: 任务ID
            inputs: 输入参数

        Returns:
            输出参数字典
        """
        agent = self._initialize_agent(AgentType.LORE_BIBLE_MANAGER.value)
        if not agent:
            raise RuntimeError("初始化LoreBibleManager失败")

        workspace = inputs.get("workspace", self.workspace)

        if task_id == "init_workspace":
            # 验证目录结构
            is_valid, missing_dirs = agent.validate_directory_structure()

            if not is_valid:
                # 创建缺失目录
                success = agent.create_directory_structure()
                if not success:
                    raise RuntimeError("创建目录结构失败")

            # 扫描现有角色
            characters = agent.scan_existing_characters()

            return {
                "directory_status": "valid" if is_valid else "created",
                "missing_dirs": missing_dirs if not is_valid else [],
                "character_count": len(characters),
                "character_index": characters
            }

        elif task_id == "scan_existing":
            characters = agent.scan_existing_characters()
            index = agent.get_character_index(force_refresh=True)

            return {
                "character_index": characters,
                "character_count": len(characters),
                "index_details": index
            }

        else:
            raise ValueError(f"未知的LoreBible任务: {task_id}")

    def _execute_conflict_detector_task(self, task_id: str, inputs: Dict) -> Dict:
        """执行冲突检测任务

        Args:
            task_id: 任务ID
            inputs: 输入参数

        Returns:
            输出参数字典
        """
        agent = self._initialize_agent(AgentType.CONFLICT_DETECTOR.value)
        if not agent:
            raise RuntimeError("初始化ConflictDetector失败")

        if task_id == "detect_conflicts":
            character_data = inputs.get("character_data", {})
            character_index = inputs.get("character_index", [])

            # 设置角色索引
            agent.set_character_index({
                "characters": character_index,
                "total_count": len(character_index)
            })

            # 检测冲突
            conflicts = agent.detect_conflicts(character_data, character_index)
            is_valid, _ = agent.validate_character(character_data)

            # 生成报告
            report = agent.generate_report(conflicts, "text")

            return {
                "conflicts": conflicts,
                "is_valid": is_valid,
                "conflict_count": len(conflicts),
                "report": report
            }

        else:
            raise ValueError(f"未知的冲突检测任务: {task_id}")

    def _execute_profile_session_task(self, task_id: str, inputs: Dict) -> Dict:
        """执行会话管理任务

        Args:
            task_id: 任务ID
            inputs: 输入参数

        Returns:
            输出参数字典
        """
        from profile_session import ProfileSession, SessionConfig

        if task_id == "save_temp":
            profile_content = inputs.get("profile_content", "")
            character_name = inputs.get("character_name", "")
            workspace = inputs.get("workspace", self.workspace)

            # 创建会话配置
            config = SessionConfig(
                workspace=workspace,
                character_name=character_name,
                enable_validation=False,
                enable_conflict_check=False,
                require_confirmation=False
            )

            # 创建会话
            session = ProfileSession(config)

            # 保存临时档案
            temp_path = session.save_temp_profile(profile_content)
            if not temp_path:
                raise RuntimeError("保存临时档案失败")

            # 保存会话ID到上下文
            self.context["session_id"] = session.session_id

            return {
                "temp_file_path": str(temp_path),
                "session_id": session.session_id
            }

        elif task_id == "user_review":
            conflicts = inputs.get("conflicts", [])
            temp_file_path = inputs.get("temp_file_path", "")
            session_id = self.context.get("session_id")

            if not session_id:
                raise ValueError("未找到会话ID")

            # 加载会话
            workspace = inputs.get("workspace", self.workspace)
            session = ProfileSession.load_session(session_id, workspace)
            if not session:
                raise RuntimeError("加载会话失败")

            # 向用户展示
            user_confirmed = session.present_to_user(conflicts)
            user_notes = session.session_data.user_notes

            return {
                "user_confirmed": user_confirmed,
                "user_notes": user_notes,
                "session_id": session_id
            }

        elif task_id == "move_final":
            temp_file_path = inputs.get("temp_file_path", "")
            character_name = inputs.get("character_name", "")
            user_confirmed = inputs.get("user_confirmed", False)
            session_id = self.context.get("session_id")

            if not user_confirmed:
                return {"skipped": True, "reason": "用户未确认"}

            if not session_id:
                raise ValueError("未找到会话ID")

            # 加载会话
            workspace = inputs.get("workspace", self.workspace)
            session = ProfileSession.load_session(session_id, workspace)
            if not session:
                raise RuntimeError("加载会话失败")

            # 移动到最终目录
            final_path = session.confirm_and_move()
            if not final_path:
                raise RuntimeError("移动档案失败")

            return {
                "final_file_path": str(final_path),
                "session_id": session_id
            }

        elif task_id == "cleanup":
            session_id = inputs.get("session_id", self.context.get("session_id"))
            workspace = inputs.get("workspace", self.workspace)

            if not session_id:
                return {"cleaned_count": 0}

            # 加载会话
            session = ProfileSession.load_session(session_id, workspace)
            if session:
                session.cleanup()

            return {"cleaned_count": 1}

        else:
            raise ValueError(f"未知的会话管理任务: {task_id}")

    def _execute_profile_generator_task(self, task_id: str, inputs: Dict) -> Dict:
        """执行档案生成任务

        Args:
            task_id: 任务ID
            inputs: 输入参数

        Returns:
            输出参数字典
        """
        agent = self._initialize_agent(AgentType.PROFILE_GENERATOR.value)
        if not agent:
            raise RuntimeError("初始化ProfileGenerator失败")

        if task_id == "generate_profile":
            character_data = inputs.get("character_data", {})
            template_type = inputs.get("template_type", "standard")

            # 设置模板类型
            agent.template_type = template_type

            # 生成档案内容
            profile_content = agent.generate_markdown(character_data, output_path=None)

            return {
                "profile_content": profile_content,
                "character_name": character_data.get("name", "")
            }

        elif task_id == "generate_and_save":
            character_data = inputs.get("character_data", {})
            template_type = inputs.get("template_type", "standard")
            workspace = inputs.get("workspace", self.workspace)

            # 设置工作空间
            agent.workspace = workspace
            agent.enable_enhanced_features = True

            # 使用增强功能生成
            success, final_path, conflicts = agent.generate_enhanced_profile(
                character_data,
                require_confirmation=False
            )

            if not success:
                raise RuntimeError(f"生成档案失败: {conflicts}")

            return {
                "final_file_path": str(final_path) if final_path else None,
                "success": success,
                "conflict_count": len(conflicts)
            }

        else:
            raise ValueError(f"未知的档案生成任务: {task_id}")

    def run_workflow(self, workflow_name: str, initial_context: Dict = None) -> Dict[str, Any]:
        """运行工作流

        Args:
            workflow_name: 工作流名称
            initial_context: 初始上下文

        Returns:
            最终上下文和结果
        """
        if initial_context:
            self.context.update(initial_context)

        # 获取工作流定义
        workflow = self.workflows.get("workflows", {}).get(workflow_name)
        if not workflow:
            raise ValueError(f"未找到工作流: {workflow_name}")

        logger.info(f"开始运行工作流: {workflow['name']}")

        # 解析任务
        tasks_data = workflow.get("tasks", [])
        self.tasks = {task["id"]: WorkflowTask(**task) for task in tasks_data}

        # 执行任务
        execution_order = self._calculate_execution_order()

        for task_id in execution_order:
            task = self.tasks[task_id]

            # 检查依赖是否完成
            for dep_id in task.depends_on:
                if dep_id not in self.results:
                    raise RuntimeError(f"任务 {task_id} 的依赖 {dep_id} 未执行")
                if self.results[dep_id].status == TaskStatus.FAILED:
                    logger.warning(f"任务 {task_id} 的依赖 {dep_id} 失败，跳过")
                    self.results[task_id] = TaskResult(
                        task_id=task_id,
                        status=TaskStatus.SKIPPED,
                        outputs={"skipped": True, "reason": f"依赖 {dep_id} 失败"}
                    )
                    continue

            # 执行任务（带重试）
            result = None
            for attempt in range(task.retry_count + 1):
                if attempt > 0:
                    logger.info(f"重试任务 {task_id} (尝试 {attempt + 1}/{task.retry_count + 1})")

                result = self._execute_task(task)

                if result.status == TaskStatus.COMPLETED:
                    break
                elif attempt < task.retry_count:
                    logger.warning(f"任务 {task_id} 失败，准备重试: {result.error}")
                    time.sleep(1)  # 重试前等待

            self.results[task_id] = result

        # 生成报告
        report = self._generate_report(workflow_name)

        logger.info(f"工作流完成: {workflow_name}")
        return {
            "context": self.context,
            "results": self.results,
            "report": report
        }

    def _calculate_execution_order(self) -> List[str]:
        """计算任务执行顺序（拓扑排序）

        Returns:
            任务ID列表
        """
        # 构建依赖图
        graph = {task_id: set(task.depends_on) for task_id, task in self.tasks.items()}

        # 拓扑排序
        visited = set()
        temp_visited = set()
        order = []

        def visit(node):
            if node in temp_visited:
                raise RuntimeError(f"检测到循环依赖: {node}")
            if node in visited:
                return

            temp_visited.add(node)
            for dep in graph.get(node, set()):
                if dep in self.tasks:  # 只包括定义的任务
                    visit(dep)

            temp_visited.remove(node)
            visited.add(node)
            order.append(node)

        for task_id in self.tasks:
            if task_id not in visited:
                visit(task_id)

        return order

    def _generate_report(self, workflow_name: str) -> Dict:
        """生成执行报告

        Args:
            workflow_name: 工作流名称

        Returns:
            报告字典
        """
        total_tasks = len(self.tasks)
        completed = sum(1 for r in self.results.values() if r.status == TaskStatus.COMPLETED)
        failed = sum(1 for r in self.results.values() if r.status == TaskStatus.FAILED)
        skipped = sum(1 for r in self.results.values() if r.status == TaskStatus.SKIPPED)

        task_details = []
        for task_id, result in self.results.items():
            task_details.append({
                "task_id": task_id,
                "name": self.tasks[task_id].name if task_id in self.tasks else "未知",
                "status": result.status.value,
                "duration": result.duration,
                "error": result.error
            })

        return {
            "workflow": workflow_name,
            "total_tasks": total_tasks,
            "completed": completed,
            "failed": failed,
            "skipped": skipped,
            "success_rate": completed / total_tasks if total_tasks > 0 else 0,
            "total_duration": sum(r.duration for r in self.results.values()),
            "task_details": task_details,
            "final_context_keys": list(self.context.keys())
        }


def main():
    """命令行测试"""
    import sys

    if len(sys.argv) < 3:
        print("用法: python subagent_orchestrator.py <工作目录> <工作流名称>")
        print("可用工作流: character_creation, quick_creation")
        sys.exit(1)

    workspace = sys.argv[1]
    workflow_name = sys.argv[2]

    # 创建协调器
    orchestrator = SubagentOrchestrator(workspace)

    # 运行工作流
    try:
        result = orchestrator.run_workflow(workflow_name)

        print(f"\n{'='*60}")
        print(f"工作流执行完成: {workflow_name}")
        print(f"{'='*60}\n")

        report = result["report"]
        print(f"任务统计: {report['completed']}/{report['total_tasks']} 完成, "
              f"{report['failed']} 失败, {report['skipped']} 跳过")
        print(f"成功率: {report['success_rate']:.1%}")
        print(f"总耗时: {report['total_duration']:.2f} 秒\n")

        print("任务详情:")
        for task in report["task_details"]:
            status_icon = {
                "completed": "✓",
                "failed": "✗",
                "skipped": "⏭",
                "running": "↻",
                "pending": "⏳"
            }.get(task["status"], "?")

            print(f"  {status_icon} {task['name']} ({task['task_id']})")
            print(f"    状态: {task['status']}, 耗时: {task['duration']:.2f}秒")
            if task["error"]:
                print(f"    错误: {task['error']}")

        # 显示最终输出
        if "final_file_path" in result["context"]:
            print(f"\n生成的档案: {result['context']['final_file_path']}")

    except Exception as e:
        print(f"工作流执行失败: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()