<?php

namespace Core\App\Services;

class GeminiImageService
{
    private array $settings;

    public function __construct()
    {
        $this->settings = $this->loadGeminiSettings();
    }

    public function getUiConfig(): array
    {
        $apiKey = trim((string)($this->settings['api_key'] ?? ''));
        $enabled = (int)($this->settings['image_generation_enabled'] ?? 0) === 1;
        $model = trim((string)($this->settings['image_model'] ?? ''));

        return [
            'has_api_key' => $apiKey !== '',
            'enabled' => $enabled,
            'model' => $model,
            'available' => $apiKey !== '' && $enabled && $model !== '',
        ];
    }

    public function generateProductImages(string $sourceImagePath, string $productName, string $productDescription, array $requestedTypes): array
    {
        $config = $this->getUiConfig();
        if (!$config['available']) {
            throw new \RuntimeException(__('products.ai_images_not_configured', 'Gemini image generation is not configured.'));
        }

        $resolvedPath = $this->resolveLocalPath($sourceImagePath);
        if (!is_file($resolvedPath)) {
            throw new \RuntimeException(__('products.ai_images_source_missing', 'Source image was not found.'));
        }

        $binary = (string)@file_get_contents($resolvedPath);
        if ($binary === '') {
            throw new \RuntimeException(__('products.ai_images_source_invalid', 'Unable to read the source image.'));
        }

        $imageInfo = @getimagesize($resolvedPath);
        if (!is_array($imageInfo) || empty($imageInfo['mime'])) {
            throw new \RuntimeException(__('products.ai_images_source_invalid', 'Unable to validate the source image.'));
        }

        $results = [];
        $requestedTypes = array_values(array_intersect($requestedTypes, array_keys($this->getImageTypeDefinitions())));
        if (empty($requestedTypes)) {
            throw new \RuntimeException(__('products.ai_images_type_required', 'Select at least one image type.'));
        }

        foreach ($requestedTypes as $type) {
            $payload = $this->requestGeneratedImage($binary, (string)$imageInfo['mime'], $productName, $productDescription, $type);
            $results[] = [
                'type' => $type,
                'mime' => $payload['mime'],
                'data' => $payload['data'],
                'label' => $this->getImageTypeDefinitions()[$type]['label'],
            ];
        }

        return $results;
    }

    public function getImageTypeDefinitions(): array
    {
        return [
            'hero' => [
                'label' => __('products.ai_image_type_hero', 'Hero Image'),
                'prompt' => 'Create a premium hero marketing image for the product, suitable for the top section of a landing page. Keep the product recognizable and dominant.',
            ],
            'lifestyle' => [
                'label' => __('products.ai_image_type_lifestyle', 'Lifestyle Image'),
                'prompt' => 'Create a realistic lifestyle image showing the product in use in a believable everyday setting. Keep the product faithful to the reference image.',
            ],
            'square_ad' => [
                'label' => __('products.ai_image_type_square', 'Square Ad Image'),
                'prompt' => 'Create a square advertising visual for social media. Keep the composition strong and centered, with the product as the hero.',
            ],
            'clean_product' => [
                'label' => __('products.ai_image_type_clean', 'Clean Product Image'),
                'prompt' => 'Create a clean studio product image with a polished background and sharp focus on the product only.',
            ],
        ];
    }

    private function requestGeneratedImage(string $imageBinary, string $imageMime, string $productName, string $productDescription, string $type): array
    {
        $definition = $this->getImageTypeDefinitions()[$type] ?? null;
        if (!$definition) {
            throw new \RuntimeException(__('products.ai_images_type_invalid', 'Invalid image type requested.'));
        }

        $prompt = implode("\n\n", [
            'You are generating a commercial marketing image variation from the provided reference image.',
            'Product name: ' . trim($productName),
            'Product description: ' . trim($productDescription),
            'Required output type: ' . $definition['label'],
            'Instruction: ' . $definition['prompt'],
            'Rules:',
            '- Preserve the identity of the product shown in the reference image.',
            '- Do not add visible text, logos, price tags, or watermarks.',
            '- Return an image only.',
        ]);

        $url = 'https://generativelanguage.googleapis.com/v1beta/models/'
            . rawurlencode((string)$this->settings['image_model'])
            . ':generateContent?key=' . rawurlencode((string)$this->settings['api_key']);

        $body = [
            'contents' => [[
                'role' => 'user',
                'parts' => [
                    ['text' => $prompt],
                    ['inline_data' => [
                        'mime_type' => $imageMime,
                        'data' => base64_encode($imageBinary),
                    ]],
                ],
            ]],
            'generationConfig' => [
                'temperature' => 0.6,
            ],
        ];

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_POSTFIELDS => json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
            CURLOPT_TIMEOUT => 120,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_SSL_VERIFYHOST => 2,
        ]);

        $response = curl_exec($ch);
        $status = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);

        if ($response === false || $error !== '') {
            throw new \RuntimeException(__('products.ai_images_network_error', 'Failed to reach Gemini image generation service.') . ' ' . $error);
        }

        $decoded = json_decode((string)$response, true);
        if (!is_array($decoded)) {
            throw new \RuntimeException(__('products.ai_images_invalid_response', 'Gemini returned an invalid response.'));
        }

        if ($status >= 400) {
            $message = $decoded['error']['message'] ?? __('products.ai_images_generation_failed', 'Gemini image generation failed.');
            throw new \RuntimeException((string)$message);
        }

        foreach (($decoded['candidates'] ?? []) as $candidate) {
            foreach (($candidate['content']['parts'] ?? []) as $part) {
                $inline = $part['inlineData'] ?? $part['inline_data'] ?? null;
                if (!is_array($inline) || empty($inline['data'])) {
                    continue;
                }

                return [
                    'mime' => (string)($inline['mimeType'] ?? $inline['mime_type'] ?? 'image/png'),
                    'data' => (string)$inline['data'],
                ];
            }
        }

        throw new \RuntimeException(__('products.ai_images_no_output', 'Gemini did not return a generated image.'));
    }

    private function loadGeminiSettings(): array
    {
        $stmt = \db()->prepare('SELECT * FROM ai_settings WHERE provider = ? LIMIT 1');
        $stmt->execute(['gemini']);
        $row = $stmt->fetch(\PDO::FETCH_ASSOC);

        return is_array($row) ? $row : [];
    }

    private function resolveLocalPath(string $path): string
    {
        $path = trim($path);
        if ($path === '') {
            return '';
        }

        if (strpos($path, ROOT_PATH) === 0) {
            return $path;
        }

        if (strpos($path, '/uploads/') === 0) {
            return ROOT_PATH . $path;
        }

        return $path;
    }
}
