<?php
// Fetch all blog posts, sorted alphabetically
$posts = get_posts([
    'post_type'      => 'post',
    'posts_per_page' => -1,
    'orderby'        => 'title',
    'order'          => 'ASC'
]);

// Fetch all pages, sorted alphabetically
$pages = get_posts([
    'post_type'      => 'page',
    'posts_per_page' => -1,
    'orderby'        => 'title',
    'order'          => 'ASC'
]);

$options_html = '';

// Create optgroup for Blogs if posts exist
if ($posts) {
    $options_html .= '<optgroup label="Blogs">';
    foreach ($posts as $post) {
        $options_html .= '<option value="' . $post->ID . '">' . esc_html(get_the_title($post)) . '</option>';
    }
    $options_html .= '</optgroup>';
}

// Create optgroup for Pages if pages exist
if ($pages) {
    $options_html .= '<optgroup label="Pages">';
    foreach ($pages as $page) {
        $options_html .= '<option value="' . $page->ID . '">' . esc_html(get_the_title($page)) . '</option>';
    }
    $options_html .= '</optgroup>';
}
?>
<script>
// This variable now holds alphabetized options with Blogs and Pages separated.
var blogPagesOptions = <?php echo json_encode($options_html); ?>;
</script>

<div class="wrap">
    <h1>Inception Image Importer & Converter</h1>

    <!-- Initially hidden "Working On it" GIF -->
    <div id="gif-container" style="opacity: 0; height: 0; overflow: hidden; transition: opacity 1s, height 1s;">
        <p><img src="<?php echo plugins_url('../search-and-replace/working-on-it.gif', __FILE__); ?>" alt="Working on it" style="width: 400px;" /></p>
    </div>

    <!-- Cropper.js (for visual crop selection) -->
    <link rel="stylesheet" href="https://unpkg.com/cropperjs@1.6.2/dist/cropper.min.css">
    <script src="https://unpkg.com/cropperjs@1.6.2/dist/cropper.min.js"></script>

    <!-- Crop modal -->
    <div id="inceptionCropModal" style="display:none; position:fixed; inset:0; background:rgba(0,0,0,.7); z-index:100000;">
        <div id="inceptionCropDialog" style="background:#fff; max-width: 980px; margin: 40px auto; padding: 16px; border-radius: 8px;">
            <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom: 10px;">
                <strong>Adjust Crop <span id="inceptionCropOutputLabel" style="font-weight:normal; color:#666;">(final output: 714×250)</span></strong>
            </div>
            <div style="display:flex; gap:16px;">
                <div style="flex:1; min-width: 0;">
                    <img id="inceptionCropImage" src="" style="max-width:100%; display:block;">
                </div>
                <div style="width: 290px;">
                    <div style="margin:0 0 12px 0;">
                        <div style="font-weight:600; margin-bottom:6px;">Crop size</div>
                        <label style="display:block; margin-bottom:6px;">
                            <input type="radio" name="inceptionCropMode" value="banner" id="inceptionCropModeBanner" checked>
                            714×250 (Hero Images)
                        </label>
                        <label style="display:block; margin-bottom:6px;">
                            <input type="radio" name="inceptionCropMode" value="square" id="inceptionCropModeSquare">
                            400×400 (Square)
                        </label>
                        <label style="display:block; margin-bottom:8px;">
                            <input type="radio" name="inceptionCropMode" value="custom" id="inceptionCropModeCustom">
                            Custom
                        </label>

                        <div id="inceptionCropCustomWrap" style="display:none; padding:10px; border:1px solid #dcdcde; border-radius:6px;">
                            <div style="display:flex; gap:8px;">
                                <div style="flex:1;">
                                    <label style="display:block; font-size:12px; color:#555; margin-bottom:4px;">Width</label>
                                    <input type="number" min="1" step="1" id="inceptionCropCustomW" value="714" style="width:100%;">
                                </div>
                                <div style="flex:1;">
                                    <label style="display:block; font-size:12px; color:#555; margin-bottom:4px;">Height</label>
                                    <input type="number" min="1" step="1" id="inceptionCropCustomH" value="250" style="width:100%;">
                                </div>
                            </div>
                            <p style="margin:8px 0 0 0; font-size:12px; color:#666;">The crop box will lock to this aspect ratio.</p>
                        </div>
                    </div>

                    <p style="margin-top:0;">Drag / resize the box to choose what stays.</p>
                    <button type="button" class="button button-primary" id="inceptionCropSaveBtn" style="width:100%;">Save Crop</button>
                    <button type="button" class="button" id="inceptionCropNoCropBtn" style="width:100%; margin-top:8px;">Save Without Cropping</button>
                    <hr>
                    <p style="font-size:12px; color:#666; margin:0;">
                        Tip: If the image is smaller than the selected output size, the plugin will still try to crop/resize, but the quality may suffer.
                    </p>
                </div>
            </div>
        </div>
    </div>

    <p>Please upload your images or choose from the Image Library and add your Titles & Alt Text for each one. When you're ready to import them to the Media Library, click the Submit button. This will convert the images you're importing to .webp files!</p>
    <p><strong>Important:</strong> You can select multiple items while uploading or in the Image Library by either holding the Shift key or holding the Ctrl key!</p>

    <br>

    <input type="text" id="optimizationField" class="optimizationField" placeholder="Optimization" style="width:300px; margin-left: 10px;">
    <input type="text" id="cityField" class="cityField" placeholder="City" style="width:300px; margin-left: 10px;">
    <input type="text" id="stateField" class="stateField" placeholder="State" style="width:300px; margin-left: 10px;">

    <button type="button" id="applyOptimizationButton" class="button button-secondary" onclick="applyOptimization()" style="margin-left: 10px;">Apply Optimization</button>

    <script>
    function applyOptimization() {
        const optimization = document.getElementById('optimizationField')?.value.trim();
        const city = document.getElementById('cityField')?.value.trim();
        const state = document.getElementById('stateField')?.value.trim();

        const parts = [];
        if (optimization) parts.push(optimization);
        if (city) parts.push(city);
        if (state) parts.push(state);

        const prefix = parts.join(' ');

        if (prefix) {
            const uploadedtitleInputs = document.querySelectorAll('input[name^="uploadedtitles"]');
            const uploadedaltInputs = document.querySelectorAll('input[name^="uploadedalts"]');
            const selectedtitleInputs = document.querySelectorAll('input[name^="selectedtitles"]');
            const selectedaltInputs = document.querySelectorAll('input[name^="selectedalts"]');

            uploadedtitleInputs.forEach(input => {
                if (!input.value.startsWith(prefix)) input.value = `${prefix} ${input.value}`.trim();
            });

            uploadedaltInputs.forEach(input => {
                if (!input.value.startsWith(prefix)) input.value = `${prefix} ${input.value}`.trim();
            });

            selectedtitleInputs.forEach(input => {
                if (!input.value.startsWith(prefix)) input.value = `${prefix} ${input.value}`.trim();
            });

            selectedaltInputs.forEach(input => {
                if (!input.value.startsWith(prefix)) input.value = `${prefix} ${input.value}`.trim();
            });
        }
    }
    </script>

    <br><br>

    <!-- File Upload Form -->
    <form id="imageForm" method="post" enctype="multipart/form-data" style="display: flex; align-items: center; gap: 10px;">
        <input type="hidden" name="action" value="convert_images">
        <?php wp_nonce_field('convert_nonce'); ?>
        <input type="file" id="imageUpload" name="images[]" multiple accept=".png, .jpeg, .jpg, .webp" />
        <div id="hiddenUploadInputs"></div>
        <div id="hiddenSelectedInputs"></div>

        <br>

        <!-- Dropdown for selecting multiple images -->
        <select name="selectedImages[]" id="selectedImage" class="input-field" style="margin-left: -10px; min-height: 300px;" multiple>
            <?php
            $blog_template_list_path = plugin_dir_path(__FILE__) . '../blog-maker/blog-template-list.php';

            if (file_exists($blog_template_list_path)) {
                $images = include $blog_template_list_path;

                $groupedAndSortedOptions = [];

                if (isset($images) && is_array($images)) {
                    foreach ($images as $imageName => $imageData) {
                        if ($imageData['type'] === 'Images') {
                            $groupedAndSortedOptions[$imageData['imagegroup']][] = [
                                'id' => esc_url($imageData['id']),
                                'label' => esc_html($imageData['label']),
                            ];
                        }
                    }

                    ksort($groupedAndSortedOptions);

                    foreach ($groupedAndSortedOptions as $group => $options) {
                        echo '<optgroup label="' . esc_attr($group) . '">';
                        usort($options, function ($a, $b) {
                            return strcmp($a['label'], $b['label']);
                        });
                        foreach ($options as $option) {
                            echo '<option value="' . $option['id'] . '">' . $option['label'] . '</option>';
                        }
                        echo '</optgroup>';
                    }
                }
            } else {
                echo '<option value="">Error: Template file not found</option>';
            }
            ?>
        </select>

        <input type="text" id="imageSearch" class="search-input-field" placeholder="Search Image Library" style="width:300px; margin-left: 10px;">
        </div>

        <!-- Preview Area -->
        <div id="imagePreview" style="margin-top: 20px; display: flex; flex-direction: column;"></div>
        <input type="hidden" id="blogpages_debug" name="blogpages_debug" value="">

        <br>

        <div style="margin-top: 20px;">
            <input type="submit" value="Submit" class="button button-primary" onclick="return validateForm(event)">
        </div>
    </form>

