<?php

if (!defined('ABSPATH')) { exit; }

class AIEO_WC_Compat_Migration {

    const COMPLETED_OPTION = 'aieo_wc_compat_migration_completed_at';
    const UPDATE_HOOK      = 'aieo_wc_compat_migration_run';
    const UPDATE_GROUP     = 'aieo-migrations';
    const BATCH_SIZE       = 250;
    const SENTINEL_META    = '_wc_variation_gallery_legacy_fallback_disabled';
    
    
    
    
    
    
    
    
    
    const MIGRATED_META      = '_aieo_variation_migrated';
    const TERM_MIGRATED_META = '_aieo_swatch_term_migrated';

    
    public static function bootstrap() {
        if (!get_option(self::COMPLETED_OPTION)) {
            add_action('init', array(__CLASS__, 'maybe_schedule'), 30);
        }
        add_action(self::UPDATE_HOOK, array(__CLASS__, 'run_as_callback'));

        if (defined('WP_CLI') && WP_CLI) {
            WP_CLI::add_command('aieo migrate wc-compat', array(__CLASS__, 'cli_run'));
        }
    }

    
    public static function maybe_schedule() {
        if (get_option(self::COMPLETED_OPTION)) { return; }
        if (!function_exists('WC') || !WC()->queue()) { return; }

        if (null !== WC()->queue()->get_next(self::UPDATE_HOOK, array(), self::UPDATE_GROUP)) {
            return;
        }

        $running = WC()->queue()->search(array(
            'hook'     => self::UPDATE_HOOK,
            'status'   => \ActionScheduler_Store::STATUS_RUNNING,
            'per_page' => 1,
            'group'    => self::UPDATE_GROUP,
        ), 'ids');
        if (!empty($running)) { return; }

        WC()->queue()->add(self::UPDATE_HOOK, array(), self::UPDATE_GROUP);
    }

    
    public static function run_as_callback() {
        if (self::run()) {
            self::maybe_schedule();
        }
    }

    
    public static function run(): bool {
        if (get_option(self::COMPLETED_OPTION)) { return false; }

        $variation_pending = self::migrate_variation_batch();
        $term_pending      = self::migrate_swatch_terms_batch();

        if (!$variation_pending && !$term_pending) {
            self::promote_attribute_types();
            update_option(self::COMPLETED_OPTION, time(), false);
            return false;
        }

        return true;
    }

    
    private static function migrate_variation_batch(): bool {
        global $wpdb;

        
        
        
        
        
        $variation_ids = $wpdb->get_col($wpdb->prepare(
            "SELECT legacy.post_id
             FROM {$wpdb->postmeta} AS legacy
             INNER JOIN {$wpdb->posts} AS posts
                 ON posts.ID = legacy.post_id AND posts.post_type = 'product_variation'
             LEFT JOIN {$wpdb->postmeta} AS canonical
                 ON canonical.post_id = legacy.post_id
                 AND canonical.meta_key = '_product_image_gallery'
                 AND canonical.meta_value <> ''
             LEFT JOIN {$wpdb->postmeta} AS attempted
                 ON attempted.post_id = legacy.post_id
                 AND attempted.meta_key = %s
                 AND attempted.meta_value = 'yes'
             WHERE legacy.meta_key = 'botiga_variation_gallery'
                 AND legacy.meta_value <> ''
                 AND canonical.post_id IS NULL
                 AND attempted.post_id IS NULL
             GROUP BY legacy.post_id
             ORDER BY legacy.post_id ASC
             LIMIT %d",
            self::MIGRATED_META,
            self::BATCH_SIZE
        ));

        if (empty($variation_ids)) { return false; }

        foreach ($variation_ids as $vid) {
            self::migrate_one_variation((int) $vid);
        }

        
        return count($variation_ids) >= self::BATCH_SIZE;
    }

    
    public static function migrate_one_variation(int $variation_id): void {
        $legacy = get_post_meta($variation_id, 'botiga_variation_gallery', true);
        
        
        
        
        
        
        if (empty($legacy) || !is_array($legacy)) {
            update_post_meta($variation_id, self::MIGRATED_META, 'yes');
            return;
        }

        $image_ids = array();
        $videos    = array();

        foreach ($legacy as $position => $entry) {
            $classified = self::classify_gallery_entry($entry);
            if ($classified === null) { continue; }

            if ($classified['kind'] === 'image') {
                $image_ids[] = $classified['id'];
            } else {
                $videos[] = array_merge($classified, array('position' => (int) $position));
            }
        }

        if (!empty($image_ids)) {
            update_post_meta($variation_id, '_product_image_gallery', implode(',', $image_ids));

            $existing_thumb = (int) get_post_meta($variation_id, '_thumbnail_id', true);
            if (!$existing_thumb || !wp_attachment_is_image($existing_thumb)) {
                update_post_meta($variation_id, '_thumbnail_id', $image_ids[0]);
            }
        }

        if (!empty($videos)) {
            update_post_meta($variation_id, '_aieo_variation_gallery_videos', $videos);
        }

        update_post_meta($variation_id, self::SENTINEL_META, 'yes');
        
        
        
        update_post_meta($variation_id, self::MIGRATED_META, 'yes');
    }

    
    public static function classify_gallery_entry($entry): ?array {
        if (is_numeric($entry)) {
            $id = (int) $entry;
            if ($id <= 0) { return null; }
            if (wp_attachment_is('video', $id)) {
                return array('kind' => 'video', 'type' => 'attachment', 'id' => $id);
            }
            if (wp_attachment_is_image($id)) {
                return array('kind' => 'image', 'id' => $id);
            }
            return null;
        }

        if (is_string($entry) && (strpos($entry, 'youtube') !== false || strpos($entry, 'youtu.be') !== false)) {
            $obj = json_decode($entry);
            if ($obj && isset($obj->url)) {
                return array(
                    'kind'         => 'video',
                    'type'         => 'youtube',
                    'url'          => (string) $obj->url,
                    'aspect_ratio' => isset($obj->aspect_ratio) ? (string) $obj->aspect_ratio : '16-9',
                );
            }
            return null;
        }

        if (is_string($entry) && strpos($entry, 'vimeo') !== false) {
            $obj = json_decode($entry);
            if ($obj && isset($obj->url)) {
                return array(
                    'kind'         => 'video',
                    'type'         => 'vimeo',
                    'url'          => (string) $obj->url,
                    'aspect_ratio' => isset($obj->aspect_ratio) ? (string) $obj->aspect_ratio : '16-9',
                );
            }
            return null;
        }

        return null;
    }

    
    private static function migrate_swatch_terms_batch(): bool {
        global $wpdb;

        
        
        
        
        
        
        
        $term_ids = $wpdb->get_col($wpdb->prepare(
            "SELECT DISTINCT tm.term_id
             FROM {$wpdb->termmeta} AS tm
             INNER JOIN {$wpdb->term_taxonomy} AS tt ON tt.term_id = tm.term_id
             LEFT JOIN {$wpdb->termmeta} AS canonical
                 ON canonical.term_id = tm.term_id
                 AND canonical.meta_key = 'color'
                 AND canonical.meta_value <> ''
             LEFT JOIN {$wpdb->termmeta} AS sidecar_type
                 ON sidecar_type.term_id = tm.term_id
                 AND sidecar_type.meta_key = '_aieo_swatch_color_type'
             LEFT JOIN {$wpdb->termmeta} AS sidecar_image
                 ON sidecar_image.term_id = tm.term_id
                 AND sidecar_image.meta_key = '_aieo_swatch_image_id'
             LEFT JOIN {$wpdb->termmeta} AS attempted
                 ON attempted.term_id = tm.term_id
                 AND attempted.meta_key = %s
                 AND attempted.meta_value = 'yes'
             WHERE tm.meta_key IN ('product_attribute_color', 'product_attribute_image')
                 AND tm.meta_value <> ''
                 AND tt.taxonomy LIKE %s
                 AND canonical.term_id IS NULL
                 AND sidecar_type.term_id IS NULL
                 AND sidecar_image.term_id IS NULL
                 AND attempted.term_id IS NULL
             ORDER BY tm.term_id ASC
             LIMIT %d",
            self::TERM_MIGRATED_META,
            $wpdb->esc_like('pa_') . '%',
            self::BATCH_SIZE
        ));

        if (empty($term_ids)) { return false; }

        foreach ($term_ids as $term_id) {
            self::migrate_one_term((int) $term_id);
        }

        return count($term_ids) >= self::BATCH_SIZE;
    }

    
    public static function migrate_one_term(int $term_id): void {
        $type        = (string) get_term_meta($term_id, 'product_attribute_color_type', true);
        $bg_color    = (string) get_term_meta($term_id, 'product_attribute_color', true);
        $grad_c1     = (string) get_term_meta($term_id, 'product_attribute_color_gradient_color_1', true);
        $grad_c2     = (string) get_term_meta($term_id, 'product_attribute_color_gradient_color_2', true);
        $grad_dir    = (string) get_term_meta($term_id, 'product_attribute_color_gradient_direction', true);
        $multi_dir   = (string) get_term_meta($term_id, 'product_attribute_color_multiple_direction', true);
        $multi_colors = array_filter(array(
            (string) get_term_meta($term_id, 'product_attribute_color_multiple_color_1', true),
            (string) get_term_meta($term_id, 'product_attribute_color_multiple_color_2', true),
            (string) get_term_meta($term_id, 'product_attribute_color_multiple_color_3', true),
            (string) get_term_meta($term_id, 'product_attribute_color_multiple_color_4', true),
        ));
        $image_id    = (int) get_term_meta($term_id, 'product_attribute_image', true);

        
        
        $canonical_hex = '';
        if ($type === 'gradient' && $grad_c1 !== '') {
            $canonical_hex = $grad_c1;
        } elseif ($type === 'multiple' && !empty($multi_colors)) {
            $canonical_hex = reset($multi_colors);
        } elseif ($bg_color !== '') {
            $canonical_hex = $bg_color;
        }

        if ($canonical_hex !== '') {
            $sanitised = sanitize_hex_color($canonical_hex);
            if ($sanitised) {
                update_term_meta($term_id, 'color', $sanitised);
            }
        }

        if ($type !== '' && $type !== 'background') {
            update_term_meta($term_id, '_aieo_swatch_color_type', $type);

            if ($type === 'gradient' && ($grad_c1 !== '' || $grad_c2 !== '')) {
                update_term_meta($term_id, '_aieo_swatch_gradient', array(
                    'color_1'   => $grad_c1,
                    'color_2'   => $grad_c2,
                    'direction' => $grad_dir,
                ));
            } elseif ($type === 'multiple' && !empty($multi_colors)) {
                update_term_meta($term_id, '_aieo_swatch_multiple', array(
                    'colors'    => array_values($multi_colors),
                    'direction' => $multi_dir,
                ));
            }
        }

        if ($image_id > 0) {
            update_term_meta($term_id, '_aieo_swatch_image_id', $image_id);
        }

        
        
        
        
        
        update_term_meta($term_id, self::TERM_MIGRATED_META, 'yes');
    }

    
    private static function promote_attribute_types(): void {
        global $wpdb;

        $table = $wpdb->prefix . 'woocommerce_attribute_taxonomies';

        
        $wpdb->query("UPDATE {$table} SET attribute_type = 'wc-visual' WHERE attribute_type = 'color'");

        
        
        delete_transient('wc_attribute_taxonomies');
    }

    
    public static function cli_run($args, $assoc_args) {
        $force = !empty($assoc_args['force']);
        if ($force) {
            delete_option(self::COMPLETED_OPTION);
        }

        $batch = 0;
        do {
            $batch++;
            if (class_exists('WP_CLI')) { WP_CLI::log("Running batch {$batch}..."); }
            $pending = self::run();
        } while ($pending);

        if (class_exists('WP_CLI')) {
            WP_CLI::success(sprintf('AIEO→WC compat migration complete after %d batch(es).', $batch));
        }
    }
}
