<?php
/*
desenvolvedor: luciano donizeti
mania de script: www.maniadescript.com.br
whatsapp 43998240911
*/

/**
 * Helper para criacao automatica de cards com IA.
 * Mantem a configuracao em arquivo local para nao exigir alteracao manual no banco.
 */

function aiCardConfigDir(): string {
    $dir = __DIR__ . '/api/ai_cards';
    if (!is_dir($dir)) { @mkdir($dir, 0755, true); }
    $index = $dir . '/index.php';
    if (!is_file($index)) { @file_put_contents($index, '<?php http_response_code(403); exit; ?>'); }
    $htaccess = $dir . '/.htaccess';
    if (!is_file($htaccess)) { @file_put_contents($htaccess, "Deny from all\n"); }
    return $dir;
}

function aiCardConfigPath(): string {
    return aiCardConfigDir() . '/config.json';
}

function aiCardDefaultConfig(): array {
    return [
        'provider' => 'openai',
        'api_url' => 'https://api.openai.com/v1/images/generations',
        'api_key' => getenv('OPENAI_API_KEY') ?: '',
        'model' => 'gpt-image-1',
        'size' => '1024x1024',
        'quality' => 'medium',
        'style' => 'premium_esportivo',
        'save_key' => true,
    ];
}

function aiCardAvailableProviders(): array {
    return [
        'openai' => 'OpenAI / API paga',
        'pollinations' => 'Alternativa sem chave / gratuita',
    ];
}

function aiCardProviderNeedsKey(string $provider): bool {
    return strtolower(trim($provider)) === 'openai';
}

function aiCardProviderDefaultUrl(string $provider): string {
    $provider = strtolower(trim($provider));
    if ($provider === 'pollinations') {
        return 'https://image.pollinations.ai/prompt';
    }
    return 'https://api.openai.com/v1/images/generations';
}

function aiCardNormalizeProvider(string $provider): string {
    $provider = strtolower(trim($provider));
    $providers = aiCardAvailableProviders();
    return array_key_exists($provider, $providers) ? $provider : 'openai';
}

function aiCardLoadConfig(): array {
    $config = aiCardDefaultConfig();
    $file = aiCardConfigPath();
    if (is_file($file)) {
        $data = json_decode((string)@file_get_contents($file), true);
        if (is_array($data)) { $config = array_merge($config, $data); }
    }
    $config['provider'] = aiCardNormalizeProvider((string)($config['provider'] ?? 'openai'));
    if (trim((string)($config['api_url'] ?? '')) === '') {
        $config['api_url'] = aiCardProviderDefaultUrl((string)$config['provider']);
    }
    return $config;
}