<?php
// -----------------------------
// SERVER SIDE (PHP-only) IMPORT/CONVERT
// -----------------------------

if (!defined('INCEPTION_CROP_W')) define('INCEPTION_CROP_W', 714);
if (!defined('INCEPTION_CROP_H')) define('INCEPTION_CROP_H', 250);

/**
 * Create a filesystem-safe filename from a title (matches your bash script behavior closely):
 * - spaces => dashes
 * - remove apostrophes
 * - keep only [A-Za-z0-9-]
 */
if (!function_exists('inception_ic_slug_filename_from_title')) {
    function inception_ic_slug_filename_from_title($title) {
        $title = (string) $title;
        $title = str_replace("'", '', $title);
        $title = preg_replace('/\s+/', '-', $title);
        $title = preg_replace('/[^A-Za-z0-9\-]/', '', $title);
        $title = preg_replace('/\-+/', '-', $title);
        $title = trim($title, '-');
        if ($title === '') $title = 'image';
        return $title;
    }
}

/**
 * Apply a user-selected crop (and then resize) to a local image path.
 * $crop keys: x, y, width, height (in source pixels).
 * Returns new temp file path (in uploads) or original path on failure.
 */
if (!function_exists('inception_ic_apply_user_crop')) {
    function inception_ic_apply_user_crop($local_path, $crop, $upload_path, &$temp_files) {
        if (!is_string($local_path) || !file_exists($local_path) || empty($crop) || !is_array($crop)) {
            return $local_path;
        }

        $x = isset($crop['x']) ? (int) round($crop['x']) : 0;
        $y = isset($crop['y']) ? (int) round($crop['y']) : 0;
        $w = isset($crop['width']) ? (int) round($crop['width']) : 0;
        $h = isset($crop['height']) ? (int) round($crop['height']) : 0;

        // Target output size (defaults to Banner 714x250)
        $tw = isset($crop['target_w']) ? (int) round($crop['target_w']) : (int) INCEPTION_CROP_W;
        $th = isset($crop['target_h']) ? (int) round($crop['target_h']) : (int) INCEPTION_CROP_H;

        // Safety clamps
        if ($tw <= 0) $tw = (int) INCEPTION_CROP_W;
        if ($th <= 0) $th = (int) INCEPTION_CROP_H;
        if ($tw > 8000) $tw = 8000;
        if ($th > 8000) $th = 8000;

        if ($w <= 0 || $h <= 0) {
            return $local_path;
        }

        if ($w <= 0 || $h <= 0) {
            return $local_path;
        }

        // Try WP image editor first (normal path)
        $editor = wp_get_image_editor($local_path);
        if (is_wp_error($editor) || $editor === false || $editor === null) {
            $editor = null;
        }

        if ($editor) {
            $cropped = $editor->crop($x, $y, $w, $h);
            if (!is_wp_error($cropped)) {
                $resized = $editor->resize($tw, $th, false);
                if (!is_wp_error($resized)) {
                                        $pi = pathinfo($local_path);
                    $name = isset($pi['filename']) ? $pi['filename'] : 'image';

                    // Always save cropped intermediate as PNG (prevents WEBP->JPEG accidental fallback)
                    $target_name = sprintf('%s-%dx%d-usercrop.%s', $name, $tw, $th, 'png');
                    $target_name = wp_unique_filename($upload_path, $target_name);
                    $target_path = trailingslashit($upload_path) . $target_name;

                    // Force PNG mime for the intermediate
                    $saved = $editor->save($target_path, 'image/png');
                    if (!is_wp_error($saved) && file_exists($target_path)) {
                        $temp_files[] = $target_path;
                        return $target_path;
                    }

                    if (!is_wp_error($saved) && file_exists($target_path)) {
                        $temp_files[] = $target_path;
                        return $target_path;
                    }
                }
            }
        }

        // If we reach here, WP editor crop/resize/save failed (or editor not available). Try GD fallback (preserves PNG alpha).
        if (function_exists('imagecreatefromstring')) {
            $raw = @file_get_contents($local_path);
            if ($raw !== false) {
                $src_img = @imagecreatefromstring($raw);
                if ($src_img !== false) {
                    $dst = imagecreatetruecolor($tw, $th);
                    // Preserve alpha for PNG
                    imagesavealpha($dst, true);
                    $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127);
                    imagefill($dst, 0, 0, $transparent);

                    // Perform the crop+resample
                    $resample_ok = imagecopyresampled(
                        $dst,
                        $src_img,
                        0, 0,                // dst x,y
                        $x, $y,              // src x,y (crop start)
                        $tw, $th, // dst w,h (final size)
                        $w, $h               // src w,h (crop size)
                    );

                    if ($resample_ok) {
                         $pi = pathinfo($local_path);
                         $name = isset($pi['filename']) ? $pi['filename'] : 'image';

                         // Always save cropped intermediate as PNG (prevents WEBP->JPEG)
                         $target_name = sprintf('%s-%dx%d-usercrop.%s', $name, $tw, $th, 'png');
                         $target_name = wp_unique_filename($upload_path, $target_name);
                         $target_path = trailingslashit($upload_path) . $target_name;

                         // Save PNG (keeps alpha if present)
                         $saved = imagepng($dst, $target_path);

                        imagedestroy($dst);
                        imagedestroy($src_img);

                        if ($saved && file_exists($target_path)) {
                            $temp_files[] = $target_path;
                            return $target_path;
                        } else {
                            // fallback cleanup
                            @unlink($target_path);
                        }
                    } // resample_ok
                    @imagedestroy($src_img);
                } // src_img
            } // raw
        } // function_exists

        // Nothing worked — return original path
        return $local_path;
    }
}

/**
 * Bake EXIF orientation into JPEG pixels before crop/convert.
 *
 * Many phone photos store sideways pixels plus an EXIF Orientation flag. Browsers
 * honor that flag in the preview, but WebP conversion often drops it, making the
 * saved image appear rotated. Normalizing first makes the pixels match the preview.
 */
if (!function_exists('inception_ic_normalize_jpeg_orientation')) {
    function inception_ic_normalize_jpeg_orientation($local_path, $upload_path, &$temp_files) {
        if (!is_string($local_path) || !file_exists($local_path)) {
            return $local_path;
        }

        $img_info = @getimagesize($local_path);
        $mime = is_array($img_info) && !empty($img_info['mime']) ? $img_info['mime'] : '';
        if ($mime !== 'image/jpeg' || !function_exists('exif_read_data')) {
            return $local_path;
        }

        $exif = @exif_read_data($local_path);
        $orientation = is_array($exif) && !empty($exif['Orientation']) ? (int) $exif['Orientation'] : 1;
        if ($orientation < 2 || $orientation > 8) {
            return $local_path;
        }

        $editor = wp_get_image_editor($local_path);
        if (is_wp_error($editor) || !$editor) {
            return $local_path;
        }

        $changed = false;

        switch ($orientation) {
            case 2:
                $changed = !is_wp_error($editor->flip(true, false));
                break;
            case 3:
                $changed = !is_wp_error($editor->rotate(180));
                break;
            case 4:
                $changed = !is_wp_error($editor->flip(false, true));
                break;
            case 5:
                $changed = !is_wp_error($editor->flip(true, false));
                if ($changed) $changed = !is_wp_error($editor->rotate(270));
                break;
            case 6:
                $changed = !is_wp_error($editor->rotate(270));
                break;
            case 7:
                $changed = !is_wp_error($editor->flip(true, false));
                if ($changed) $changed = !is_wp_error($editor->rotate(90));
                break;
            case 8:
                $changed = !is_wp_error($editor->rotate(90));
                break;
        }

        if (!$changed) {
            return $local_path;
        }

        $pi = pathinfo($local_path);
        $name = isset($pi['filename']) ? $pi['filename'] : 'image';
        $target_name = wp_unique_filename($upload_path, $name . '-oriented.jpg');
        $target_path = trailingslashit($upload_path) . $target_name;

        if (method_exists($editor, 'set_quality')) {
            $editor->set_quality(95);
        }

        $saved = $editor->save($target_path, 'image/jpeg');
        if (!is_wp_error($saved) && file_exists($target_path)) {
            $temp_files[] = $target_path;
            return $target_path;
        }

        @unlink($target_path);
        return $local_path;
    }
}

