<?php

namespace OtomaticAi\Utils;

use Exception;
use OtomaticAi\Vendors\Illuminate\Support\Arr;

class Image
{
    private $content;
    private $mimeType;
    private $attachmentId;

    public static array $models = [
        "dall_e_2" => ["provider" => "dall_e", "model" => "dall-e-2"],
        "dall_e_3" => ["provider" => "dall_e", "model" => "dall-e-3"],
        "gpt_image_1_low" => ["provider" => "dall_e", "model" => "gpt-image-1", "params" => ["quality" => "low"]],
        "gpt_image_1_medium" => ["provider" => "dall_e", "model" => "gpt-image-1", "params" => ["quality" => "medium"]],
        "gpt_image_1_high" => ["provider" => "dall_e", "model" => "gpt-image-1", "params" => ["quality" => "high"]],
        "gpt_image_1_5_low" => ["provider" => "dall_e", "model" => "gpt-image-1.5", "params" => ["quality" => "low"]],
        "gpt_image_1_5_medium" => ["provider" => "dall_e", "model" => "gpt-image-1.5", "params" => ["quality" => "medium"]],
        "gpt_image_1_5_high" => ["provider" => "dall_e", "model" => "gpt-image-1.5", "params" => ["quality" => "high"]],
        "gpt_image_2_low" => ["provider" => "dall_e", "model" => "gpt-image-2", "params" => ["quality" => "low"]],
        "gpt_image_2_medium" => ["provider" => "dall_e", "model" => "gpt-image-2", "params" => ["quality" => "medium"]],
        "gpt_image_2_high" => ["provider" => "dall_e", "model" => "gpt-image-2", "params" => ["quality" => "high"]],
        "stable_diffusion_sdxl" => ["provider" => "stable_diffusion", "model" => "sdxl"],
        "stable_diffusion_core" => ["provider" => "stable_diffusion", "model" => "core"],
        "stable_diffusion_sd3_medium" => ["provider" => "stable_diffusion", "model" => "sd3-medium"],
        "stable_diffusion_sd3_large" => ["provider" => "stable_diffusion", "model" => "sd3-large"],
        "stable_diffusion_sd3_large_turbo" => ["provider" => "stable_diffusion", "model" => "sd3-large-turbo"],
        "stable_diffusion_sd3_5_medium" => ["provider" => "stable_diffusion", "model" => "sd3.5-medium"],
        "stable_diffusion_sd3_5_large" => ["provider" => "stable_diffusion", "model" => "sd3.5-large"],
        "stable_diffusion_sd3_5_large_turbo" => ["provider" => "stable_diffusion", "model" => "sd3.5-large-turbo"],
        "stable_diffusion_ultra" => ["provider" => "stable_diffusion", "model" => "ultra"],
        "ideogram_v_1" => ["provider" => "ideogram", "model" => "V_1"],
        "ideogram_v_1_turbo" => ["provider" => "ideogram", "model" => "V_1_TURBO"],
        "ideogram_v_2" => ["provider" => "ideogram", "model" => "V_2"],
        "ideogram_v_2_turbo" => ["provider" => "ideogram", "model" => "V_2_TURBO"],
        "ideogram_v_2a" => ["provider" => "ideogram", "model" => "V_2A"],
        "ideogram_v_2a_turbo" => ["provider" => "ideogram", "model" => "V_2A_TURBO"],
        "ideogram_v_3" => ["provider" => "ideogram", "model" => "ideogram-v3", "params" => ["rendering_speed" => "BALANCED"]],
        "ideogram_v_3_turbo" => ["provider" => "ideogram", "model" => "ideogram-v3", "params" => ["rendering_speed" => "TURBO"]],
        "ideogram_v_3_quality" => ["provider" => "ideogram", "model" => "ideogram-v3", "params" => ["rendering_speed" => "QUALITY"]],
        "flux_1_dev" => ["provider" => "flux", "model" => "flux-dev"],
        "flux_1_pro" => ["provider" => "flux", "model" => "flux-pro"],
        "flux_1_1_pro" => ["provider" => "flux", "model" => "flux-pro-1.1"],
        "flux_1_1_pro_ultra" => ["provider" => "flux", "model" => "flux-pro-1.1-ultra"],
        "flux_2_pro" => ["provider" => "flux", "model" => "flux-2-pro"],
        "flux_2_flex" => ["provider" => "flux", "model" => "flux-2-flex"],
        "flux_kontext_pro" => ["provider" => "flux", "model" => "flux-kontext-pro"],
        "flux_kontext_max" => ["provider" => "flux", "model" => "flux-kontext-max"],
        "grok_2_image" => ["provider" => "grok", "model" => "grok-2-image"],
        "grok_imagine_pro" => ["provider" => "grok", "model" => "grok-imagine-image-pro"],
        "grok_imagine" => ["provider" => "grok", "model" => "grok-imagine-image"],
        "gemini_2_5_flash_image" => ["provider" => "gemini", "model" => "gemini-2.5-flash-image"],
        "gemini_3_pro_image" => ["provider" => "gemini", "model" => "gemini-3-pro-image-preview"],
        "gemini_3_1_flash_image" => ["provider" => "gemini", "model" => "gemini-3.1-flash-image-preview"],
        "unsplash" => ["provider" => "unsplash", "model" => "unsplash"],
        "pexels" => ["provider" => "pexels", "model" => "pexels"],
        "pixabay" => ["provider" => "pixabay", "model" => "pixabay"],
        "google_image" => ["provider" => "google_image", "model" => "google_image"],
        "bing_image" => ["provider" => "bing_image", "model" => "bing_image"],
    ];

