<?php

namespace XZD\AI\V5\Agents;

use XZD\AI\V5\AI\Client;
use XZD\AI\V5\AI\Types;
use XZD\AI\V5\Tools\ToolRegistry;
use XZD\AI\V5\Core\Logger;

/**
 * Orchestrator Agent — 总调度 Agent
 *
 * 职责:
 * - 意图识别（委托 IntentParser）
 * - 路由到专业 Agent
 * - 通用对话（无特定意图时直接回复）
 * - 多 Agent 协作编排
 */
class OrchestratorAgent extends BaseAgent
{
    private IntentParser $intentParser;

    /** @var array<string, BaseAgent> */
    private array $agents = [];

    private string $defaultModel = 'deepseek-v4-flash';

    public function __construct()
    {
        parent::__construct();
        $this->intentParser = new IntentParser();
        $this->registerDefaultAgents();
    }

    /**
     * 注册所有专业 Agent
     */
    private function registerDefaultAgents(): void
    {
        $this->registerAgent(new ContentAgent());
        $this->registerAgent(new SiteManagerAgent());
        $this->registerAgent(new UserManagerAgent());
        $this->registerAgent(new ThemeBridgeAgent());
        $this->registerAgent(new MonitorAgent());
    }

    /**
     * 注册一个 Agent
     */
    public function registerAgent(BaseAgent $agent): self
    {
        $this->agents[$agent->getId()] = $agent;
        return $this;
    }

    /**
     * 获取已注册的 Agent
     */
    public function getAgent(string $id): ?BaseAgent
    {
        return $this->agents[$id] ?? null;
    }

    /**
     * 获取所有 Agent
     */
    public function getAgents(): array
    {
        return $this->agents;
    }

    public function getId(): string
    {
        return 'orchestrator';
    }

    public function getName(): string
    {
        return '总调度 Agent';
    }

    public function getDescription(): string
    {
        return '识别用户意图，调度专业 Agent 执行任务';
    }

    public function getToolCategories(): array
    {
        return []; // orchestrator 可以访问所有工具
    }

    public function getMinRole(): string
    {
        return 'guest';
    }

    /**
     * 核心入口 — 处理用户消息
     *
     * @return array ['agent'=>'...','content'=>'...','tool_calls'=>[...],'intent'=>[...]]
     */
    public function handle(string $message, string $role, array $options = []): array
    {
        $start = microtime(true);

        // 1. 意图识别
        $intent = $this->intentParser->parse($message);

        // 2. 路由到专业 Agent
        $targetAgent = $this->agents[$intent['agent']] ?? $this;

        // 3. 检查权限 — 权限不足时降级到 orchestrator，而非直接拒绝
        if (!$this->checkAgentAccess($targetAgent, $role)) {
            $targetAgent = $this;  // 降级到基础对话模式
        }

        // 4. 构建上下文 + 执行
        $systemPrompt = $targetAgent->getSystemPrompt($role);
        $messages = [
            Types::system($systemPrompt),
            Types::user($message),
        ];

        try {
            $result = $targetAgent->chat($role, $messages, $options);

            return [
                'agent'      => $intent['agent'],
                'content'    => $result['content'] ?? '',
                'tool_calls' => $result['tool_calls'] ?? null,
                'intent'     => $intent,
                'model'      => $result['model'] ?? '',
                'input_tokens'  => $result['input_tokens'] ?? 0,
                'output_tokens' => $result['output_tokens'] ?? 0,
                'duration_ms' => (int) ((microtime(true) - $start) * 1000),
            ];
        } catch (\Throwable $e) {
            Logger::error('orchestrator_handle', $e->getMessage(), [
                'agent'  => $intent['agent'],
                'role'   => $role,
            ]);

            return [
                'agent'   => $intent['agent'],
                'content' => "抱歉，处理请求时出现错误: {$e->getMessage()}",
                'tool_calls' => null,
                'intent'  => $intent,
                'error'   => $e->getMessage(),
                'duration_ms' => (int) ((microtime(true) - $start) * 1000),
            ];
        }
    }

    /**
     * 流式处理用户消息
     */
    public function handleStream(string $message, string $role, array $options = []): \Generator
    {
        $start = microtime(true);

        // 1. 意图识别
        $intent = $this->intentParser->parse($message);

        // 2. 路由
        $targetAgent = $this->agents[$intent['agent']] ?? $this;

        // 3. 检查权限 — 权限不足时降级到 orchestrator，而非直接拒绝
        if (!$this->checkAgentAccess($targetAgent, $role)) {
            $targetAgent = $this;  // 降级到基础对话模式
        }

        // 4. 流式对话
        $systemPrompt = $targetAgent->getSystemPrompt($role);
        $messages = [
            Types::system($systemPrompt),
            Types::user($message),
        ];

        yield from $targetAgent->chatStream($role, $messages, $options);
    }

    /**
     * 处理带工具调用的完整 ReAct 循环（用于非流式场景）
     *
     * @return array 最终消息列表和结果
     */
    public function handleWithTools(string $sessionKey, string $message, string $role, int $userId, int $maxTurns = 5): array
    {
        $sessionManager = new SessionManager();
        $dispatcher = ActionDispatcher::instance();

        // 获取会话
        $session = $sessionManager->getSession($sessionKey);
        if (!$session) {
            $created = $sessionManager->createSession($userId, mb_substr($message, 0, 50));
            if (!$created['success']) {
                return ['error' => '创建会话失败'];
            }
            $sessionKey = $created['session_key'];
        }

        // 保存用户消息
        $sessionManager->addMessage($sessionKey, 'user', $message);

        // 初始意图识别
        $intent = $this->intentParser->parse($message);
        $targetAgent = $this->agents[$intent['agent']] ?? $this;

        if (!$this->checkAgentAccess($targetAgent, $role)) {
            return [
                'agent'    => 'orchestrator',
                'content'  => "抱歉，{$targetAgent->getName()} 需要更高权限。",
                'intent'   => $intent,
            ];
        }

        // AgentLoop 入口
        $loop = new AgentLoop($targetAgent, $dispatcher);
        return $loop->run($sessionKey, $message, $role, $userId);
    }

    // ===== 内部 =====

    /**
     * 检查用户是否有权使用此 Agent
     */
    private function checkAgentAccess(BaseAgent $agent, string $role): bool
    {
        $roleLevel = ['guest' => 0, 'user' => 1, 'vip' => 2, 'admin' => 3];
        $userLevel = $roleLevel[$role] ?? 0;
        $minLevel = $roleLevel[$agent->getMinRole()] ?? 0;
        return $userLevel >= $minLevel;
    }
}