/**
 * Download a remote image URL to a temp file.
 * - Tries WordPress HTTP first.
 * - If host is hero.inceptionimages.com AND curl exists, tries the two pinned IPs as fallback (like your bash script).
 * Returns temp filepath or WP_Error.
 */
if (!function_exists('inception_ic_download_remote_image')) {
    function inception_ic_download_remote_image($url) {
        $url = esc_url_raw($url);
        if (!$url) return new WP_Error('bad_url', 'Invalid URL');

        // 1) WP HTTP API attempt
        $resp = wp_remote_get($url, [
            'timeout' => 30,
            'redirection' => 5,
        ]);

        if (!is_wp_error($resp)) {
            $code = (int) wp_remote_retrieve_response_code($resp);
            $body = wp_remote_retrieve_body($resp);
            if ($code >= 200 && $code < 300 && is_string($body) && $body !== '') {
                $tmp = wp_tempnam($url);
                if (!$tmp) return new WP_Error('tmp_fail', 'Could not create temp file');
                file_put_contents($tmp, $body);
                return $tmp;
            }
        }

        // 2) curl fallback with IP pinning (best-effort)
        $host = wp_parse_url($url, PHP_URL_HOST);
        if ($host && function_exists('curl_init')) {
            $pins = [
                ['hero.inceptionimages.com', '18.214.60.67'],
                ['hero.inceptionimages.com', '67.225.142.253'],
            ];

            foreach ($pins as $pin) {
                [$pinHost, $pinIP] = $pin;
                if (strcasecmp($host, $pinHost) !== 0) continue;

                $tmp = wp_tempnam($url);
                if (!$tmp) continue;

                $fp = fopen($tmp, 'w');
                if (!$fp) {
                    @unlink($tmp);
                    continue;
                }

                $ch = curl_init($url);
                curl_setopt($ch, CURLOPT_FILE, $fp);
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
                curl_setopt($ch, CURLOPT_TIMEOUT, 30);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
                curl_setopt($ch, CURLOPT_RESOLVE, [$pinHost . ':443:' . $pinIP]);

                $ok = curl_exec($ch);
                $err = curl_error($ch);
                $http = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);

                curl_close($ch);
                fclose($fp);

                if ($ok && $http >= 200 && $http < 300 && filesize($tmp) > 0) {
                    return $tmp;
                }

                @unlink($tmp);
            }
        }

        return new WP_Error('download_failed', 'Could not download remote image.');
    }
}

// Convert an image file to webp (best-effort via WP image editor).
// Returns temp file path to the webp or WP_Error.
if (!function_exists('inception_ic_convert_to_webp_temp')) {
    function inception_ic_convert_to_webp_temp($source_path) {
        if (!is_string($source_path) || !file_exists($source_path)) {
            return new WP_Error('missing_source', 'Source file missing');
        }

        // If already webp, just return original path (caller can sideload directly)
        $ext = strtolower(pathinfo($source_path, PATHINFO_EXTENSION));
        if ($ext === 'webp') {
            // Only skip conversion if it is truly a WEBP
            $img_info = @getimagesize($source_path);
            $mime = is_array($img_info) && !empty($img_info['mime']) ? $img_info['mime'] : '';
            if ($mime === 'image/webp') {
                return $source_path;
            }
            // else: fall through and convert (file extension lied)
        }

        $editor = wp_get_image_editor($source_path);
        if (is_wp_error($editor)) return $editor;

        // Ensure it’s loaded
        $size = $editor->get_size();
        if (empty($size['width']) || empty($size['height'])) {
            return new WP_Error('bad_image', 'Could not read image dimensions');
        }

        $tmp = wp_tempnam($source_path . '.webp');
        if (!$tmp) return new WP_Error('tmp_fail', 'Could not create temp webp');

        // WP editors usually accept quality via set_quality
        if (method_exists($editor, 'set_quality')) {
            $editor->set_quality(80);
        }

        // Save as webp using WP image editor (attempt)
        $saved = $editor->save($tmp, 'image/webp');
        if (!is_wp_error($saved) && file_exists($tmp) && filesize($tmp) > 0) {
            return $tmp;
        }

        // ---------- cwebp fallback (robust) ----------
        // Locate cwebp
        exec('command -v cwebp 2>/dev/null', $which_out, $which_ret);
        $cwebp_path = ($which_ret === 0 && !empty($which_out[0])) ? $which_out[0] : null;

        if ($cwebp_path) {
            // Ensure source is readable; if not, try copying it to a temp file we control
            if (!is_readable($source_path)) {
                $copy_tmp = wp_tempnam($source_path);
                if ($copy_tmp && @copy($source_path, $copy_tmp)) {
                    $run_src = $copy_tmp;
                    $temp_files[] = $copy_tmp; // ensure cleanup later
                } else {
                    return new WP_Error('webp_fail_cannot_read', 'Source not readable and copy failed.');
                }
            } else {
                $run_src = $source_path;
            }

            // Place the webp output next to the (copied) source to avoid cross-fs rename issues
            $dest_dir  = dirname($run_src);
            $dest_base = pathinfo($run_src, PATHINFO_FILENAME) . '-' . uniqid('webp_', true) . '.webp';
            $dest_path = $dest_dir . '/' . $dest_base;

            $cmd = escapeshellcmd($cwebp_path) . ' -q 80 ' . escapeshellarg($run_src) . ' -o ' . escapeshellarg($dest_path) . ' 2>&1';
            exec($cmd, $cmd_out, $cmd_ret);
            $cmd_output_debug = is_array($cmd_out) ? implode("\n", $cmd_out) : (string)$cmd_out;

            if ($cmd_ret === 0 && file_exists($dest_path) && filesize($dest_path) > 0) {
                // success: return path to created webp
                return $dest_path;
            } else {
                // remove any partial output and return helpful debug
                @unlink($dest_path);
                return new WP_Error('webp_fail_cwebp',
                    'cwebp conversion failed (exit:' . intval($cmd_ret) . '). Output: ' . $cmd_output_debug
                );
            }
        }

        // If we get here, neither WP editor nor cwebp produced a webp
        @unlink($tmp);
        return new WP_Error('webp_fail', 'Failed converting to webp (Imagick/GD did not produce webp and cwebp not available).');
    }
}

/**
 * Sideload a file into the Media Library with title + alt.
 * Returns attachment ID or WP_Error.
 */
if (!function_exists('inception_ic_media_sideload')) {
    function inception_ic_media_sideload($file_path, $desired_basename, $title, $alt) {
        if (!file_exists($file_path)) {
            return new WP_Error('missing_file', 'File missing for sideload');
        }

        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';

        $file_array = [
            'name'     => $desired_basename,
            'tmp_name' => $file_path,
        ];

        // media_handle_sideload moves the file into uploads and creates attachment
        $attachment_id = media_handle_sideload($file_array, 0, $title);
        if (is_wp_error($attachment_id)) return $attachment_id;

        if ($alt !== '') {
            update_post_meta($attachment_id, '_wp_attachment_image_alt', $alt);
        }

        return (int) $attachment_id;
    }
}

/**
 * Update per-post meta like your bash script:
 * - _thumbnail_id
 * - _yoast_wpseo_opengraph-image
 * - wp_yoast_seo_links url update for rows that look like uploads/inceptionimages.com
 * - fifu_image_url
 */