function aiCardSaveConfig(array $config): bool {
    $safe = aiCardDefaultConfig();
    foreach (['provider','api_url','api_key','model','size','quality','style','save_key'] as $key) {
        if (array_key_exists($key, $config)) { $safe[$key] = $config[$key]; }
    }
    $safe['provider'] = aiCardNormalizeProvider((string)$safe['provider']);
    $safe['api_url'] = trim((string)$safe['api_url']);
    if ($safe['api_url'] === '') { $safe['api_url'] = aiCardProviderDefaultUrl((string)$safe['provider']); }
    $safe['api_key'] = trim((string)$safe['api_key']);
    $safe['model'] = trim((string)$safe['model']);
    if ($safe['model'] === '') { $safe['model'] = $safe['provider'] === 'pollinations' ? 'flux' : 'gpt-image-1'; }
    $safe['size'] = trim((string)$safe['size']);
    $safe['quality'] = trim((string)$safe['quality']);
    $safe['style'] = trim((string)$safe['style']);
    $json = json_encode($safe, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    if ($json === false) { return false; }
    return (bool)@file_put_contents(aiCardConfigPath(), $json, LOCK_EX);
}

function aiCardMaskKey(string $key): string {
    $key = trim($key);
    if ($key === '') { return 'Nenhuma chave salva'; }
    $len = strlen($key);
    if ($len <= 12) { return substr($key, 0, 3) . str_repeat('*', max(0, $len - 3)); }
    return substr($key, 0, 7) . str_repeat('*', 8) . substr($key, -5);
}

function aiCardAvailableStyles(): array {
    return [
        'premium_esportivo' => 'Premium esportivo',
        'neon_futebol' => 'Neon futebol',
        'estadio_noite' => 'Estadio a noite',
        'dourado_luxo' => 'Dourado luxo',
        'verde_gramado' => 'Verde gramado',
        'azul_broadcast' => 'Azul transmissao',
        'derby_vermelho' => 'Derby vermelho',
        'minimalista_claro' => 'Minimalista claro',
        'cinematic_dark' => 'Cinematico dark',
        'brasil_tropical' => 'Brasil tropical',
    ];
}

function aiCardStylePrompt(string $style): string {
    $map = [
        'premium_esportivo' => 'visual esportivo premium, moldura moderna, brilho controlado, fundo de estadio desfocado, acabamento profissional de transmissao',
        'neon_futebol' => 'estetica neon, luzes azuis e roxas, energia urbana, reflexos, contraste alto, atmosfera futurista de futebol',
        'estadio_noite' => 'estadio de futebol a noite, refletores fortes, gramado escuro, arquibancada desfocada, clima de jogo importante',
        'dourado_luxo' => 'preto e dourado, luxo esportivo, detalhes metalizados, atmosfera de final de campeonato, acabamento elegante',
        'verde_gramado' => 'gramado vivo, linhas de campo, luz natural, textura esportiva limpa, visual organizado e profissional',
        'azul_broadcast' => 'azul de transmissao esportiva, paineis luminosos, grafismo de TV, fundo limpo para informacoes do jogo',
        'derby_vermelho' => 'vermelho intenso, energia de classico, faiscas sutis, sombras dramaticas, competicao forte',
        'minimalista_claro' => 'fundo claro elegante, grafismos esportivos discretos, layout limpo, contraste suave, visual moderno',
        'cinematic_dark' => 'cinematic dark, fumaça leve, luz lateral, textura premium, atmosfera de arena e suspense',
        'brasil_tropical' => 'cores inspiradas no futebol brasileiro, energia tropical, verde e amarelo equilibrados, visual alegre e premium',
    ];
    return $map[$style] ?? $map['premium_esportivo'];
}

function aiCardBuildPrompt(string $cardName, string $style, string $title, string $customPrompt): string {
    $title = trim($title);
    $customPrompt = trim($customPrompt);
    $stylePrompt = aiCardStylePrompt($style);
    $parts = [];
    $parts[] = "Crie uma imagem de fundo para um card de jogos de futebol chamado {$cardName}.";
    if ($title !== '') {
        $parts[] = "Tema/titulo criativo informado pelo usuario: {$title}.";
    }
    $parts[] = "Estilo visual: {$stylePrompt}.";
    $parts[] = "Composicao: card quadrado, area central e laterais organizadas para receber escudos, nomes dos times, horario, campeonato e canais depois pelo sistema.";
    $parts[] = "Nao coloque textos, palavras, numeros, nomes de clubes, marcas, logos oficiais, placar, datas, watermark ou elementos que pareçam texto.";
    $parts[] = "Use detalhes visuais esportivos, profundidade, brilho, sombra e acabamento profissional. Deixe espacos limpos para sobreposicao de conteudo.";
    $parts[] = "Imagem final limpa, sem bordas cortadas, alta qualidade, pronta para ser usada como background de card.";
    if ($customPrompt !== '') {
        $parts[] = "Instrucoes adicionais do usuario: {$customPrompt}";
    }
    return implode(' ', $parts);
}

function aiCardFetchUrl(string $url, int $timeout = 90) {
    $url = trim($url);
    if (!filter_var($url, FILTER_VALIDATE_URL)) { return false; }
    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS => 6,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_CONNECTTIMEOUT => 15,
            CURLOPT_TIMEOUT => $timeout,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) FutBanner/1.0',
            CURLOPT_HTTPHEADER => [
                'Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8',
                'Referer: https://www.google.com/'
            ],
        ]);
        $content = curl_exec($ch);
        $http = (int)curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
        curl_close($ch);
        return ($content !== false && $http < 400 && $content !== '') ? $content : false;
    }
    $context = stream_context_create([
        'http' => [
            'method' => 'GET',
            'timeout' => $timeout,
            'header' => "User-Agent: Mozilla/5.0 FutBanner/1.0\r\nAccept: image/*,*/*;q=0.8\r\n",
        ],
        'ssl' => ['verify_peer' => false, 'verify_peer_name' => false],
    ]);
    $content = @file_get_contents($url, false, $context);
    return $content === false ? false : $content;
}

