<?php
/**
 * 数字人Agent基类
 * 提供LLM调用、会话管理、消息总线等通用能力
 */

require_once __DIR__ . '/../config.php';

class BaseAgent {
    protected $agentType;
    protected $sessionId;
    protected $pdo;
    protected $systemPrompt;
    protected $conversationHistory = [];
    protected $maxHistory = 20;

    private static $siliconflowKey = 'sk-bcczdchfdqzvrdcaozkubiypsmgathqotfsdgjshowosyumg';
    private static $siliconflowUrl = 'https://api.siliconflow.cn/v1/chat/completions';
    private static $doubaoKey = 'ark-2383016b-22c3-48a8-9613-f9e437f6b624-8c249';
    private static $doubaoUrl = 'https://ark.cn-beijing.volces.com/api/v3/chat/completions';

    public function __construct($agentType, $sessionId = null) {
        global $pdo;
        $this->pdo = $pdo;
        $this->agentType = $agentType;
        $this->sessionId = $sessionId ?: uniqid($agentType . '_');
        $this->loadConversation();
    }

    public function getAgentType() {
        return $this->agentType;
    }

    public function getSessionId() {
        return $this->sessionId;
    }

    protected function loadConversation() {
        if (!$this->pdo) return;
        try {
            $stmt = $this->pdo->prepare(
                "SELECT messages FROM digital_human_sessions WHERE session_id = ? AND agent_type = ? ORDER BY created_at DESC LIMIT 1"
            );
            $stmt->execute([$this->sessionId, $this->agentType]);
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            if ($row && $row['messages']) {
                $this->conversationHistory = json_decode($row['messages'], true) ?: [];
            }
        } catch (PDOException $e) {
            $this->conversationHistory = [];
        }
    }

    protected function saveConversation() {
        if (!$this->pdo) return;
        try {
            $stmt = $this->pdo->prepare(
                "INSERT INTO digital_human_sessions (agent_type, session_id, messages, context)
                 VALUES (?, ?, ?, ?)
                 ON DUPLICATE KEY UPDATE messages = VALUES(messages), context = VALUES(context)"
            );
            $context = json_encode(['agent_type' => $this->agentType, 'updated_at' => date('Y-m-d H:i:s')]);
            $stmt->execute([$this->agentType, $this->sessionId, json_encode($this->conversationHistory, JSON_UNESCAPED_UNICODE), $context]);
        } catch (PDOException $e) {}
    }

    protected function addToHistory($role, $content) {
        $this->conversationHistory[] = ['role' => $role, 'content' => $content];
        if (count($this->conversationHistory) > $this->maxHistory * 2) {
            $systemMsgs = array_filter($this->conversationHistory, function($m) { return $m['role'] === 'system'; });
            $recentMsgs = array_slice($this->conversationHistory, -$this->maxHistory);
            $this->conversationHistory = array_merge($systemMsgs, $recentMsgs);
        }
        $this->saveConversation();
    }

    protected function callLLM($userMessage, $systemPromptOverride = null, $temperature = 0.7) {
        $systemPrompt = $systemPromptOverride ?: $this->systemPrompt;

        $messages = [];
        if ($systemPrompt) {
            $messages[] = ['role' => 'system', 'content' => $systemPrompt];
        }
        foreach ($this->conversationHistory as $msg) {
            if ($msg['role'] !== 'system') {
                $messages[] = $msg;
            }
        }
        $messages[] = ['role' => 'user', 'content' => $userMessage];

        $result = $this->callSiliconflow($messages, $temperature);
        if ($result['success']) {
            return $result;
        }

        $result = $this->callDoubao($messages, $temperature);
        if ($result['success']) {
            return $result;
        }

        return ['success' => false, 'message' => '所有AI引擎均不可用', 'content' => ''];
    }

    private function callSiliconflow($messages, $temperature) {
        $data = [
            'model' => 'deepseek-ai/DeepSeek-V4-Flash',
            'messages' => $messages,
            'temperature' => $temperature,
            'max_tokens' => 2048,
            'stream' => false
        ];

        $ch = curl_init(self::$siliconflowUrl);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Authorization: Bearer ' . self::$siliconflowKey
            ]
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($response === false || $httpCode !== 200) {
            return ['success' => false];
        }

        $result = json_decode($response, true);
        if (!$result || !isset($result['choices'][0]['message']['content'])) {
            return ['success' => false];
        }

        $content = $result['choices'][0]['message']['content'];
        return ['success' => true, 'content' => $content, 'source' => 'siliconflow'];
    }

    private function callDoubao($messages, $temperature) {
        $data = [
            'model' => 'doubao-pro-128k',
            'messages' => $messages,
            'temperature' => $temperature,
            'max_tokens' => 2048
        ];

        $ch = curl_init(self::$doubaoUrl);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/json',
                'Authorization: Bearer ' . self::$doubaoKey
            ]
        ]);

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($response === false || $httpCode !== 200) {
            return ['success' => false];
        }

        $result = json_decode($response, true);
        if (!$result || !isset($result['choices'][0]['message']['content'])) {
            return ['success' => false];
        }

        $content = $result['choices'][0]['message']['content'];
        return ['success' => true, 'content' => $content, 'source' => 'doubao'];
    }

    protected function sendAgentEvent($toAgent, $eventType, $payload) {
        if (!$this->pdo) return false;
        try {
            $stmt = $this->pdo->prepare(
                "INSERT INTO agent_events (from_agent, to_agent, event_type, payload) VALUES (?, ?, ?, ?)"
            );
            return $stmt->execute([$this->agentType, $toAgent, $eventType, json_encode($payload, JSON_UNESCAPED_UNICODE)]);
        } catch (PDOException $e) {
            return false;
        }
    }

    protected function receiveAgentEvents($sinceId = 0) {
        if (!$this->pdo) return [];
        try {
            $stmt = $this->pdo->prepare(
                "SELECT * FROM agent_events WHERE to_agent = ? AND is_read = 0 AND id > ? ORDER BY id ASC"
            );
            $stmt->execute([$this->agentType, $sinceId]);
            $events = $stmt->fetchAll(PDO::FETCH_ASSOC);

            if (!empty($events)) {
                $ids = array_column($events, 'id');
                $placeholders = implode(',', array_fill(0, count($ids), '?'));
                $this->pdo->prepare("UPDATE agent_events SET is_read = 1 WHERE id IN ($placeholders)")->execute($ids);
            }

            return $events;
        } catch (PDOException $e) {
            return [];
        }
    }

    public function clearSession() {
        $this->conversationHistory = [];
        if ($this->pdo) {
            try {
                $stmt = $this->pdo->prepare("DELETE FROM digital_human_sessions WHERE session_id = ? AND agent_type = ?");
                $stmt->execute([$this->sessionId, $this->agentType]);
            } catch (PDOException $e) {}
        }
    }
}