if (!function_exists('inception_ic_update_post_image_meta')) {
    function inception_ic_update_post_image_meta($post_id, $attachment_id, $image_url) {
        global $wpdb;

        $post_id = (int) $post_id;
        $attachment_id = (int) $attachment_id;

        if ($post_id <= 0 || $attachment_id <= 0 || !is_string($image_url) || $image_url === '') {
            return;
        }

        update_post_meta($post_id, '_thumbnail_id', $attachment_id);
        update_post_meta($post_id, '_yoast_wpseo_opengraph-image', $image_url);
        update_post_meta($post_id, 'fifu_image_url', $image_url);

        // Update Yoast links table if present
        $table = $wpdb->prefix . 'yoast_seo_links';
        $exists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table));

        if ($exists === $table) {
            // Update rows for this post where url looks like uploads or inceptionimages.com
            // (mirrors your bash WHERE clause)
            $likeUploads = '%uploads%';
            $likeInception = '%inceptionimages.com%';

            $sql = $wpdb->prepare(
                "UPDATE {$table}
                 SET url = %s
                 WHERE post_id = %d
                   AND (url LIKE %s OR url LIKE %s)",
                $image_url,
                $post_id,
                $likeUploads,
                $likeInception
            );
            $wpdb->query($sql);
        }
    }
}

if (isset($_POST['action']) && $_POST['action'] === 'convert_images') {
    if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'convert_nonce')) {
        echo '<div class="notice notice-error"><p>Nonce verification failed.</p></div>';
        return;
    }

    $upload_dir  = wp_upload_dir();
    $upload_path = $upload_dir['path'];

    // Crop data posted from the UI (keyed by original filename)
    $uploaded_crops_byname = (isset($_POST['uploadedcrops_byname']) && is_array($_POST['uploadedcrops_byname']))
        ? $_POST['uploadedcrops_byname']
        : [];

    $image_titles = isset($_POST['uploadedtitles']) ? $_POST['uploadedtitles'] : [];
    $image_alts   = isset($_POST['uploadedalts']) ? $_POST['uploadedalts'] : [];
    $image_titles_byname = (isset($_POST['uploadedtitles_byname']) && is_array($_POST['uploadedtitles_byname']))
        ? $_POST['uploadedtitles_byname']
        : [];
    $image_alts_byname = (isset($_POST['uploadedalts_byname']) && is_array($_POST['uploadedalts_byname']))
        ? $_POST['uploadedalts_byname']
        : [];

    $files = isset($_FILES['images']) ? $_FILES['images'] : null;

    // These arrays track items in the same index order as your UI
    $items = []; // each: ['source' => path|url, 'title'=>..., 'alt'=>..., 'ids'=>string]

    // Track temp files created during processing for cleanup
    $temp_files = [];

    // 1) Build "items" from uploaded files
    if ($files && isset($files['name']) && count($files['name']) > 0 && !empty($files['name'][0])) {
        foreach ($files['name'] as $key => $name) {
            if ((int)$files['error'][$key] !== 0) {
                echo '<div class="notice notice-error"><p>Error: ' . htmlspecialchars($name) . '</p></div>';
                continue;
            }

            $temp_name     = $files['tmp_name'][$key];
            $new_file_path = $upload_path . '/' . basename($name);

            if (!move_uploaded_file($temp_name, $new_file_path)) {
                echo '<div class="notice notice-error"><p>Error uploading: ' . htmlspecialchars($name) . '</p></div>';
                continue;
            }

            $new_file_path = inception_ic_normalize_jpeg_orientation($new_file_path, $upload_path, $temp_files);

            // Optional: apply user-selected crop (Banner 714x250, Square 400x400, or Custom) before conversion
            $crop_json = isset($uploaded_crops_byname[$name]) ? $uploaded_crops_byname[$name] : '';
            if (is_string($crop_json) && $crop_json !== '') {
                $crop_arr = json_decode(stripslashes($crop_json), true);
                if (is_array($crop_arr)) {
                    $new_file_path = inception_ic_apply_user_crop($new_file_path, $crop_arr, $upload_path, $temp_files);
                }
            }

            $title = isset($image_titles_byname[$name]) ? (string)$image_titles_byname[$name] : (isset($image_titles[$key]) ? (string)$image_titles[$key] : '');
            $alt   = isset($image_alts_byname[$name]) ? (string)$image_alts_byname[$name] : (isset($image_alts[$key]) ? (string)$image_alts[$key] : '');

            $items[] = [
                'source' => $new_file_path,
                'title'  => $title,
                'alt'    => $alt,
                'ids'    => '', // filled from blogpages_debug below
            ];
        }
    }

    // 2) Append items from selected image URLs
    if (isset($_POST['selectedImages']) && is_array($_POST['selectedImages'])) {
        $selected_image_urls = $_POST['selectedImages'];
        $dropdown_titles     = isset($_POST['selectedtitles']) ? $_POST['selectedtitles'] : [];
        $dropdown_alts       = isset($_POST['selectedalts']) ? $_POST['selectedalts'] : [];

        foreach ($selected_image_urls as $index => $url) {
            $items[] = [
                'source' => esc_url_raw($url),
                'title'  => isset($dropdown_titles[$index]) ? (string)$dropdown_titles[$index] : '',
                'alt'    => isset($dropdown_alts[$index]) ? (string)$dropdown_alts[$index] : '',
                'ids'    => '', // filled below
            ];
        }
    }

    // 3) Map blogpages_debug groups to each item (same index order)
    $blogpages_debug = isset($_POST['blogpages_debug']) ? (string)$_POST['blogpages_debug'] : '';
    $ids_groups = $blogpages_debug !== '' ? explode('|', $blogpages_debug) : [];

    foreach ($items as $i => &$itemRef) {
        $itemRef['ids'] = isset($ids_groups[$i]) ? (string)$ids_groups[$i] : '';
    }
    unset($itemRef);

    // 4) Process items (dedupe by source string)
    $seen = [];
    $errors = [];
    $success_count = 0;

    foreach ($items as $i => $item) {
        $source = (string) $item['source'];
        $title  = (string) $item['title'];
        $alt    = (string) $item['alt'];
        $idsStr = (string) $item['ids'];

        if ($source === '') continue;

        if (isset($seen[$source])) {
            // Skip duplicates (matches bash behavior)
            continue;
        }
        $seen[$source] = true;

        // Determine source file path (local file or downloaded temp)
        $source_path = null;
        $download_tmp = null;

        if (preg_match('#^https?://#i', $source)) {
            $dl = inception_ic_download_remote_image($source);
            if (is_wp_error($dl)) {
                $errors[] = "Download failed: {$source} (" . esc_html($dl->get_error_message()) . ")";
                continue;
            }
            $download_tmp = $dl;
            $source_path = $download_tmp;
            $temp_files[] = $download_tmp;
            $source_path = inception_ic_normalize_jpeg_orientation($source_path, $upload_path, $temp_files);
        } else {
            $source_path = $source;
            if (!file_exists($source_path)) {
                $errors[] = "Missing file: {$source}";
                continue;
            }
        }

        // Convert to webp (temp)
        $webp_tmp = inception_ic_convert_to_webp_temp($source_path);
        if (is_wp_error($webp_tmp)) {
            $errors[] = "WebP conversion failed for: {$source} (" . esc_html($webp_tmp->get_error_message()) . ")";
            continue;
        }

        // Build filename from title (matches bash "title => filename.webp")
        $base = inception_ic_slug_filename_from_title($title);
        $desired_basename = $base . '.webp';

        // Sideload into media library
        $attachment_id = inception_ic_media_sideload($webp_tmp, $desired_basename, $title, $alt);
        if (is_wp_error($attachment_id) || (int)$attachment_id <= 0) {
            $msg = is_wp_error($attachment_id) ? $attachment_id->get_error_message() : 'Unknown error';
            $errors[] = "Media import failed for: {$source} ({$msg})";
            continue;
        }

        $image_url = wp_get_attachment_url($attachment_id);
        if (!$image_url) {
            // Not fatal — but we can’t update Yoast links table reliably without a URL
            $image_url = '';
        }

        // Update post/page IDs (comma-separated)
        $idsStr = trim($idsStr);
        if ($idsStr !== '') {
            $post_ids = array_filter(array_map('trim', explode(',', $idsStr)));
            foreach ($post_ids as $pid) {
                $pidInt = (int) $pid;
                if ($pidInt > 0) {
                    inception_ic_update_post_image_meta($pidInt, $attachment_id, $image_url);
                }
            }
        }

        $success_count++;
    }

    // Cleanup temp files created by cropping and remote download
    if (!empty($temp_files) && is_array($temp_files)) {
        foreach ($temp_files as $tmp) {
            if (is_string($tmp) && file_exists($tmp)) {
                @unlink($tmp);
            }
        }
    }

    if (!empty($errors)) {
        echo '<div class="notice notice-error"><p><strong>Some items failed:</strong></p><pre>' . esc_html(implode("\n", $errors)) . '</pre></div>';
    }

    if ($success_count > 0 && empty($errors)) {
        echo '<div class="notice notice-success"><p>All images successfully converted and added to the media library!</p><p><strong>"Try to be a rainbow in someone\'s cloud." — Maya Angelou</strong></p></div>';
    } elseif ($success_count > 0) {
        echo '<div class="notice notice-warning"><p>Imported ' . (int)$success_count . ' image(s), but some items failed (see errors above).</p></div>';
    } else {
        echo '<div class="notice notice-error"><p>No images were imported. Please check the errors above and try again.</p></div>';
    }
}
?>

