<?php
// Secure JSON Output Guarantee
header('Content-Type: application/json');

// Catch any fatal errors and turn them into JSON
register_shutdown_function(function() {
    $error = error_get_last();
    if ($error !== null && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE])) {
        echo json_encode([
            'success' => false,
            'error' => 'Backend Error: ' . $error['message'],
            'type' => 'fatal_crash'
        ]);
    }
});

require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../includes/db.php';

// Allow GET for listing models, POST for generation
$requestMethod = $_SERVER['REQUEST_METHOD'];
$action = $_GET['action'] ?? null;

if ($requestMethod !== 'POST' && $action !== 'list_models') {
    http_response_code(405);
    echo json_encode(['error' => 'Method not allowed']);
    exit;
}

$data = [];
if ($requestMethod === 'POST') {
    $data = json_decode(file_get_contents('php://input'), true) ?? [];
}
$prompt = $data['prompt'] ?? '';
$mode = $data['mode'] ?? 'chat'; // 'chat' or 'generate'

// Fetch AI settings
$settings = [];
$rows = Database::fetchAll("SELECT setting_key, setting_value FROM settings WHERE setting_group = 'ai'");
foreach ($rows as $row) {
    $settings[$row['setting_key']] = $row['setting_value'];
}

$provider = $settings['ai_provider'] ?? 'gemini';
$geminiKey = $settings['gemini_api_key'] ?? '';
$openaiKey = $settings['openai_api_key'] ?? '';
$persona = $settings['chatbot_persona'] ?? "You are a technical assistant.";

if ($action === 'list_models') {
    try {
        $reqProvider = $_GET['provider'] ?? $provider;
        if ($reqProvider === 'openai') {
            $key = $_GET['api_key'] ?? $openaiKey;
            if (!$key) throw new Exception("API Key is required to fetch models.");
            $models = listOpenAIModels($key);
        } elseif ($reqProvider === 'custom') {
            $baseUrl = $_GET['api_base'] ?? ($settings['custom_api_base'] ?? '');
            $key = $_GET['api_key'] ?? ($settings['custom_api_key'] ?? '');
            if (!$baseUrl) throw new Exception("Custom Base URL is required to fetch models.");
            $models = listCustomModels($baseUrl, $key);
        } else {
            $key = $_GET['api_key'] ?? $geminiKey;
            if (!$key) throw new Exception("API Key is required to fetch models.");
            $models = listGeminiModels($key);
        }
        echo json_encode(['success' => true, 'models' => $models]);
    } catch (Exception $e) {
        echo json_encode(['success' => false, 'error' => $e->getMessage()]);
    }
    exit;
}

if (!$prompt) {
    echo json_encode(['error' => 'Prompt is required']);
    exit;
}

if ($provider === 'openai' && !$openaiKey) {
    echo json_encode(['error' => 'OpenAI API key not configured']);
    exit;
}
if ($provider === 'gemini' && !$geminiKey) {
    echo json_encode(['error' => 'Gemini API key not configured']);
    exit;
}
if ($provider === 'custom' && empty($settings['custom_api_base'])) {
    echo json_encode(['error' => 'Custom API Base URL not configured']);
    exit;
}

// Get chosen model from settings (with defaults)
$geminiModel = $settings['gemini_model'] ?? 'gemini-1.5-flash';
$openaiModel = $settings['openai_model'] ?? 'gpt-4o';
$customModel = $settings['custom_model'] ?? '';

try {
    if ($provider === 'openai') {
        $response = callOpenAI($openaiKey, $prompt, $persona, $mode, $openaiModel);
    } elseif ($provider === 'custom') {
        $customBaseUrl = $settings['custom_api_base'] ?? '';
        $customKey = $settings['custom_api_key'] ?? '';
        $response = callCustom($customBaseUrl, $customKey, $prompt, $persona, $mode, $customModel);
    } else {
        $response = callGemini($geminiKey, $prompt, $persona, $mode, $geminiModel);
    }
    echo json_encode(['success' => true, 'response' => $response, 'provider' => $provider]);
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode(['error' => $e->getMessage()]);
}
exit;

function callOpenAI($key, $prompt, $persona, $mode, $model) {
    $url = 'https://api.openai.com/v1/chat/completions';
    $messages = [
        ['role' => 'system', 'content' => $persona],
        ['role' => 'user', 'content' => $prompt]
    ];

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'model' => $model,
        'messages' => $messages,
        'temperature' => 0.7
    ]));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'Authorization: Bearer ' . $key
    ]);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);

    $result = curl_exec($ch);
    if (curl_errno($ch)) throw new Exception(curl_error($ch));
    curl_close($ch);

    $json = json_decode($result, true);
    return $json['choices'][0]['message']['content'] ?? 'Error: No response from OpenAI';
}

