<?php
// system/library/OpenAIImage.php
class OpenAIImage {
    private $apiKey;
    private $apiBase;

    public function __construct($apiKey, $apiBase = 'https://api.openai.com/v1') {
        $this->apiKey  = $apiKey;
        $this->apiBase = rtrim($apiBase, '/');
    }

    /* ---------- HTTP yardımcıları ---------- */

    /** URL'den resmi indirir, içerik tipini kontrol eder, geçici dosyaya yazar. */
    public function downloadImageToTemp(string $url, int $maxBytes = 15_000_000): string {
        // Basit URL doğrulama
        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            throw new Exception('Geçersiz URL.');
        }

        $ch = curl_init($url);
        $tmp = tempnam(sys_get_temp_dir(), 'oa_in_');
        $fp  = fopen($tmp, 'wb');

        curl_setopt_array($ch, [
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS      => 5,
            CURLOPT_CONNECTTIMEOUT => 15,
            CURLOPT_TIMEOUT        => 60,
            CURLOPT_USERAGENT      => 'OpenCart-OpenAIImage/1.0',
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_FILE           => $fp,
            CURLOPT_NOPROGRESS     => false,
            CURLOPT_PROGRESSFUNCTION => function($res, $dlTotal, $dlNow) use ($maxBytes) {
                if ($dlNow > $maxBytes) { return 1; } // abort
                return 0;
            },
            CURLOPT_HEADERFUNCTION => function($ch, $header) use (&$ctype) {
                if (stripos($header, 'Content-Type:') === 0) {
                    $ctype = trim(substr($header, 13));
                }
                return strlen($header);
            }
        ]);

        $ok = curl_exec($ch);
        $err = curl_error($ch);
        $code= curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        fclose($fp);

        if (!$ok || $code >= 400) {
            @unlink($tmp);
            throw new Exception('Görsel indirilemedi: ' . ($err ?: 'HTTP '.$code));
        }
        // Tipi kendimiz de tespit edelim
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime  = finfo_file($finfo, $tmp);
        finfo_close($finfo);

        $allowed = ['image/png','image/jpeg','image/webp'];
        if (!in_array($mime, $allowed)) {
            @unlink($tmp);
            throw new Exception('Desteklenmeyen görsel türü: ' . $mime);
        }
        return $tmp;
    }

    /** Dosyanın PNG olmasını garanti eder; değilse PNG'ye çevirir ve yeni yol döndürür. */
    public function ensurePng(string $path): string {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime  = finfo_file($finfo, $path);
        finfo_close($finfo);

        if ($mime === 'image/png') return $path;

        // Imagick varsa onu dene
        if (class_exists('Imagick')) {
            $img = new Imagick($path);
            $img->setImageFormat('png');
            $out = $path . '.png';
            $img->writeImage($out);
            $img->destroy();
            return $out;
        }

        // GD fallback (JPEG/WEBP → PNG)
        $im = null;
        if ($mime === 'image/jpeg') {
            $im = imagecreatefromjpeg($path);
        } elseif ($mime === 'image/webp' && function_exists('imagecreatefromwebp')) {
            $im = imagecreatefromwebp($path);
        } else {
            throw new Exception('PNG’ye dönüştürülemedi (GD/Imagick yok ya da format desteklenmiyor).');
        }
        if (!$im) throw new Exception('Görsel açılamadı.');

        imagesavealpha($im, true);
        $out = $path . '.png';
        imagepng($im, $out, 6);
        imagedestroy($im);
        return $out;
    }

    /* ---------- OpenAI çağrıları ---------- */

    private function request($endpoint, $fields, $isMultipart = true) {
        $ch = curl_init();
        $headers = [
            'Authorization: Bearer ' . $this->apiKey,
        ];
        if (!$isMultipart) {
            $headers[] = 'Content-Type: application/json';
        }

        curl_setopt_array($ch, [
            CURLOPT_URL            => $this->apiBase . $endpoint,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST           => true,
            CURLOPT_HTTPHEADER     => $headers,
            CURLOPT_POSTFIELDS     => $isMultipart ? $fields : json_encode($fields),
            CURLOPT_TIMEOUT        => 120,
        ]);

        $resp = curl_exec($ch);
        if ($resp === false) {
            $err = curl_error($ch);
            curl_close($ch);
            throw new Exception('cURL error: ' . $err);
        }
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $json = json_decode($resp, true);
        if ($code >= 400) {
            throw new Exception('OpenAI API error (' . $code . '): ' . $resp);
        }
        return $json;
    }

    /** Variations: referans PNG’nin “benzerini” üretir. */

    public function createVariationFromUrl(string $imageUrl, string $size = '1024x1024', int $n = 1)
    {
        $endpoint = 'https://api.openai.com/v1/images/variations';

        // Görseli indirip dosya olarak gönder
        $tmp = tempnam(sys_get_temp_dir(), 'img');
        file_put_contents($tmp, file_get_contents($imageUrl));

        $payload = [
            'model' => 'gpt-image-1',        // model
            'n'     => $n,                   // isteğe bağlı
            'size'  => $size,                // 256x256 | 512x512 | 1024x1024 (kare)
            // DİKKAT: variations'ta prompt YOK!
            'image' => new CURLFile($tmp, mime_content_type($tmp) ?: 'image/png', 'image.png'),
        ];

        $ch = curl_init($endpoint);
        curl_setopt_array($ch, [
            CURLOPT_HTTPHEADER    => ['Authorization: Bearer ' . $this->apiKey],
            CURLOPT_POST          => true,
            CURLOPT_POSTFIELDS    => $payload,          // multipart/form-data otomatik
            CURLOPT_RETURNTRANSFER=> true,
        ]);

        $res = curl_exec($ch);
        $err = curl_error($ch);
        curl_close($ch);
        @unlink($tmp);

        if ($err) {
            throw new \Exception('cURL error: ' . $err);
        }
        $json = json_decode($res, true);
        if (isset($json['error'])) {
            throw new \Exception('OpenAI API error: ' . $res);
        }
        return $json;
    }

    /** Edits: URL’den indirilen baz görsel + (opsiyonel) maske URL. */
    public function editFromUrls(string $imageUrl, ?string $maskUrl, string $prompt, string $size='1024x1024', int $n=1, string $model='gpt-image-1'): array {
        $baseTmp = $this->ensurePng($this->downloadImageToTemp($imageUrl));
        $fields = [
            'model'  => $model,
            'image'  => new CURLFile($baseTmp, 'image/png', basename($baseTmp)),
            'prompt' => $prompt,
            'n'      => (string)$n,
            'size'   => $size,
        ];
        if ($maskUrl) {
            $maskTmp = $this->ensurePng($this->downloadImageToTemp($maskUrl));
            $fields['mask'] = new CURLFile($maskTmp, 'image/png', basename($maskTmp));
        }
        $json = $this->request('/images/edits', $fields, true);
        $out = [];
        foreach ($json['data'] as $item) { $out[] = $item['b64_json']; }
        return $out;
    }

    /** Base64 PNG’yi dosyaya kaydet. */
    public function saveBase64Png($b64, $targetPath) {
        $bin = base64_decode($b64);
        if ($bin === false) throw new Exception('Base64 decode failed.');
        $dir = dirname($targetPath);
        if (!is_dir($dir)) mkdir($dir, 0755, true);
        file_put_contents($targetPath, $bin);
        return $targetPath;
    }
}