<style>
.highlight-error {
    border: 2px solid red !important;
}

#selectedImage {
    min-height: 300px;
    width: 100%;
    box-sizing: border-box;
    overflow: auto;
}

input[type="file"]::file-selector-button {
    content: 'Upload Files';
}

input[type="file"]::before {
    content: 'Upload Files';
    display: inline-block;
    padding: 5px 15px;
    background-color: #f6f7f7;
    color: #2271b1;
    border: 1px solid #2271b1;
    border-radius: 4px;
    cursor: pointer;
    margin-left: 80px;
}

input[type="file"]::-webkit-file-upload-button {
    visibility: hidden;
}

input[type="file"]::file-selector-button {
    visibility: hidden;
}

/* Hide the default "Choose File" button */
input[type="file"]::-webkit-file-upload-button,
input[type="file"]::file-selector-button {
    visibility: hidden;
}

/* Hide the "No file chosen" text */
input[type="file"] {
    color: transparent;
}

input[type="file"]::-webkit-file-upload-text {
    visibility: hidden;
}

/* Hide the footer text in the WordPress admin area */
#wpfooter {
    display: none;
}

/* Add this to your plugin’s CSS file or inside a <style> tag */
select.blog-page-dropdown {
    width: max-content !important;
    min-width: max-content !important;
    white-space: nowrap !important;
    flex-shrink: 0 !important;
}
</style>

<!-- JavaScript for Previewing Images -->
<script>
function sortFilesAlphabetically(files) {
    return Array.from(files).sort((a, b) => a.name.localeCompare(b.name));
}

// Store previously selected images and their titles and alt texts
let previouslySelectedImages = [];
let previouslySelectedTitles = [];
let previouslySelectedAlts = [];
let previouslySelectedBlogPages = [];

// Function to update previously selected images, titles, and alts
function updatePreviouslySelected() {
    previouslySelectedImages = Array.from(document.querySelectorAll('input[name^="selectedImages"]')).map(input => input.value);
    previouslySelectedTitles = Array.from(document.querySelectorAll('input[name^="selectedtitles"]')).map(input => input.value);
    previouslySelectedAlts = Array.from(document.querySelectorAll('input[name^="selectedalts"]')).map(input => input.value);

    previouslySelectedBlogPages = Array.from(document.querySelectorAll('select[name="selectedblogpages[]"]')).map(select =>
        Array.from(select.selectedOptions).map(opt => opt.value)
    );
}

// Function to restore previously entered text fields
function restorePreviouslySelectedFields() {
    previouslySelectedTitles.forEach((title, index) => {
        const titleInput = document.querySelector(`input[name="selectedtitles[${index}]"]`);
        if (titleInput) titleInput.value = title;
    });
    previouslySelectedAlts.forEach((alt, index) => {
        const altInput = document.querySelector(`input[name="selectedalts[${index}]"]`);
        if (altInput) altInput.value = alt;
    });
}

