<?php
namespace Peak;

class ImageGenerator {
    public static function handleRequest(): void {
        $raw = file_get_contents('php://input');
        if (!$raw) Response::error('Empty request body', 400);
        $data = json_decode($raw, true);
        if (!$data) Response::error('Invalid JSON: ' . substr($raw, 0, 200), 400);
        $prompt = trim($data['prompt'] ?? '');
        $model = $data['model'] ?? 'google/gemini-2.5-flash-image';
        if (!$prompt) Response::error('Prompt is required');

        if (strpos($model, 'pollinations') === 0) {
            self::generatePollinations($prompt, $model);
        } elseif (in_array($model, ['free', 'flux-free', 'seedream'])) {
            self::generateFreeSVG($prompt);
        } elseif (strpos($model, 'google/') === 0) {
            self::generateViaGemini($prompt, $model);
        } else {
            self::generateViaOpenRouter($prompt, $model);
        }
    }

    private static function generateFreeSVG(string $prompt): void {
        $svgPrompt = 'Generate ONLY valid SVG code. Make a beautiful, detailed SVG image of: ' . $prompt . '. Return ONLY raw SVG markup starting with <svg and ending with </svg>. No HTML, no markdown, no explanation.';
        $body = json_encode([
            'model' => 'openrouter/free',
            'messages' => [['role' => 'user', 'content' => $svgPrompt]],
            'max_tokens' => 2000,
        ]);
        $ch = curl_init('https://openrouter.ai/api/v1/chat/completions');
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . Config::$OPENROUTER_API_KEY, 'Content-Type: application/json'],
            CURLOPT_POSTFIELDS => $body,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 120,
            CURLOPT_SSL_VERIFYPEER => false,
        ]);
        $resp = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curlErr = curl_error($ch);
        curl_close($ch);
        if ($resp === false) Response::error('Free service: curl_error: ' . ($curlErr ?: 'unknown'), 503);
        if ($code < 200 || $code >= 300) Response::error("Free service: http_{$code}: " . substr($resp, 0, 300), 503);
        $parsed = json_decode($resp, true);
        $svg = $parsed['choices'][0]['message']['content'] ?? '';
        $svg = preg_replace('/^.*?(<svg)/s', '$1', $svg);
        $svg = preg_replace('/(<\/svg>).*$/s', '$1', $svg);
        if (strpos($svg, '<svg') !== false) {
            $b64 = base64_encode($svg);
            Response::json(['data' => [['url' => "data:image/svg+xml;base64,{$b64}"]]]);
        }
        Response::error('Free service: no SVG tag in response', 503);
    }

    private static function generatePollinations(string $prompt, string $model): void {
        $seed = crc32($prompt) & 0x7fffffff;
        $encoded = urlencode($prompt);
        $pollModel = 'turbo';
        $width = 1024;
        $height = 1024;
        switch ($model) {
            case 'pollinations-flux':
                $pollModel = 'flux';
                $width = 1024; $height = 1024;
                break;
            case 'pollinations-flux-realism':
                $pollModel = 'flux-realism';
                $width = 1024; $height = 1024;
                break;
            case 'pollinations-flux-pro':
                $pollModel = 'flux-pro';
                $width = 1024; $height = 1024;
                break;
        }
        $imageUrl = "https://image.pollinations.ai/prompt/{$encoded}?width={$width}&height={$height}&model={$pollModel}&nologo=true&seed={$seed}&enhance=true";
        Response::json(['data' => [['url' => $imageUrl]]]);
    }

    private static function generateViaOpenRouter(string $prompt, string $model): void {
        $body = json_encode([
            'model' => $model,
            'messages' => [['role' => 'user', 'content' => $prompt]],
            'max_tokens' => 200,
        ]);
        if (!function_exists('curl_init')) Response::error('cURL not available on this server', 500);
        $ch = curl_init('https://openrouter.ai/api/v1/chat/completions');
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . Config::$OPENROUTER_API_KEY, 'Content-Type: application/json'],
            CURLOPT_POSTFIELDS => $body,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 120,
            CURLOPT_SSL_VERIFYPEER => false,
        ]);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        if ($response === false) Response::error('cURL error: ' . ($error ?: 'Unknown error'), 502);
        if ($httpCode < 200 || $httpCode >= 300) {
            $parsed = json_decode($response, true);
            $msg = $parsed['error']['message'] ?? $parsed['error'] ?? substr($response, 0, 500);
            Response::error('Image generation failed: ' . $msg, 502);
        }
        $parsed = json_decode($response, true);
        if (!$parsed) Response::error('Invalid API response', 502);
        $images = [];
        $choice = $parsed['choices'][0]['message'] ?? [];
        foreach ((array)($choice['images'] ?? []) as $img) {
            if (!empty($img['image_url']['url'])) $images[] = ['url' => $img['image_url']['url']];
        }
        foreach ((array)($choice['content_parts'] ?? []) as $part) {
            if (($part['type'] ?? '') === 'image_url' && !empty($part['image_url']['url'])) $images[] = ['url' => $part['image_url']['url']];
        }
        Response::json(['data' => $images]);
    }

    private static function resolveGeminiModel(string $model): string {
        $m = str_replace('google/', '', $model);
        $map = [
            'gemini-2.5-flash-preview-image' => 'gemini-2.5-flash-image',
            'gemini-2.5-flash-image' => 'gemini-2.5-flash-image',
            'gemini-3-pro-image' => 'gemini-3-pro-image',
            'gemini-3.1-flash-image' => 'gemini-3.1-flash-image',
            'gemini-3-pro-image-preview' => 'gemini-3-pro-image-preview',
            'gemini-3.1-flash-image-preview' => 'gemini-3.1-flash-image-preview',
            'imagen-4-ultra-generate' => 'gemini-2.5-flash-image',
            'imagen-4-generate' => 'gemini-2.5-flash-image',
            'imagen-4-fast-generate' => 'gemini-2.5-flash-image',
        ];
        return $map[$m] ?? 'gemini-2.5-flash-image';
    }

    private static function generateViaGemini(string $prompt, string $model): void {
        $googleModel = self::resolveGeminiModel($model);
        $url = 'https://generativelanguage.googleapis.com/v1beta/models/' . $googleModel . ':generateContent?key=' . Config::$GEMINI_API_KEY;
        $body = json_encode([
            'contents' => [['parts' => [['text' => $prompt]]]],
            'generationConfig' => ['responseModalities' => ['Text', 'Image']]
        ]);
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_POSTFIELDS => $body,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 60,
            CURLOPT_SSL_VERIFYPEER => false,
        ]);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        if ($response === false) Response::error('Gemini: connection error: ' . ($error ?: 'unknown'), 502);
        if ($httpCode < 200 || $httpCode >= 300) {
            $parsed = json_decode($response, true);
            $msg = $parsed['error']['message'] ?? $parsed['error'] ?? substr($response, 0, 500);
            if ($httpCode === 429) {
                Response::error('Gemini: Quota exceeded. Use Puter.js models (sign-in required) or SVG AI for free unlimited generation.', 429);
            }
            Response::error('Gemini: ' . $msg, 502);
        }
        $parsed = json_decode($response, true);
        if (!$parsed) Response::error('Gemini: invalid response', 502);
        $images = [];
        foreach ($parsed['candidates'] ?? [] as $c) {
            foreach ($c['content']['parts'] ?? [] as $p) {
                if (!empty($p['inlineData']['data'])) {
                    $images[] = ['url' => 'data:' . $p['inlineData']['mimeType'] . ';base64,' . $p['inlineData']['data']];
                }
            }
        }
        if (!empty($images)) Response::json(['data' => $images]);
        $text = $parsed['candidates'][0]['content']['parts'][0]['text'] ?? '';
        if ($text) {
            $svg = preg_replace('/^.*?(<svg)/s', '$1', $text);
            $svg = preg_replace('/(<\/svg>).*$/s', '$1', $svg);
            if (strpos($svg, '<svg') !== false) {
                Response::json(['data' => [['url' => 'data:image/svg+xml;base64,' . base64_encode($svg)]]]);
            }
            Response::error('Gemini: no image in response: ' . mb_substr($text, 0, 200), 503);
        }
        Response::error('Gemini: no image generated', 503);
    }
}