function aiCardSaveImageAsPng(string $imageContent, string $fixedFilenameBase, ?string &$error = null): bool {
    $error = null;
    if ($imageContent === '') {
        $error = 'Imagem vazia.';
        return false;
    }
    $uploadPath = __DIR__ . '/fzstore/card/';
    if (!is_dir($uploadPath)) { @mkdir($uploadPath, 0755, true); }

    $img = @imagecreatefromstring($imageContent);
    if (!$img && class_exists('Imagick')) {
        try {
            $imagick = new Imagick();
            $imagick->readImageBlob($imageContent);
            $imagick->setImageFormat('png');
            $imageContent = $imagick->getImagesBlob();
            $imagick->clear();
            $imagick->destroy();
            $img = @imagecreatefromstring($imageContent);
        } catch (Throwable $e) {
            $img = false;
        }
    }

    if (!$img) {
        $error = 'A resposta recebida nao parece ser uma imagem valida.';
        return false;
    }

    imagealphablending($img, false);
    imagesavealpha($img, true);
    $dest = $uploadPath . $fixedFilenameBase . '.png';
    $ok = imagepng($img, $dest, 6);
    imagedestroy($img);
    if (!$ok) {
        $error = 'Nao foi possivel salvar o PNG do card.';
        return false;
    }
    @chmod($dest, 0644);

    foreach (['jpg','jpeg','gif','webp'] as $ext) {
        $old = $uploadPath . $fixedFilenameBase . '.' . $ext;
        if (is_file($old)) { @unlink($old); }
    }
    clearstatcache(true, $dest);
    return true;
}

function aiCardDownloadAndSaveUrl(string $imageUrl, string $fixedFilenameBase, ?string &$error = null): bool {
    $error = null;
    $content = aiCardFetchUrl($imageUrl, 45);
    if ($content === false || $content === '') {
        $error = 'Nao foi possivel baixar a imagem da URL informada.';
        return false;
    }
    return aiCardSaveImageAsPng((string)$content, $fixedFilenameBase, $error);
}

function aiCardParseSize(string $size): array {
    $size = strtolower(trim($size));
    if (preg_match('/^(\d{3,4})x(\d{3,4})$/', $size, $m)) {
        $w = max(256, min(1536, (int)$m[1]));
        $h = max(256, min(1536, (int)$m[2]));
        return [$w, $h];
    }
    return [1024, 1024];
}

function aiCardHumanizeApiError(string $message, int $http = 0, string $code = ''): string {
    $raw = trim($message !== '' ? $message : ($http ? 'HTTP ' . $http : 'erro desconhecido'));
    $check = strtolower($raw . ' ' . $code);

    if (strpos($check, 'billing hard limit') !== false || strpos($check, 'insufficient_quota') !== false || strpos($check, 'quota') !== false || strpos($check, 'usage limit') !== false) {
        return 'Erro da IA: a conta/API atingiu o limite de cobrança ou créditos. Solução: adicione saldo/aumente o limite no painel da OpenAI ou selecione o provedor "Alternativa sem chave / gratuita" neste formulário.';
    }
    if ($http === 401 || strpos($check, 'invalid api key') !== false || strpos($check, 'incorrect api key') !== false || strpos($check, 'unauthorized') !== false) {
        return 'Erro da IA: chave de API inválida ou sem permissão. Confira se a chave foi copiada completa e se pertence ao projeto correto.';
    }
    if ($http === 429 || strpos($check, 'rate limit') !== false || strpos($check, 'too many requests') !== false) {
        return 'Erro da IA: limite de requisições por minuto atingido. Aguarde um pouco ou use outro modelo/provedor.';
    }
    if ($http >= 500) {
        return 'Erro da IA: o servidor do provedor respondeu com falha temporária. Tente novamente ou use outro provedor.';
    }
    return 'Erro da IA: ' . $raw;
}

function aiCardCallPollinations(array $config, string $prompt, ?string &$error = null): ?string {
    $error = null;
    [$width, $height] = aiCardParseSize((string)($config['size'] ?? '1024x1024'));
    $model = trim((string)($config['model'] ?? 'flux'));
    if ($model === '' || stripos($model, 'gpt') === 0 || stripos($model, 'dall-e') === 0) {
        $model = 'flux';
    }
    $baseUrl = trim((string)($config['api_url'] ?? '')) ?: aiCardProviderDefaultUrl('pollinations');
    $baseUrl = rtrim($baseUrl, '/');
    if (!filter_var($baseUrl, FILTER_VALIDATE_URL)) {
        $error = 'URL da IA alternativa invalida.';
        return null;
    }

    $seed = random_int(100000, 999999999);
    $params = http_build_query([
        'width' => $width,
        'height' => $height,
        'model' => $model,
        'nologo' => 'true',
        'private' => 'true',
        'safe' => 'true',
        'enhance' => 'true',
        'seed' => $seed,
    ]);
    $url = $baseUrl . '/' . rawurlencode($prompt) . '?' . $params;
    $binary = aiCardFetchUrl($url, 180);
    if ($binary === false || $binary === '') {
        $error = 'A IA alternativa sem chave nao retornou imagem. Tente novamente ou use a opcao URL/Upload manual.';
        return null;
    }
    return (string)$binary;
}