document.getElementById('imageUpload').addEventListener('change', async function(event) {
    const preview = document.getElementById('imagePreview');
    updatePreviouslySelected();
    preview.innerHTML = '';

    const hiddenUploadInputs = document.getElementById('hiddenUploadInputs');
    hiddenUploadInputs.innerHTML = '';

    const files = Array.from(event.target.files);
    const allowedTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/webp'];

    function readFile(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = function(e) {
                resolve({
                    src: e.target.result,
                    name: file.name,
                    type: file.type
                });
            };
            reader.onerror = function() {
                reject(new Error('Error reading file'));
            };
            reader.readAsDataURL(file);
        });
    }

    const filePromises = files.map(file => {
        if (allowedTypes.includes(file.type)) {
            return readFile(file);
        } else {
            alert('File type not allowed: ' + file.name);
            return Promise.resolve();
        }
    });

    const fileResults = await Promise.all(filePromises);

    fileResults.forEach((fileResult, index) => {
        if (!fileResult) return;

        const container = document.createElement('div');
        container.style.display = 'flex';
        container.style.alignItems = 'center';
        container.style.marginBottom = '20px';

        const img = document.createElement('img');
        img.src = fileResult.src;
        img.dataset.inceptionOriginalSrc = fileResult.src;
        img.style.height = 'auto';
        img.style.width = '300px';
        img.style.marginRight = '20px';

        const textContainer = document.createElement('div');
        textContainer.style.display = 'flex';
        textContainer.style.flexDirection = 'column';

        const filenameParagraph = document.createElement('p');
        filenameParagraph.textContent = fileResult.name;
        filenameParagraph.style.marginBottom = '5px';
        filenameParagraph.style.fontWeight = 'bold';

        const titleInput = document.createElement('input');
        titleInput.type = 'text';
        titleInput.name = `uploadedtitles[${index}]`;
        titleInput.placeholder = 'Image Title';
        titleInput.style.marginBottom = '5px';
        titleInput.style.width = '300px';

        const altInput = document.createElement('input');
        altInput.type = 'text';
        altInput.name = `uploadedalts[${index}]`;
        altInput.placeholder = 'Alt Text';
        altInput.style.marginBottom = '5px';
        altInput.style.width = '300px';

        // Hidden crop data input (keyed by original filename)
        const hiddenCropInput = document.createElement('input');
        hiddenCropInput.type = 'hidden';
        hiddenCropInput.name = `uploadedcrops_byname[${fileResult.name}]`;
        hiddenCropInput.value = '';
        hiddenUploadInputs.appendChild(hiddenCropInput);

        // Crop button (opens visual cropper; choose Banner 714x250, Square 400x400, or Custom)
        const cropBtn = document.createElement('button');
        cropBtn.type = 'button';
        cropBtn.className = 'button';
        cropBtn.textContent = 'Adjust Crop';
        cropBtn.style.marginTop = '6px';
        cropBtn.style.width = '300px';
        cropBtn.style.boxSizing = 'border-box';
        cropBtn.addEventListener('click', function() {
            const originalSrc = img.dataset.inceptionOriginalSrc || fileResult.src;
            openInceptionCropModal(originalSrc, hiddenCropInput, img);
        });

        textContainer.appendChild(filenameParagraph);
        textContainer.appendChild(titleInput);
        textContainer.appendChild(altInput);
        textContainer.appendChild(cropBtn);

        container.appendChild(img);
        container.appendChild(textContainer);
        preview.appendChild(container);

        // Blog/pages dropdown
        const blogLabel = document.createElement('p');
        blogLabel.textContent = 'Set Featured Image on These Blogs/Pages:';
        blogLabel.style.fontWeight = 'bold';
        textContainer.appendChild(blogLabel);

        const blogDropdown = document.createElement('select');
        blogDropdown.multiple = true;
        blogDropdown.name = `uploadedblogpages[]`;
        blogDropdown.innerHTML = blogPagesOptions;
        blogDropdown.classList.add('blog-page-dropdown');
        blogDropdown.setAttribute('size', '6');
        textContainer.appendChild(blogDropdown);

        // Hidden inputs for titles/alts (submitted values)
        const hiddenTitleInput = document.createElement('input');
        hiddenTitleInput.type = 'hidden';
        hiddenTitleInput.name = `uploadedtitles[${index}]`;
        hiddenTitleInput.value = '';
        hiddenUploadInputs.appendChild(hiddenTitleInput);

        const hiddenTitleByNameInput = document.createElement('input');
        hiddenTitleByNameInput.type = 'hidden';
        hiddenTitleByNameInput.name = `uploadedtitles_byname[${fileResult.name}]`;
        hiddenTitleByNameInput.value = '';
        hiddenUploadInputs.appendChild(hiddenTitleByNameInput);

        const hiddenAltInput = document.createElement('input');
        hiddenAltInput.type = 'hidden';
        hiddenAltInput.name = `uploadedalts[${index}]`;
        hiddenAltInput.value = '';
        hiddenUploadInputs.appendChild(hiddenAltInput);

        const hiddenAltByNameInput = document.createElement('input');
        hiddenAltByNameInput.type = 'hidden';
        hiddenAltByNameInput.name = `uploadedalts_byname[${fileResult.name}]`;
        hiddenAltByNameInput.value = '';
        hiddenUploadInputs.appendChild(hiddenAltByNameInput);

        // Sync hidden inputs + autofill alt from title
        titleInput.addEventListener('input', function() {
            hiddenTitleInput.value = titleInput.value;
            hiddenTitleByNameInput.value = titleInput.value;
            if (titleInput.value.trim()) titleInput.classList.remove('highlight-error');

            altInput.value = titleInput.value;
            hiddenAltInput.value = altInput.value;
            hiddenAltByNameInput.value = altInput.value;
        });

        altInput.addEventListener('input', function() {
            hiddenAltInput.value = altInput.value;
            hiddenAltByNameInput.value = altInput.value;
            if (altInput.value.trim()) altInput.classList.remove('highlight-error');
        });
    });

    // Restore titles/alts for previously selected images
    previouslySelectedImages.forEach((image, index) => {
        const titleInput = document.querySelector(`input[name="selectedtitles[${index}]"]`);
        const altInput = document.querySelector(`input[name="selectedalts[${index}]"]`);
        if (titleInput && previouslySelectedTitles[index]) titleInput.value = previouslySelectedTitles[index];
        if (altInput && previouslySelectedAlts[index]) altInput.value = previouslySelectedAlts[index];
    });

    // Re-add previously selected images (dropdown selections)
    const hiddenSelectedInputs = document.getElementById('hiddenSelectedInputs');
    const selectedOptions = Array.from(document.getElementById('selectedImage').selectedOptions);

    selectedOptions.forEach((option, index) => {
        const container = document.createElement('div');
        container.classList.add('dropdown-preview-container');
        container.style.display = 'flex';
        container.style.alignItems = 'center';
        container.style.marginBottom = '20px';

        const img = document.createElement('img');
        img.src = option.value;
        img.style.height = 'auto';
        img.style.width = '300px';
        img.style.marginRight = '20px';

        const textContainer = document.createElement('div');
        textContainer.style.display = 'flex';
        textContainer.style.flexDirection = 'column';

        const filenameParagraph = document.createElement('p');
        filenameParagraph.textContent = option.text;
        filenameParagraph.style.marginBottom = '5px';
        filenameParagraph.style.fontWeight = 'bold';

        const titleInput = document.createElement('input');
        titleInput.type = 'text';
        titleInput.name = `selectedtitles[${index}]`;
        titleInput.placeholder = 'Image Title';
        titleInput.style.marginBottom = '5px';
        titleInput.style.width = '300px';

        const altInput = document.createElement('input');
        altInput.type = 'text';
        altInput.name = `selectedalts[${index}]`;
        altInput.placeholder = 'Alt Text';
        altInput.style.marginBottom = '5px';
        altInput.style.width = '300px';

        textContainer.appendChild(filenameParagraph);
        textContainer.appendChild(titleInput);
        textContainer.appendChild(altInput);

        const blogLabel = document.createElement('p');
        blogLabel.textContent = 'Set Featured Image on These Blogs/Pages:';
        blogLabel.style.fontWeight = 'bold';
        textContainer.appendChild(blogLabel);

        const blogDropdown = document.createElement('select');
        blogDropdown.multiple = true;
        blogDropdown.name = `selectedblogpages[]`;
        blogDropdown.innerHTML = blogPagesOptions;
        blogDropdown.classList.add('blog-page-dropdown');
        blogDropdown.setAttribute('size', '6');
        textContainer.appendChild(blogDropdown);

        container.appendChild(img);
        container.appendChild(textContainer);
        preview.appendChild(container);

        // Hidden selected image input
        const hiddenSelectedImageInput = document.createElement('input');
        hiddenSelectedImageInput.type = 'hidden';
        hiddenSelectedImageInput.name = `selectedImages[${index}]`;
        hiddenSelectedImageInput.value = option.value;
        hiddenSelectedInputs.appendChild(hiddenSelectedImageInput);

        const hiddenTitleInput = document.createElement('input');
        hiddenTitleInput.type = 'hidden';
        hiddenTitleInput.name = `selectedtitles[${index}]`;
        hiddenSelectedInputs.appendChild(hiddenTitleInput);

        const hiddenAltInput = document.createElement('input');
        hiddenAltInput.type = 'hidden';
        hiddenAltInput.name = `selectedalts[${index}]`;
        hiddenSelectedInputs.appendChild(hiddenAltInput);

        // Restore previously entered titles/alts/blogs
        if (previouslySelectedTitles[index]) {
            titleInput.value = previouslySelectedTitles[index];
            hiddenTitleInput.value = previouslySelectedTitles[index];
        }
        if (previouslySelectedAlts[index]) {
            altInput.value = previouslySelectedAlts[index];
            hiddenAltInput.value = previouslySelectedAlts[index];
        }
        if (previouslySelectedBlogPages[index]) {
            const savedBlogs = previouslySelectedBlogPages[index];
            for (let i = 0; i < blogDropdown.options.length; i++) {
                if (savedBlogs.includes(blogDropdown.options[i].value)) {
                    blogDropdown.options[i].selected = true;
                }
            }
        }

        // Sync hidden fields + autofill alt from title
        titleInput.addEventListener('input', function() {
            hiddenTitleInput.value = titleInput.value;
            if (titleInput.value.trim()) titleInput.classList.remove('highlight-error');

            altInput.value = titleInput.value;
            hiddenAltInput.value = altInput.value;
        });

        altInput.addEventListener('input', function() {
            hiddenAltInput.value = altInput.value;
            if (altInput.value.trim()) altInput.classList.remove('highlight-error');
        });
    });

    restorePreviouslySelectedFields();
});

// Global object to store data for selected images keyed by image URL (or unique ID)
let uploadedImageData = {};
let selectedImageData = {};

