#!/usr/bin/env php
<?php
/**
 * ptyAIGetMessage
 *
 * AI API를 통해 메시지를 전송하고 응답을 받는 CLI 도구
 *
 * 설정 파일: ~/.ptyAIConfig.ini
 *
 * Usage: ./ptyAIGetMessage "메시지" [--ai=섹션명] [--verbose]
 *
 * 지원 provider:
 * - anthropic: Claude API
 * - openai: ChatGPT API
 * - google: Gemini API
 */

namespace platyFramework;

require_once __DIR__ . '/ptyLibrary_PHP/cli/ptyCliOptionParser.php';
require_once __DIR__ . '/ptyLibrary_PHP/ai/ptyAIConfig.php';

// 인자 파싱
$parsed = ptyCliOptionParser::parse($argv);
$positionalArgs = $parsed['positional'];
$options = $parsed['options'];
$aiSection = $options['ai'] ?? 'default';
$modelOverride = $options['model'] ?? null;
$anthropicBetaOverride = $options['anthropic-beta'] ?? null;
$verbose = isset($options['verbose']);
$jsonOutput = isset($options['json']);

// --edit 옵션: vi로 설정 파일 열기
if (isset($options['edit'])) {
    $configPath = ptyAIConfig::getConfigPath();
    passthru("vi " . escapeshellarg($configPath));
    exit(0);
}

