<?php

namespace platyFramework;

require_once(__DIR__ . "/../ptycommon/model.php");

/**
 * ChatGPT API Model
 * OpenAI ChatGPT API를 사용하기 위한 클래스
 */
class ChatGPTAPIModel extends model
{
    private $apiKey;
    private $model = 'gpt-4o';
    private $apiUrl = 'https://api.openai.com/v1/chat/completions';
    private $maxTokens = 4096;
    private $temperature = 1.0;
    private $conversationHistory = [];
    private $debug = false;


    /**
     * 모델 설정
     * @param string $model 사용할 ChatGPT 모델명 (gpt-4o, gpt-4-turbo, gpt-3.5-turbo 등)
     * @return $this
     */
    public function setModel($model)
    {
        $this->model = $model;
        return $this;
    }

    public function setAPIKey($apiKey)
    {
        $this->apiKey = $apiKey;
        return $this;
    }

    /**
     * 최대 토큰 수 설정
     * @param int $maxTokens
     * @return $this
     */
    public function setMaxTokens($maxTokens)
    {
        $this->maxTokens = $maxTokens;
        return $this;
    }

    /**
     * Temperature 설정
     * @param float $temperature 0.0 ~ 2.0
     * @return $this
     */
    public function setTemperature($temperature)
    {
        $this->temperature = $temperature;
        return $this;
    }

    /**
     * 대화 기록 초기화
     * @return $this
     */
    public function resetConversation()
    {
        $this->conversationHistory = [];
        return $this;
    }

    /**
     * 디버그 모드 설정
     * @param bool $debug 디버그 모드 활성화 여부
     * @return $this
     */
    public function setDebug($debug)
    {
        $this->debug = $debug;
        return $this;
    }

    /**
     * 새 모델인지 확인 (o1, o3, gpt-5 등은 max_completion_tokens 사용)
     * @return bool
     */
    private function isNewModel()
    {
        return preg_match('/^(o1|o3|gpt-5|gpt-4\.5)/i', $this->model);
    }

    /**
     * ChatGPT API 호출
     * @param string $message 사용자 메시지
     * @param bool $keepHistory 대화 기록 유지 여부
     * @return array|false 응답 배열 또는 false
     */
    public function get($message, $keepHistory = false)
    {
        // 현재 메시지를 대화 기록에 추가
        $messages = $this->conversationHistory;
        $messages[] = [
            'role' => 'user',
            'content' => $message
        ];

        // API 요청 데이터 구성
        $data = [
            'model' => $this->model,
            'temperature' => $this->temperature,
            'messages' => $messages
        ];

        // 새 모델은 max_completion_tokens 사용
        if ($this->isNewModel()) {
            $data['max_completion_tokens'] = $this->maxTokens;
        } else {
            $data['max_tokens'] = $this->maxTokens;
        }

        // API 호출
        $response = $this->_sendRequest($data);

        if ($response === false) {
            return false;
        }

        // 대화 기록 유지
        if ($keepHistory && isset($response['choices'][0]['message']['content'])) {
            $this->conversationHistory = $messages;
            $this->conversationHistory[] = [
                'role' => 'assistant',
                'content' => $response['choices'][0]['message']['content']
            ];
        }

        return $response;
    }

    /**
     * 시스템 프롬프트와 함께 메시지 전송
     * @param string $message 사용자 메시지
     * @param string $systemPrompt 시스템 프롬프트
     * @return array|false
     */
    public function getWithSystem($message, $systemPrompt)
    {
        $messages = [
            [
                'role' => 'system',
                'content' => $systemPrompt
            ],
            [
                'role' => 'user',
                'content' => $message
            ]
        ];

        $data = [
            'model' => $this->model,
            'temperature' => $this->temperature,
            'messages' => $messages
        ];

        // 새 모델은 max_completion_tokens 사용
        if ($this->isNewModel()) {
            $data['max_completion_tokens'] = $this->maxTokens;
        } else {
            $data['max_tokens'] = $this->maxTokens;
        }

        return $this->_sendRequest($data);
    }

    /**
     * API 요청 전송
     * @param array $data 요청 데이터
     * @return array|false
     */
    private function _sendRequest($data)
    {
        // API 호출 타임아웃 방지
        set_time_limit(0);
        ini_set('max_execution_time', '0');

        $ch = curl_init($this->apiUrl);

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

        $jsonData = json_encode($data);

        // 디버그 출력
        if ($this->debug) {
            fwrite(STDERR, "━━━━━━━━━━━━ CURL REQUEST ━━━━━━━━━━━━\n");
            fwrite(STDERR, "URL: {$this->apiUrl}\n");
            fwrite(STDERR, "Method: POST\n");
            fwrite(STDERR, "Headers:\n");
            foreach ($headers as $header) {
                if (strpos($header, 'Authorization:') === 0) {
                    $key = substr($this->apiKey, 0, 12) . '...';
                    fwrite(STDERR, "  Authorization: Bearer {$key}\n");
                } else {
                    fwrite(STDERR, "  {$header}\n");
                }
            }
            fwrite(STDERR, "Body:\n");
            fwrite(STDERR, "  " . json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n");
            fwrite(STDERR, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
        }

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

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

        // 디버그 출력 (응답)
        if ($this->debug) {
            fwrite(STDERR, "━━━━━━━━━━━━ CURL RESPONSE ━━━━━━━━━━━━\n");
            fwrite(STDERR, "HTTP Code: {$httpCode}\n");
            if ($error) {
                fwrite(STDERR, "cURL Error: {$error}\n");
            }
            fwrite(STDERR, "Response:\n");
            $prettyResponse = json_decode($response, true);
            if ($prettyResponse) {
                fwrite(STDERR, "  " . json_encode($prettyResponse, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n");
            } else {
                fwrite(STDERR, "  {$response}\n");
            }
            fwrite(STDERR, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
        }

        if ($error) {
            error_log("ChatGPT API cURL Error: " . $error);
            return false;
        }

        if ($httpCode !== 200) {
            error_log("ChatGPT API HTTP Error: " . $httpCode . " - " . $response);
            return false;
        }

        $result = json_decode($response, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            error_log("ChatGPT API JSON Decode Error: " . json_last_error_msg());
            return false;
        }

        return $result;
    }

    /**
     * 응답에서 텍스트만 추출
     * @param array $response API 응답
     * @return string|false
     */
    public function extractText($response)
    {
        if (isset($response['choices'][0]['message']['content'])) {
            return $response['choices'][0]['message']['content'];
        }
        return false;
    }

    /**
     * 간단한 텍스트 응답만 받기
     * @param string $message
     * @return string|false
     */
    public function getSimple($message)
    {
        $response = $this->get($message);
        return $this->extractText($response);
    }
}