function aiCardCallOpenAiImageApi(array $config, string $prompt, ?string &$error = null): ?string {
    $error = null;
    $apiUrl = trim((string)($config['api_url'] ?? '')) ?: aiCardProviderDefaultUrl('openai');
    $apiKey = trim((string)($config['api_key'] ?? ''));
    $model = trim((string)($config['model'] ?? 'gpt-image-1')) ?: 'gpt-image-1';
    $size = trim((string)($config['size'] ?? '1024x1024')) ?: '1024x1024';
    $quality = trim((string)($config['quality'] ?? 'medium')) ?: 'medium';

    if ($apiKey === '') {
        $error = 'Informe e salve a chave da OpenAI antes de gerar o card ou selecione o provedor "Alternativa sem chave / gratuita".';
        return null;
    }
    if (!filter_var($apiUrl, FILTER_VALIDATE_URL)) {
        $error = 'URL da API de IA invalida.';
        return null;
    }

    $payload = [
        'model' => $model,
        'prompt' => $prompt,
        'n' => 1,
        'size' => $size,
    ];

    $modelLower = strtolower($model);
    if (strpos($modelLower, 'dall-e-3') === 0) {
        $payload['response_format'] = 'b64_json';
        if (in_array($quality, ['standard', 'hd'], true)) { $payload['quality'] = $quality; }
        $payload['style'] = 'vivid';
    } elseif (strpos($modelLower, 'dall-e-2') === 0) {
        $payload['response_format'] = 'b64_json';
    } else {
        $payload['output_format'] = 'png';
        if (in_array($quality, ['low','medium','high','auto'], true)) { $payload['quality'] = $quality; }
    }

    $jsonPayload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    if ($jsonPayload === false) {
        $error = 'Falha ao montar o pedido da IA.';
        return null;
    }

    if (!function_exists('curl_init')) {
        $error = 'A extensao cURL do PHP precisa estar ativa para usar a IA.';
        return null;
    }

    $ch = curl_init($apiUrl);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $jsonPayload,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $apiKey,
        ],
        CURLOPT_CONNECTTIMEOUT => 20,
        CURLOPT_TIMEOUT => 180,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
    ]);
    $response = curl_exec($ch);
    $curlError = curl_error($ch);
    $http = (int)curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);

    if ($response === false || $response === '') {
        $error = 'A IA nao respondeu. Erro cURL: ' . ($curlError ?: 'desconhecido');
        return null;
    }

    $data = json_decode((string)$response, true);
    if (!is_array($data)) {
        $error = 'Resposta invalida da IA. HTTP ' . $http;
        return null;
    }
    if ($http >= 400 || isset($data['error'])) {
        $msg = $data['error']['message'] ?? ('HTTP ' . $http);
        $code = (string)($data['error']['code'] ?? '');
        $error = aiCardHumanizeApiError((string)$msg, $http, $code);
        return null;
    }

    $first = $data['data'][0] ?? null;
    if (!is_array($first)) {
        $error = 'A IA nao retornou imagem.';
        return null;
    }

    if (!empty($first['b64_json'])) {
        $binary = base64_decode((string)$first['b64_json'], true);
        if ($binary === false || $binary === '') {
            $error = 'Base64 retornado pela IA e invalido.';
            return null;
        }
        return $binary;
    }

    if (!empty($first['url']) && filter_var($first['url'], FILTER_VALIDATE_URL)) {
        $binary = aiCardFetchUrl((string)$first['url'], 90);
        if ($binary === false || $binary === '') {
            $error = 'A IA retornou uma URL, mas nao foi possivel baixar a imagem gerada.';
            return null;
        }
        return (string)$binary;
    }

    $error = 'A IA respondeu sem b64_json ou URL de imagem.';
    return null;
}

function aiCardCallImageApi(array $config, string $prompt, ?string &$error = null): ?string {
    $error = null;
    $provider = aiCardNormalizeProvider((string)($config['provider'] ?? 'openai'));
    if ($provider === 'pollinations') {
        return aiCardCallPollinations($config, $prompt, $error);
    }
    return aiCardCallOpenAiImageApi($config, $prompt, $error);
}
