<?php

namespace platyFramework;

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

/**
 * Claude API Model
 * Anthropic Claude API를 사용하기 위한 클래스
 */
class ClaudeAPIModel extends model
{
    private $apiKey;
    private $model = 'claude-3-5-sonnet-20241022';
    private $apiUrl = 'https://api.anthropic.com/v1/messages';
    private $apiVersion = '2023-06-01';
    private $maxTokens = 4096;
    private $temperature = 1.0;
    private $conversationHistory = [];
    private $anthropicBeta = null;
    private $debug = false;

    /**
     * 생성자
     * @param string $apiKey Anthropic API 키
     */
    public function __construct($apiKey)
    {
        parent::__construct();
        $this->apiKey = $apiKey;
    }

    /**
     * 모델 설정
     * @param string $model 사용할 Claude 모델명
     * @return $this
     */
    public function setModel($model)
    {
        $this->model = $model;
        return $this;
    }

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

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

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

    /**
     * anthropic-beta 헤더 설정
     * @param string|null $betaFeature 베타 기능 이름 (예: context-1m-2025-08-07)
     * @return $this
     */
    public function setAnthropicBeta($betaFeature)
    {
        $this->anthropicBeta = $betaFeature;
        return $this;
    }

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

    /**
     * Claude 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,
            'max_tokens' => $this->maxTokens,
            'temperature' => $this->temperature,
            'messages' => $messages
        ];

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

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

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

        return $response;
    }

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

        $data = [
            'model' => $this->model,
            'max_tokens' => $this->maxTokens,
            'temperature' => $this->temperature,
            'system' => $systemPrompt,
            'messages' => $messages
        ];

        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',
            'x-api-key: ' . $this->apiKey,
            'anthropic-version: ' . $this->apiVersion
        ];

        // anthropic-beta 헤더 추가
        if ($this->anthropicBeta) {
            $headers[] = 'anthropic-beta: ' . $this->anthropicBeta;
        }

        $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) {
                // apiKey는 일부만 표시
                if (strpos($header, 'x-api-key:') === 0) {
                    $key = substr($this->apiKey, 0, 12) . '...';
                    fwrite(STDERR, "  x-api-key: {$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("Claude API cURL Error: " . $error);
            return false;
        }

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

        $result = json_decode($response, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            error_log("Claude 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['content'][0]['text'])) {
            return $response['content'][0]['text'];
        }
        return false;
    }

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