    public static array $convertModels = [
        "dall-e-2" => "dall_e_2",
        "dall-e-3" => "dall_e_3",
        "sdxl" => "stable_diffusion_sdxl",
        "stable_image_core" => "stable_diffusion_core",
        "stable_image_sd3_medium" => "stable_diffusion_sd3_medium",
        "stable_image_sd3_large" => "stable_diffusion_sd3_large",
        "stable_image_sd3_large_turbo" => "stable_diffusion_sd3_large_turbo",
        "stable_image_sd3_5_large" => "stable_diffusion_sd3_5_large",
        "stable_image_sd3_5_large_turbo" => "stable_diffusion_sd3_5_large_turbo",
        "stable_image_ultra" => "stable_diffusion_ultra",
        'gpt_image_1_5_low' => 'gpt_image_2_low',
        'gpt_image_1_5_medium' => 'gpt_image_2_medium',
        'gpt_image_1_5_high' => 'gpt_image_2_high',
    ];

    public function __construct($content, $mimeType = "image/jpeg")
    {
        $this->content = $content;
        $this->mimeType = $mimeType;
    }

    public function save($name, $description = null, $legend = null)
    {
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        require_once(ABSPATH . 'wp-admin/includes/post.php');

        if ($this->attachmentId === null) {
            $extension = $this->mimeTypeToExtension($this->mimeType);

            // store media
            $uploadBits = wp_upload_bits($name . '.' . $extension, null, $this->content);

            if (!$uploadBits['error']) {
                $wpFileType = wp_check_filetype($uploadBits["file"], null);

                $attachment = [
                    'guid'           => $uploadBits["file"],
                    'post_mime_type' => $wpFileType['type'],
                    'post_title'     => $name,
                    'post_content'   => '',
                    'post_status'    => 'inherit',
                ];
                if (!empty($legend)) {
                    $attachment["post_excerpt"] = $legend;
                }

                $attachmentId = wp_insert_attachment($attachment, $uploadBits["file"]);

                if (!is_wp_error($attachmentId)) {

                    // fire wp_handle_upload filter
                    apply_filters('wp_handle_upload', [
                        'file' => $uploadBits["file"],
                        'url'  => $uploadBits["url"],
                        'type' => $wpFileType['type']
                    ]);
                    require_once ABSPATH . 'wp-admin/includes/image.php';

                    // generate attachment metadata
                    $attachmentMetadata = wp_generate_attachment_metadata($attachmentId, $uploadBits["file"]);
                    wp_update_attachment_metadata($attachmentId, $attachmentMetadata);

                    if (!empty($description)) {
                        update_post_meta($attachmentId, '_wp_attachment_image_alt', $description);
                    }
                    $this->attachmentId = $attachmentId;
                }
            }
        }

        return $this->attachmentId;
    }

    public function getAttachmentId()
    {
        return $this->attachmentId;
    }

    static public function fromUrl($url)
    {
        $mediaFile = wp_remote_get($url);
        if (is_wp_error($mediaFile)) {
            throw new Exception("Can not download image url `" . $url . "`. Error: " . $mediaFile->get_error_message());
        }
        return new self($mediaFile["body"], Arr::get($mediaFile, 'headers.content-type', 'image/jpeg'));
    }

    static public function fromPath($path)
    {
        $mediaFile = file_get_contents($path);
        if ($mediaFile === false) {
            throw new Exception("Can not load image path `" . $path . "`.");
        }
        $f = finfo_open();
        return new self($mediaFile, finfo_buffer($f, $mediaFile, FILEINFO_MIME_TYPE));
    }

    static public function fromBase64($base64)
    {
        // Supprime le préfixe "data:image/...;base64,"
        if (preg_match('/^data:image\/\w+;base64,/', $base64)) {
            $base64 = preg_replace('/^data:image\/\w+;base64,/', '', $base64);
        }

        $content = base64_decode($base64);
        $f = finfo_open();
        return new self($content, finfo_buffer($f, $content, FILEINFO_MIME_TYPE));
    }

    static public function fromAttachmentId($attachmentId)
    {
        $image = new self(wp_get_attachment_url($attachmentId), get_post_mime_type($attachmentId));
        $image->attachmentId = $attachmentId;

        return $image;
    }

    static private function mimeTypeToExtension($mime)
    {
        $mimeTypes = [
            'image/png' => 'png',
            'image/jpeg' => 'jpg',
            'image/gif' => 'gif',
            'image/bmp' => 'bmp',
            'image/vnd.microsoft.icon' => 'ico',
            'image/tiff' => 'tif',
            'image/svg+xml' => 'svg',
            'image/webp' => 'webp',
        ];
        $extension = str_replace(
            array_keys($mimeTypes),
            array_values($mimeTypes),
            $mime,
            $count
        );
        // set default fileExtension if not found
        if ((int) $count == 0) {
            $extension = 'jpg';
        }

        return $extension;
    }

    static function imageModelToProviderAndModel(string $imageModel): ?array
    {
        return Arr::get(self::$models, $imageModel, ["provider" => "dall_e", "model" => "dall-e-3"]);
    }

    static function imageProviderAndModelToModel(string $provider = null, string $model = null): ?string
    {
        foreach (self::$models as $key => $value) {
            if ($value["provider"] === $provider && (empty($model) || $value["model"] === $model)) {
                return $key;
            }
        }

        if (!empty($model) && isset(self::$convertModels[$model])) {
            return self::$convertModels[$model];
        }

        if (!empty($model) && isset(self::$models[$model])) {
            return $model;
        }

        return "dall_e_3";
    }
}