// 도움말
if (isset($options['help'])) {
    fwrite(STDERR, "사용법: {$argv[0]} [\"메시지\"] [옵션]\n");
    fwrite(STDERR, "\n");
    fwrite(STDERR, "AI API를 통해 메시지를 전송하고 응답을 받습니다.\n");
    fwrite(STDERR, "메시지 인자가 없으면 stdin에서 읽습니다 (Ctrl+D로 완료).\n");
    fwrite(STDERR, "\n");
    fwrite(STDERR, "옵션:\n");
    fwrite(STDERR, "  --ai=섹션명              INI 파일 섹션 (기본값: default)\n");
    fwrite(STDERR, "  --model=모델명            모델 오버라이드\n");
    fwrite(STDERR, "  --anthropic-beta=기능명   Claude 베타 기능 오버라이드\n");
    fwrite(STDERR, "  --verbose                상세 정보 출력 (토큰 사용량, curl 등)\n");
    fwrite(STDERR, "  --json                   JSON 형식으로 출력\n");
    fwrite(STDERR, "  --edit                   설정 파일을 vi로 열기\n");
    fwrite(STDERR, "  --help                   도움말 출력\n");
    fwrite(STDERR, "\n");
    fwrite(STDERR, "모델 예시:\n");
    fwrite(STDERR, "  anthropic: claude-sonnet-4-5-20250514, claude-3-5-sonnet-20241022, claude-3-opus-20240229\n");
    fwrite(STDERR, "  openai: gpt-4o, gpt-4-turbo, gpt-3.5-turbo\n");
    fwrite(STDERR, "  google: gemini-2.0-flash-exp, gemini-1.5-pro, gemini-1.5-flash\n");
    fwrite(STDERR, "  ollama: llama3, mistral, codellama, gemma2\n");
    fwrite(STDERR, "\n");
    fwrite(STDERR, "anthropic-beta 예시:\n");
    fwrite(STDERR, "  context-1m-2025-08-07, interleaved-thinking-2025-05-14, max-tokens-3-5-sonnet-2024-07-15\n");
    fwrite(STDERR, "\n");
    fwrite(STDERR, "입력 방법:\n");
    fwrite(STDERR, "  {$argv[0]} --ai=openai                             # stdin에서 입력 (Ctrl+D로 완료)\n");
    fwrite(STDERR, "  {$argv[0]} --ai=openai < prompt.txt                # 파일에서 입력 (리다이렉션)\n");
    fwrite(STDERR, "  cat prompt.txt | {$argv[0]} --ai=openai            # 파일에서 입력 (파이프)\n");
    fwrite(STDERR, "  {$argv[0]} \"\$(pbpaste)\" --ai=openai                # 클립보드에서 입력 (macOS)\n");
    fwrite(STDERR, "  {$argv[0]} \"\$(xclip -o)\" --ai=openai               # 클립보드에서 입력 (Linux)\n");
    fwrite(STDERR, "\n");

    // 현재 설정 파일 내용 표시
    $configPath = ptyAIConfig::getConfigPath();
    if (file_exists($configPath)) {
        fwrite(STDERR, "현재 설정 파일: {$configPath}\n");
        fwrite(STDERR, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
        $sections = parse_ini_file($configPath, true);
        if ($sections) {
            foreach ($sections as $name => $config) {
                $provider = $config['provider'] ?? '(없음)';
                $model = $config['model'] ?? ptyAIConfig::getDefaultModel($provider);
                $apiKey = isset($config['apiKey']) ? substr($config['apiKey'], 0, 8) . '...' : null;
                $apiUrl = $config['apiUrl'] ?? null;
                $anthropicBeta = $config['anthropic-beta'] ?? null;
                fwrite(STDERR, "[{$name}]\n");
                fwrite(STDERR, "  provider: {$provider}\n");
                fwrite(STDERR, "  model: {$model}\n");
                if ($apiKey) {
                    fwrite(STDERR, "  apiKey: {$apiKey}\n");
                }
                if ($apiUrl) {
                    fwrite(STDERR, "  apiUrl: {$apiUrl}\n");
                }
                if ($anthropicBeta) {
                    fwrite(STDERR, "  anthropic-beta: {$anthropicBeta}\n");
                }
            }
        }
        fwrite(STDERR, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
    } else {
        fwrite(STDERR, "설정 파일 없음: {$configPath}\n");
        fwrite(STDERR, "\n");
        fwrite(STDERR, ptyAIConfig::getConfigExample() . "\n");
    }
    exit(0);
}

// 메시지 입력: 인자 또는 stdin
if (empty($positionalArgs)) {
    // stdin에서 읽기
    if (posix_isatty(STDIN)) {
        fwrite(STDERR, "메시지를 입력하세요 (Ctrl+D로 완료):\n");
    }
    $message = file_get_contents('php://stdin');
    $message = trim($message);
    if (empty($message)) {
        fwrite(STDERR, "Error: 메시지가 필요합니다.\n");
        fwrite(STDERR, "도움말: {$argv[0]} --help\n");
        exit(1);
    }
} else {
    $message = $positionalArgs[0];
}

try {
    // AI 클라이언트 연결
    $connection = ptyAIConfig::connect($aiSection);
    $client = $connection['client'];
    $config = $connection['config'];

    // 모델 오버라이드
    if ($modelOverride) {
        $client->setModel($modelOverride);
        $config['model'] = $modelOverride;
    }

    // anthropic-beta 오버라이드 (anthropic만 해당)
    if ($anthropicBetaOverride !== null && $config['provider'] === 'anthropic') {
        $client->setAnthropicBeta($anthropicBetaOverride);
        $config['anthropic-beta'] = $anthropicBetaOverride;
    }

    // 디버그 모드 (verbose일 때 curl 정보 출력)
    if ($verbose && method_exists($client, 'setDebug')) {
        $client->setDebug(true);
    }

    if ($verbose) {
        fwrite(STDERR, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
        fwrite(STDERR, "Provider: {$config['provider']}\n");
        fwrite(STDERR, "Model: {$config['model']}\n");
        fwrite(STDERR, "Section: {$aiSection}\n");
        if (!empty($config['anthropic-beta'])) {
            fwrite(STDERR, "anthropic-beta: {$config['anthropic-beta']}\n");
        }
        fwrite(STDERR, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
        fwrite(STDERR, "Message: " . mb_substr($message, 0, 100) . (mb_strlen($message) > 100 ? '...' : '') . "\n");
        fwrite(STDERR, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
        fwrite(STDERR, "API 호출 중...\n");
    }

    $startTime = microtime(true);

    // 메시지 전송 및 응답 받기 (전체 응답)
    $response = $client->get($message);

    $elapsed = round((microtime(true) - $startTime) * 1000);

    if ($response === false) {
        fwrite(STDERR, "Error: AI API 호출에 실패했습니다.\n");
        exit(1);
    }

    // 텍스트 추출
    $text = $client->extractText($response);

    if ($text === false) {
        fwrite(STDERR, "Error: 응답에서 텍스트를 추출할 수 없습니다.\n");
        if ($verbose) {
            fwrite(STDERR, "Response: " . json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n");
        }
        exit(1);
    }

    // 토큰 사용량 추출
    $usage = extractUsage($response, $config['provider']);

    if ($verbose) {
        fwrite(STDERR, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
        fwrite(STDERR, "응답 시간: {$elapsed}ms\n");

        if ($usage) {
            fwrite(STDERR, "토큰 사용량:\n");
            fwrite(STDERR, "  - 입력: {$usage['input']} tokens\n");
            fwrite(STDERR, "  - 출력: {$usage['output']} tokens\n");
            fwrite(STDERR, "  - 합계: {$usage['total']} tokens\n");
        }

        fwrite(STDERR, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
    }

    // JSON 출력
    if ($jsonOutput) {
        $output = [
            'request' => [
                'provider' => $config['provider'],
                'model' => $config['model'],
                'message' => $message,
            ],
            'response' => [
                'message' => $text,
                'elapsed_ms' => $elapsed,
                '_api_result' => $response,
            ],
        ];

        // anthropic-beta 추가 (있을 경우만)
        if (!empty($config['anthropic-beta'])) {
            $output['request']['anthropic-beta'] = $config['anthropic-beta'];
        }

        // 토큰 정보 추가
        if ($usage) {
            $output['response']['tokens'] = [
                'in' => $usage['input'],
                'out' => $usage['output'],
                'total' => $usage['total'],
            ];
        }

        echo json_encode($output, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
    } else {
        // 응답만 출력 (다른 메시지 없이)
        echo $text;
    }

} catch (\Exception $e) {
    fwrite(STDERR, "Error: " . $e->getMessage() . "\n");
    exit(1);
}

/**
 * API 응답에서 토큰 사용량 추출
 */
function extractUsage($response, $provider)
{
    switch ($provider) {
        case 'anthropic':
            // Claude: usage.input_tokens, usage.output_tokens
            if (isset($response['usage'])) {
                $input = $response['usage']['input_tokens'] ?? 0;
                $output = $response['usage']['output_tokens'] ?? 0;
                return [
                    'input' => $input,
                    'output' => $output,
                    'total' => $input + $output,
                ];
            }
            break;

        case 'openai':
            // ChatGPT: usage.prompt_tokens, usage.completion_tokens, usage.total_tokens
            if (isset($response['usage'])) {
                return [
                    'input' => $response['usage']['prompt_tokens'] ?? 0,
                    'output' => $response['usage']['completion_tokens'] ?? 0,
                    'total' => $response['usage']['total_tokens'] ?? 0,
                ];
            }
            break;

        case 'google':
            // Gemini: usageMetadata.promptTokenCount, usageMetadata.candidatesTokenCount
            if (isset($response['usageMetadata'])) {
                $input = $response['usageMetadata']['promptTokenCount'] ?? 0;
                $output = $response['usageMetadata']['candidatesTokenCount'] ?? 0;
                return [
                    'input' => $input,
                    'output' => $output,
                    'total' => $response['usageMetadata']['totalTokenCount'] ?? ($input + $output),
                ];
            }
            break;

        case 'ollama':
            // Ollama: prompt_eval_count, eval_count
            $input = $response['prompt_eval_count'] ?? 0;
            $output = $response['eval_count'] ?? 0;
            return [
                'input' => $input,
                'output' => $output,
                'total' => $input + $output,
            ];
    }

    return null;
}
