<?php

namespace App\Servers\Aliyun;

use \Exception;
use Darabonba\OpenApi\Models\Config;

/**
 * 通义千问大模型API
 * 提供简单易用的接口调用阿里云百炼大模型平台
 */
class TongyiQianwen
{
    private $apiKey;
    private $baseUrl = 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions';
    private $model = 'qwen-flash';
    private $timeout = 30;

    /**
     * 构造函数
     * 
     * @param string $apiKey API密钥，如果不传则尝试从环境变量获取
     * @throws Exception 当API密钥未设置时抛出异常
     */
    public function __construct($apiKey = null)
    {
        if ($apiKey) {
            $this->apiKey = $apiKey;
        } else {
            $this->apiKey = config('aliyun.bailian_access_key','');
        }

        if (empty($this->apiKey)) {
            throw new Exception('API密钥未设置，请通过构造函数传入或设置DASHSCOPE_API_KEY环境变量');
        }
    }

    /**
     * 设置模型
     * 
     * @param string $model 模型名称
     * @return $this
     */
    public function setModel($model)
    {
        $this->model = $model;
        return $this;
    }

    /**
     * 设置请求超时时间
     * 
     * @param int $timeout 超时时间（秒）
     * @return $this
     */
    public function setTimeout($timeout)
    {
        $this->timeout = $timeout;
        return $this;
    }

    /**
     * 发送消息并获取回复
     * 
     * @param string|array $messages 消息内容，可以是字符串或消息数组
     * @param string $systemPrompt 系统提示词
     * @return array 包含响应数据和错误信息的数组
     */
    public function sendMessage($messages, $systemPrompt = "")
    {
        // 格式化消息
        $formattedMessages = $this->formatMessages($messages, $systemPrompt);
        // 准备请求数据
        $data = [
            "model" => $this->model,
            "messages" => $formattedMessages
        ];

        // 设置请求头
        $headers = [
            'Authorization: Bearer ' . $this->apiKey,
            'Content-Type: application/json'
        ];

        // 初始化cURL
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $this->baseUrl,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_TIMEOUT => $this->timeout,
            CURLOPT_SSL_VERIFYPEER => true,
        ]);

        // 执行请求
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        // 处理响应
        if ($error) {
            return [
                'success' => false,
                'error' => 'CURL错误: ' . $error,
                'data' => null
            ];
        }

        $decodedResponse = json_decode($response, true);

        if ($httpCode !== 200) {
            return [
                'success' => false,
                'error' => 'API请求失败，HTTP状态码: ' . $httpCode,
                'data' => $decodedResponse
            ];
        }

        return [
            'success' => true,
            'error' => null,
            'data' => $decodedResponse
        ];
    }

    /**
     * 格式化消息为API所需的格式
     * 
     * @param string|array $messages 消息内容
     * @param string $systemPrompt 系统提示词
     * @return array 格式化后的消息数组
     */
    private function formatMessages($messages, $systemPrompt)
    {
        $formattedMessages = [];

        // 添加系统提示
        if (!empty($systemPrompt)) {
            $formattedMessages[] = [
                "role" => "system",
                "content" => $systemPrompt
            ];
        }

        // 处理不同类型的消息输入
        if (is_string($messages)) {
            // 单条用户消息
            $formattedMessages[] = [
                "role" => "user",
                "content" => $messages
            ];
        } elseif (is_array($messages)) {
            // 多条消息
            foreach ($messages as $message) {
                if (is_string($message)) {
                    $formattedMessages[] = [
                        "role" => "user",
                        "content" => $message
                    ];
                } elseif (is_array($message) && isset($message['role']) && isset($message['content'])) {
                    $formattedMessages[] = $message;
                }
            }
        }

        return $formattedMessages;
    }

    /**
     * 从响应中提取助手的回复内容
     * 
     * @param array $responseData sendMessage返回的数据
     * @return string|null 助手的回复内容，如果不存在则返回null
     */
    public function getAssistantReply($responseData)
    {
        if (!$responseData['success'] || !isset($responseData['data']['choices'][0]['message']['content'])) {
            return null;
        }

        return $responseData['data']['choices'][0]['message']['content'];
    }
    
    /**
     * 从响应中提取助手的回复消息ID
     * 
     * @param array $responseData sendMessage返回的数据
     * @return string|null 助手的回复内容，如果不存在则返回null
     */
    public function getAssistantReplyId($responseData)
    {;
        if (!$responseData['success'] || !isset($responseData['data']['id'])) {
            return null;
        }

        return $responseData['data']['id'];
    }

    /**
     * 简化调用 - 发送消息并直接获取回复文本
     * 
     * @param string $message 用户消息
     * @param string $systemPrompt 系统提示词
     * @return string 助手的回复内容，如果出错则返回错误信息
     */
    public function ask($message, $systemPrompt = "You are a helpful assistant.")
    {
        $response = $this->sendMessage($message, $systemPrompt);

        if (!$response['success']) {
            return "错误: " . $response['error'];
        }

        $reply = $this->getAssistantReply($response);

        return $reply ?: "未能获取到有效回复";
    }
}