function callGemini($key, $prompt, $persona, $mode, $model) {
    $url = "https://generativelanguage.googleapis.com/v1/models/" . $model . ":generateContent?key=" . $key;
    
    $fullPrompt = "Instructions: " . $persona . "\n\nUser Input: " . $prompt;

    $data = [
        'contents' => [
            ['parts' => [['text' => $fullPrompt]]]
        ],
        'generationConfig' => [
            'temperature' => 0.7,
            'maxOutputTokens' => 2048
        ]
    ];

    $ch = curl_init($url);
    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, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);

    $result = curl_exec($ch);
    if (curl_errno($ch)) throw new Exception(curl_error($ch));
    curl_close($ch);

    $json = json_decode($result, true);
    if (isset($json['candidates'][0]['content']['parts'][0]['text'])) {
        return $json['candidates'][0]['content']['parts'][0]['text'];
    }
    
    if (isset($json['error'])) {
        throw new Exception($json['error']['message']);
    }
    
    return 'Error: No response from Gemini';
}

function listOpenAIModels($key) {
    $url = 'https://api.openai.com/v1/models';
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $key]);
    $result = curl_exec($ch);
    if (curl_errno($ch)) throw new Exception(curl_error($ch));
    curl_close($ch);
    $json = json_decode($result, true);
    
    $models = [];
    foreach ($json['data'] ?? [] as $m) {
        if (strpos($m['id'], 'gpt') !== false) {
            $models[] = $m['id'];
        }
    }
    sort($models);
    return $models;
}

function listGeminiModels($key) {
    $url = "https://generativelanguage.googleapis.com/v1/models?key=" . $key;
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    if (curl_errno($ch)) throw new Exception(curl_error($ch));
    curl_close($ch);
    $json = json_decode($result, true);
    
    $models = [];
    foreach ($json['models'] ?? [] as $m) {
        $parts = explode('/', $m['name']);
        $id = end($parts);
        if (strpos($id, 'gemini') !== false && in_array('generateContent', $m['supportedGenerationMethods'] ?? [])) {
            $models[] = $id;
        }
    }
    sort($models);
    return $models;
}

function listCustomModels($baseUrl, $key) {
    $url = getCustomEndpoint($baseUrl, 'models');
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    $headers = [];
    if (!empty($key)) {
        $headers[] = 'Authorization: Bearer ' . $key;
    }
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    
    $result = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if (curl_errno($ch)) throw new Exception(curl_error($ch));
    curl_close($ch);
    
    if ($httpCode >= 400) {
        throw new Exception("HTTP error $httpCode from custom provider endpoint. Check your Base URL and Key.");
    }
    
    $json = json_decode($result, true);
    if (!is_array($json)) {
        throw new Exception("Invalid JSON returned from Custom API models endpoint.");
    }
    
    $models = [];
    foreach ($json['data'] ?? [] as $m) {
        if (isset($m['id'])) {
            $models[] = $m['id'];
        }
    }
    sort($models);
    return $models;
}

function callCustom($baseUrl, $key, $prompt, $persona, $mode, $model) {
    $url = getCustomEndpoint($baseUrl, 'chat/completions');
    $messages = [
        ['role' => 'system', 'content' => $persona],
        ['role' => 'user', 'content' => $prompt]
    ];

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
        'model' => $model,
        'messages' => $messages,
        'temperature' => 0.7
    ]));
    
    $headers = [
        'Content-Type: application/json'
    ];
    if (!empty($key)) {
        $headers[] = 'Authorization: Bearer ' . $key;
    }
    
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);

    $result = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if (curl_errno($ch)) throw new Exception(curl_error($ch));
    curl_close($ch);

    if ($httpCode >= 400) {
        $errResponse = json_decode($result, true);
        $errMsg = $errResponse['error']['message'] ?? $errResponse['error'] ?? $result;
        throw new Exception("HTTP error $httpCode from custom provider: " . $errMsg);
    }

    $json = json_decode($result, true);
    return $json['choices'][0]['message']['content'] ?? 'Error: No response from Custom AI';
}

function getCustomEndpoint($baseUrl, $endpoint) {
    $baseUrl = rtrim(trim($baseUrl), '/');
    if (preg_match('/\/chat\/completions$/i', $baseUrl)) {
        $baseUrl = substr($baseUrl, 0, -17);
    }
    if (preg_match('/\/models$/i', $baseUrl)) {
        $baseUrl = substr($baseUrl, 0, -7);
    }
    $baseUrl = rtrim($baseUrl, '/');
    return $baseUrl . '/' . $endpoint;
}