document.getElementById('selectedImage').addEventListener('change', function(event) {
    // Before clearing, store data from existing preview containers
    document.querySelectorAll('.dropdown-preview-container').forEach(container => {
        const imageId = container.getAttribute('data-image-id');
        if (imageId) {
            const titleInput = container.querySelector('input[name^="selectedtitles"]');
            const altInput = container.querySelector('input[name^="selectedalts"]');
            const blogDropdown = container.querySelector('select[name="selectedblogpages[]"]');

            selectedImageData[imageId] = {
                title: titleInput ? titleInput.value : '',
                alt: altInput ? altInput.value : '',
                selectedBlogPages: blogDropdown ? Array.from(blogDropdown.selectedOptions).map(opt => opt.value) : []
            };
        }
    });

    const preview = document.getElementById('imagePreview');
    const selectedOptions = Array.from(event.target.selectedOptions);
    const hiddenSelectedInputs = document.getElementById('hiddenSelectedInputs');

    // Clear existing dropdown previews
    document.querySelectorAll('.dropdown-preview-container').forEach(container => container.remove());
    hiddenSelectedInputs.innerHTML = '';

    selectedOptions.forEach((option, index) => {
        const container = document.createElement('div');
        container.classList.add('dropdown-preview-container');
        container.setAttribute('data-image-id', option.value);

        container.style.display = 'flex';
        container.style.alignItems = 'center';
        container.style.marginBottom = '20px';

        const img = document.createElement('img');
        img.src = option.value;
        img.style.height = 'auto';
        img.style.width = '300px';
        img.style.marginRight = '20px';

        const textContainer = document.createElement('div');
        textContainer.style.display = 'flex';
        textContainer.style.flexDirection = 'column';

        const filenameParagraph = document.createElement('p');
        filenameParagraph.textContent = option.text;
        filenameParagraph.style.marginBottom = '5px';
        filenameParagraph.style.fontWeight = 'bold';

        const titleInput = document.createElement('input');
        titleInput.type = 'text';
        titleInput.name = `selectedtitles[${index}]`;
        titleInput.placeholder = 'Image Title';
        titleInput.style.marginBottom = '5px';
        titleInput.style.width = '300px';

        const altInput = document.createElement('input');
        altInput.type = 'text';
        altInput.name = `selectedalts[${index}]`;
        altInput.placeholder = 'Alt Text';
        altInput.style.marginBottom = '5px';
        altInput.style.width = '300px';

        textContainer.appendChild(filenameParagraph);
        textContainer.appendChild(titleInput);
        textContainer.appendChild(altInput);

        const blogLabel = document.createElement('p');
        blogLabel.textContent = 'Set Featured Image on These Blogs/Pages:';
        blogLabel.style.fontWeight = 'bold';
        textContainer.appendChild(blogLabel);

        const blogDropdown = document.createElement('select');
        blogDropdown.multiple = true;
        blogDropdown.name = `selectedblogpages[]`;
        blogDropdown.innerHTML = blogPagesOptions;
        blogDropdown.classList.add('blog-page-dropdown');
        blogDropdown.setAttribute('size', '6');
        textContainer.appendChild(blogDropdown);

        container.appendChild(img);
        container.appendChild(textContainer);
        preview.appendChild(container);

        // Hidden selected image input
        const hiddenSelectedImageInput = document.createElement('input');
        hiddenSelectedImageInput.type = 'hidden';
        hiddenSelectedImageInput.name = `selectedImages[${index}]`;
        hiddenSelectedImageInput.value = option.value;
        hiddenSelectedInputs.appendChild(hiddenSelectedImageInput);

        const hiddenTitleInput = document.createElement('input');
        hiddenTitleInput.type = 'hidden';
        hiddenTitleInput.name = `selectedtitles[${index}]`;
        hiddenSelectedInputs.appendChild(hiddenTitleInput);

        const hiddenAltInput = document.createElement('input');
        hiddenAltInput.type = 'hidden';
        hiddenAltInput.name = `selectedalts[${index}]`;
        hiddenSelectedInputs.appendChild(hiddenAltInput);

        // Sync hidden inputs + autofill alt from title
        titleInput.addEventListener('input', function() {
            hiddenTitleInput.value = titleInput.value;
            if (titleInput.value.trim()) titleInput.classList.remove('highlight-error');

            altInput.value = titleInput.value;
            hiddenAltInput.value = altInput.value;
        });

        altInput.addEventListener('input', function() {
            hiddenAltInput.value = altInput.value;
            if (altInput.value.trim()) altInput.classList.remove('highlight-error');
        });

        // Restore saved data for this image (if exists)
        if (selectedImageData[option.value]) {
            titleInput.value = selectedImageData[option.value].title;
            altInput.value = selectedImageData[option.value].alt;
            hiddenTitleInput.value = selectedImageData[option.value].title;
            hiddenAltInput.value = selectedImageData[option.value].alt;

            const savedBlogs = selectedImageData[option.value].selectedBlogPages;
            for (let i = 0; i < blogDropdown.options.length; i++) {
                if (savedBlogs.includes(blogDropdown.options[i].value)) {
                    blogDropdown.options[i].selected = true;
                }
            }
        }
    });
});

// Filtering dropdown options
document.getElementById('imageSearch').addEventListener('input', function(event) {
    const searchTerm = event.target.value.toLowerCase();
    const optgroups = document.querySelectorAll('#selectedImage optgroup');

    optgroups.forEach(optgroup => {
        let hasVisibleOption = false;
        const options = optgroup.querySelectorAll('option');

        options.forEach(option => {
            const label = option.textContent.toLowerCase();
            if (label.includes(searchTerm)) {
                option.style.display = 'block';
                hasVisibleOption = true;
            } else {
                option.style.display = 'none';
            }
        });

        optgroup.style.display = hasVisibleOption ? 'block' : 'none';
    });
});

// validateForm MUST return boolean (your original didn't)
function validateForm(event) {
    let isValid = true;

    const titleInputs = document.querySelectorAll('input[name^="uploadedtitles"]');
    const altInputs = document.querySelectorAll('input[name^="uploadedalts"]');

    titleInputs.forEach(input => {
        if (!input.value.trim()) {
            input.classList.add('highlight-error');
            isValid = false;
        }
    });

    altInputs.forEach(input => {
        if (!input.value.trim()) {
            input.classList.add('highlight-error');
            isValid = false;
        }
    });

    const selectedTitleInputs = document.querySelectorAll('input[name^="selectedtitles"]');
    const selectedAltInputs = document.querySelectorAll('input[name^="selectedalts"]');

    selectedTitleInputs.forEach(input => {
        if (!input.value.trim()) {
            input.classList.add('highlight-error');
            isValid = false;
        }
    });

    selectedAltInputs.forEach(input => {
        if (!input.value.trim()) {
            input.classList.add('highlight-error');
            isValid = false;
        }
    });

    if (!isValid) {
        if (event) event.preventDefault();
        alert('Please fill out all required fields.');
    }

    return isValid;
}

document.getElementById('imageForm').addEventListener('submit', function(e) {
    if (!validateForm(e)) return;
    showGif();
});

// Show GIF
function showGif() {
    var gifContainer = document.getElementById('gif-container');
    gifContainer.style.opacity = '1';
    gifContainer.style.height = 'auto';
    window.scrollTo({ top: 0, behavior: 'smooth' });
}

// Blog/page IDs => hidden input string "a,b|c,d|..."
function getSelectedPostIDsString() {
    const allSelects = document.querySelectorAll('select[name="uploadedblogpages[]"], select[name="selectedblogpages[]"]');
    let groups = [];

    allSelects.forEach(select => {
        const selected = Array.from(select.selectedOptions).map(opt => opt.value);
        groups.push(selected.join(','));
    });

    return groups.join('|');
}

document.getElementById('imageForm').addEventListener('submit', function(e) {
    document.getElementById('blogpages_debug').value = getSelectedPostIDsString();
});


// ------------------------------
// Visual Crop UI (Cropper.js)
// Supports three crop modes:
// - Banner: 714x250 (locked aspect ratio; output resized to 714x250)
// - Square: 400x400 (locked aspect ratio; output resized to 400x400)
// - Custom: user-specified width/height (locked aspect ratio; output resized to those dimensions)
// ------------------------------
let inceptionCropper = null;
let inceptionCropTargetInput = null;
let inceptionCropPreviewImgEl = null;
let inceptionCropOriginalSrc = null;

function inceptionClampInt(n, min, max, fallback) {
    const v = parseInt(n, 10);
    if (Number.isNaN(v)) return fallback;
    return Math.max(min, Math.min(max, v));
}

function inceptionGetModalEls() {
    return {
        outputLabel: document.getElementById('inceptionCropOutputLabel'),
        modeBanner: document.getElementById('inceptionCropModeBanner'),
        modeSquare: document.getElementById('inceptionCropModeSquare'),
        modeCustom: document.getElementById('inceptionCropModeCustom'),
        customWrap: document.getElementById('inceptionCropCustomWrap'),
        customW: document.getElementById('inceptionCropCustomW'),
        customH: document.getElementById('inceptionCropCustomH'),
    };
}

function inceptionGetSelectedCropTarget() {
    const els = inceptionGetModalEls();

    if (els.modeSquare && els.modeSquare.checked) {
        return { mode: 'square', w: 400, h: 400 };
    }

    if (els.modeCustom && els.modeCustom.checked) {
        const w = inceptionClampInt(els.customW?.value, 1, 8000, 714);
        const h = inceptionClampInt(els.customH?.value, 1, 8000, 250);
        return { mode: 'custom', w, h };
    }

    // Default: banner
    return { mode: 'banner', w: 714, h: 250 };
}

function inceptionUpdateCropOutputLabel() {
    const els = inceptionGetModalEls();
    const t = inceptionGetSelectedCropTarget();
    if (els.outputLabel) {
        els.outputLabel.textContent = `(final output: ${t.w}×${t.h})`;
    }
    if (els.customWrap) {
        els.customWrap.style.display = (t.mode === 'custom') ? 'block' : 'none';
    }
}

