<?php

namespace platyFramework;

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

/**
 * Gemini API Model
 * Google Gemini API를 사용하기 위한 클래스
 */
class GeminiAPIModel extends model
{
    private $apiKey;
    private $model = 'gemini-2.0-flash-exp';
    private $apiBaseUrl = 'https://generativelanguage.googleapis.com/v1beta/models';
    private $maxTokens = 4096;
    private $temperature = 1.0;
    private $conversationHistory = [];

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

    /**
     * 모델 설정
     * @param string $model 사용할 Gemini 모델명
     * @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 ~ 2.0
     * @return $this
     */
    public function setTemperature($temperature)
    {
        $this->temperature = $temperature;
        return $this;
    }

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

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

        // API 요청 데이터 구성
        $data = [
            'contents' => $contents,
            'generationConfig' => [
                'maxOutputTokens' => $this->maxTokens,
                'temperature' => $this->temperature,
            ]
        ];

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

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

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

        return $response;
    }

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

        $data = [
            'contents' => $contents,
            'systemInstruction' => [
                'parts' => [['text' => $systemPrompt]]
            ],
            'generationConfig' => [
                'maxOutputTokens' => $this->maxTokens,
                'temperature' => $this->temperature,
            ]
        ];

        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');

        $url = "{$this->apiBaseUrl}/{$this->model}:generateContent?key={$this->apiKey}";
        $ch = curl_init($url);

        $headers = [
            'Content-Type: application/json'
        ];

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        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 ($error) {
            error_log("Gemini API cURL Error: " . $error);
            return false;
        }

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

        $result = json_decode($response, true);

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

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