function inceptionSetCropModeFromSaved(saved) {
    const els = inceptionGetModalEls();

    // Defaults
    let mode = 'banner';
    let w = 714;
    let h = 250;

    if (saved && typeof saved === 'object') {
        if (saved.mode === 'square') {
            mode = 'square';
            w = 400;
            h = 400;
        } else if (saved.mode === 'custom') {
            mode = 'custom';
            w = inceptionClampInt(saved.target_w, 1, 8000, 714);
            h = inceptionClampInt(saved.target_h, 1, 8000, 250);
        } else if (typeof saved.target_w !== 'undefined' && typeof saved.target_h !== 'undefined') {
            // Backward/forward compatibility if mode is missing
            w = inceptionClampInt(saved.target_w, 1, 8000, 714);
            h = inceptionClampInt(saved.target_h, 1, 8000, 250);
            if (w === 400 && h === 400) {
                mode = 'square';
            } else if (!(w === 714 && h === 250)) {
                mode = 'custom';
            }
        }
    }

    if (els.modeBanner) els.modeBanner.checked = (mode === 'banner');
    if (els.modeSquare) els.modeSquare.checked = (mode === 'square');
    if (els.modeCustom) els.modeCustom.checked = (mode === 'custom');

    if (els.customW) els.customW.value = w;
    if (els.customH) els.customH.value = h;

    inceptionUpdateCropOutputLabel();
}

function inceptionEnsureCropper(imgEl, aspectRatio) {
    if (!imgEl) return;

    if (!inceptionCropper) {
        inceptionCropper = new Cropper(imgEl, {
            viewMode: 1,
            autoCropArea: 0.9,
            aspectRatio: aspectRatio,
            movable: true,
            zoomable: true,
            rotatable: false,
            scalable: false,
        });
        return;
    }

    // Prefer setAspectRatio if available (Cropper.js >= 1.0)
    if (typeof inceptionCropper.setAspectRatio === 'function') {
        inceptionCropper.setAspectRatio(aspectRatio);
    } else {
        // Fallback: recreate (preserve current crop box as best as possible)
        const prevData = inceptionCropper.getData(true);
        inceptionCropper.destroy();
        inceptionCropper = null;

        inceptionCropper = new Cropper(imgEl, {
            viewMode: 1,
            autoCropArea: 0.9,
            aspectRatio: aspectRatio,
            movable: true,
            zoomable: true,
            rotatable: false,
            scalable: false,
        });

        try {
            inceptionCropper.setData(prevData);
        } catch (e) {}
    }
}

function inceptionWireCropModeControls(imgEl) {
    const els = inceptionGetModalEls();

    function apply() {
        inceptionUpdateCropOutputLabel();
        const t = inceptionGetSelectedCropTarget();
        const ar = (t.h > 0) ? (t.w / t.h) : (714 / 250);
        inceptionEnsureCropper(imgEl, ar);
    }

    // Avoid double-binding
    const already = document.body.dataset.inceptionCropModeWired === '1';
    if (!already) {
        document.body.dataset.inceptionCropModeWired = '1';

        ['modeBanner', 'modeSquare', 'modeCustom'].forEach((k) => {
            const el = els[k];
            if (el) el.addEventListener('change', apply);
        });

        [els.customW, els.customH].forEach((el) => {
            if (!el) return;
            el.addEventListener('input', function() {
                // Only respond when Custom is selected
                if (els.modeCustom && els.modeCustom.checked) apply();
            });
        });
    }

    apply();
}

function openInceptionCropModal(imageSrc, targetHiddenInput, previewImgEl) {
    const modal = document.getElementById('inceptionCropModal');
    const imgEl = document.getElementById('inceptionCropImage');

    inceptionCropTargetInput = targetHiddenInput;
    inceptionCropPreviewImgEl = previewImgEl || null;
    inceptionCropOriginalSrc = imageSrc;

    // Parse saved crop (if any) to set crop mode BEFORE creating the cropper.
    let saved = null;
    if (inceptionCropTargetInput && inceptionCropTargetInput.value) {
        try {
            saved = JSON.parse(inceptionCropTargetInput.value);
        } catch (e) {
            saved = null;
        }
    }
    inceptionSetCropModeFromSaved(saved);

    if (inceptionCropper) {
        inceptionCropper.destroy();
        inceptionCropper = null;
    }

    imgEl.src = imageSrc;
    modal.style.display = 'block';

    imgEl.onload = function() {
        const t = inceptionGetSelectedCropTarget();
        const ar = (t.h > 0) ? (t.w / t.h) : (714 / 250);

        inceptionCropper = new Cropper(imgEl, {
            viewMode: 1,
            autoCropArea: 0.9,
            aspectRatio: ar,
            movable: true,
            zoomable: true,
            rotatable: false,
            scalable: false,
        });

        // Wire controls now that cropper exists
        inceptionWireCropModeControls(imgEl);

        if (saved && typeof saved === 'object') {
            try {
                inceptionCropper.setData(saved);
            } catch (e) {}
        }
    };
}

function closeInceptionCropModal() {
    const modal = document.getElementById('inceptionCropModal');
    modal.style.display = 'none';

    if (inceptionCropper) {
        inceptionCropper.destroy();
        inceptionCropper = null;
    }

    inceptionCropTargetInput = null;
    inceptionCropPreviewImgEl = null;
    inceptionCropOriginalSrc = null;
}

// IMPORTANT: wire buttons directly so Cropper overlays can't swallow clicks
function wireInceptionCropButtons() {
    const saveBtn = document.getElementById('inceptionCropSaveBtn');
    const noCropBtn = document.getElementById('inceptionCropNoCropBtn');

    if (saveBtn && !saveBtn.dataset.inceptionWired) {
        saveBtn.dataset.inceptionWired = '1';

        saveBtn.addEventListener(
            'click', function(e) {
            e.preventDefault();
            e.stopPropagation();

            if (inceptionCropper && inceptionCropTargetInput) {
                const t = inceptionGetSelectedCropTarget();
                const data = inceptionCropper.getData(true);

                const payload = {
                    x: data.x,
                    y: data.y,
                    width: data.width,
                    height: data.height,
                    mode: t.mode,
                    target_w: t.w,
                    target_h: t.h
                };

                inceptionCropTargetInput.value = JSON.stringify(payload);

                if (inceptionCropPreviewImgEl) {
                    try {
                        const canvas = inceptionCropper.getCroppedCanvas({
                            width: t.w,
                            height: t.h,
                            imageSmoothingEnabled: true,
                            imageSmoothingQuality: 'high'
                        });

                        // Use PNG for preview so transparency stays transparent (preview only)
                        const previewDataUrl = canvas.toDataURL('image/png');
                        inceptionCropPreviewImgEl.src = previewDataUrl;

                        if (inceptionCropOriginalSrc) {
                            inceptionCropPreviewImgEl.dataset.inceptionOriginalSrc = inceptionCropOriginalSrc;
                        }
                        inceptionCropPreviewImgEl.dataset.inceptionHasCrop = '1';
                    } catch (err) {
                        console.warn('Could not update cropped preview:', err);
                    }
                }
            }

            closeInceptionCropModal();
        }, true); // capture phase
    }

    if (noCropBtn && !noCropBtn.dataset.inceptionWired) {
        noCropBtn.dataset.inceptionWired = '1';

        noCropBtn.addEventListener('click', function(e) {
            e.preventDefault();
            e.stopPropagation();

            if (inceptionCropTargetInput) {
                inceptionCropTargetInput.value = '';
            }

            if (inceptionCropPreviewImgEl) {
                const original = inceptionCropPreviewImgEl.dataset.inceptionOriginalSrc || inceptionCropOriginalSrc;
                if (original) {
                    inceptionCropPreviewImgEl.src = original;
                    inceptionCropPreviewImgEl.dataset.inceptionHasCrop = '0';
                }
            }

            closeInceptionCropModal();
        }, true); // capture phase
    }
}

wireInceptionCropButtons();
document.addEventListener('DOMContentLoaded', function() {
    wireInceptionCropButtons();
    inceptionUpdateCropOutputLabel();
});

// Clicking inside dialog shouldn't close anything
document.getElementById('inceptionCropDialog')?.addEventListener('click', function(e) {
    e.stopPropagation();
});
</script>
</div>
