<?php

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

class AIEO_TRS_Migrator {

    const LEGACY_TABLE = 'woocommerce_shipping_table_rates';

    
    public static function register() {
        if (!self::has_legacy_table()) { return; }
        add_action('wp_ajax_aieo_trs_migrate_audit', array(__CLASS__, 'ajax_audit'));
        add_action('wp_ajax_aieo_trs_migrate_run',   array(__CLASS__, 'ajax_run'));
    }

    public static function has_legacy_table() {
        global $wpdb;
        $name = $wpdb->prefix . self::LEGACY_TABLE;
        $found = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $name));
        return $found === $name;
    }

    private static function gate() {
        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(array('message' => 'permission_denied'), 403);
        }
        check_ajax_referer('aieo_trs_admin', 'nonce');
    }

    public static function ajax_audit() {
        self::gate();
        wp_send_json_success(self::audit());
    }

    public static function ajax_run() {
        self::gate();
        $batch_size = (int) (sanitize_text_field( wp_unslash( $_POST['batch_size'] ) ) ?? 500);
        $cursor     = (int) (sanitize_text_field( wp_unslash( $_POST['cursor'] ) )     ?? 0);
        wp_send_json_success(self::run($batch_size, $cursor));
    }

    
    public static function audit() {
        global $wpdb;
        if (!self::has_legacy_table()) {
            return array('legacy_table' => false, 'legacy_rows' => 0, 'already_migrated' => 0);
        }
        $legacy = $wpdb->prefix . self::LEGACY_TABLE;
        $ours   = $wpdb->prefix . 'aieo_dmm_shipping_rates';

        $legacy_count    = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$legacy}");
        $migrated_count  = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$ours} WHERE legacy_rate_id IS NOT NULL");

        
        
        $by_instance = $wpdb->get_results(
            "SELECT shipping_method_id, COUNT(*) AS rows_count
               FROM {$legacy}
              GROUP BY shipping_method_id
              ORDER BY shipping_method_id ASC",
            ARRAY_A
        );

        
        
        
        
        
        $orphan_zone_methods = (int) $wpdb->get_var(
            "SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_shipping_zone_methods
              WHERE method_id = 'table_rate'"
        );
        return array(
            'legacy_table'         => true,
            'legacy_rows'          => $legacy_count,
            'already_migrated'     => $migrated_count,
            'by_instance'          => is_array($by_instance) ? $by_instance : array(),
            'orphan_zone_methods'  => $orphan_zone_methods,
        );
    }

    
    public static function run($batch_size = 500, $cursor = 0) {
        global $wpdb;
        $batch_size = max(50, min(5000, (int) $batch_size));
        $cursor     = max(0, (int) $cursor);

        $out = array(
            'processed' => 0, 'inserted' => 0, 'updated' => 0, 'skipped' => 0,
            'next_cursor' => null, 'done' => true, 'errors' => array(),
        );

        if (!self::has_legacy_table()) {
            $out['errors'][] = __('Legacy table not present.', 'ai-eshop-optimizer');
            return $out;
        }

        $legacy = $wpdb->prefix . self::LEGACY_TABLE;
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$legacy}
              WHERE rate_id > %d
              ORDER BY rate_id ASC
              LIMIT %d",
            $cursor, $batch_size
        ), ARRAY_A);
        if (empty($rows)) { return $out; }

        $next_cursor = $cursor;
        foreach ($rows as $r) {
            $out['processed']++;
            $rate_id = (int) ($r['rate_id'] ?? 0);
            $next_cursor = max($next_cursor, $rate_id);

            $mapped = self::map_row($r);
            $check  = AIEO_TRS_Validator::validate($mapped);
            if (empty($check['ok'])) {
                $out['skipped']++;
                $out['errors'][] = sprintf(
                    
                    __('Legacy rate #%1$d skipped: %2$s', 'ai-eshop-optimizer'),
                    $rate_id,
                    implode('; ', $check['errors'])
                );
                continue;
            }
            $clean = $check['data'];
            $clean['legacy_rate_id'] = $rate_id;

            
            $existing = AIEO_TRS_Rules::find_by_legacy($rate_id);
            if ($existing && isset($existing['id'])) {
                $resp = AIEO_TRS_Rules::update((int) $existing['id'], $clean);
                if (!empty($resp['ok'])) { $out['updated']++; }
                else {
                    $out['skipped']++;
                    
                    $out['errors'][] = sprintf(__('Legacy rate #%d update failed', 'ai-eshop-optimizer'), $rate_id);
                }
            } else {
                $resp = AIEO_TRS_Rules::create($clean);
                if (!empty($resp['ok'])) { $out['inserted']++; }
                else {
                    $out['skipped']++;
                    
                    $out['errors'][] = sprintf(__('Legacy rate #%d insert failed', 'ai-eshop-optimizer'), $rate_id);
                }
            }
        }

        $done = count($rows) < $batch_size;
        $out['done']        = $done;
        $out['next_cursor'] = $done ? null : $next_cursor;

        
        
        
        
        
        
        
        
        
        
        
        
        if ($done) {
            $flipped = (int) $wpdb->query(
                "UPDATE {$wpdb->prefix}woocommerce_shipping_zone_methods
                    SET method_id = 'aieo_table_rate'
                  WHERE method_id = 'table_rate'"
            );
            $out['zone_methods_flipped'] = $flipped;

            
            
            
            
            
            
            
            
            
            
            $out['settings_copied'] = self::copy_legacy_instance_settings();

            if (($flipped > 0 || $out['settings_copied'] > 0)
                && class_exists('WC_Cache_Helper')
                && method_exists('WC_Cache_Helper', 'get_transient_version')) {
                WC_Cache_Helper::get_transient_version('shipping', true);
            }
        }

        return $out;
    }

    
    private static function copy_legacy_instance_settings() {
        global $wpdb;
        $written = 0;

        $instance_ids = $wpdb->get_col(
            "SELECT instance_id FROM {$wpdb->prefix}woocommerce_shipping_zone_methods
              WHERE method_id = 'aieo_table_rate'"
        );
        if (empty($instance_ids)) { return 0; }

        foreach ($instance_ids as $id) {
            $id = (int) $id;
            if ($id <= 0) { continue; }

            $aieo_key   = 'woocommerce_aieo_table_rate_' . $id . '_settings';
            $legacy_key = 'woocommerce_table_rate_' . $id . '_settings';

            $existing = get_option($aieo_key, array());
            if (!is_array($existing)) { $existing = array(); }
            if (!empty($existing['title'])) {
                
                continue;
            }

            $legacy = get_option($legacy_key, array());
            if (!is_array($legacy) || empty($legacy['title'])) {
                
                continue;
            }

            $patch = array_merge($existing, array(
                'title'      => (string) $legacy['title'],
                'tax_status' => isset($legacy['tax_status'])
                    ? (string) $legacy['tax_status']
                    : 'taxable',
                'enabled'    => 'yes',
            ));
            update_option($aieo_key, $patch, false);
            $written++;
        }

        return $written;
    }

    
    private static function map_row(array $r) {
        return array(
            'shipping_method_id'        => (int) ($r['shipping_method_id'] ?? 0),
            'rate_class'                => (string) ($r['rate_class'] ?? ''),
            'rate_condition'            => (string) ($r['rate_condition'] ?? ''),
            'rate_min'                  => self::nullable_decimal($r['rate_min'] ?? null),
            'rate_max'                  => self::nullable_decimal($r['rate_max'] ?? null),
            'rate_cost'                 => (float)  ($r['rate_cost'] ?? 0),
            'rate_cost_per_item'        => (float)  ($r['rate_cost_per_item'] ?? 0),
            'rate_cost_per_weight_unit' => (float)  ($r['rate_cost_per_weight_unit'] ?? 0),
            'rate_cost_percent'         => (float)  ($r['rate_cost_percent'] ?? 0),
            'rate_label'                => (string) ($r['rate_label'] ?? ''),
            'rate_priority'             => !empty($r['rate_priority']) ? 1 : 0,
            'rate_order'                => (int)    ($r['rate_order'] ?? 0),
            'rate_abort'                => !empty($r['rate_abort']) ? 1 : 0,
            'rate_abort_reason'         => (string) ($r['rate_abort_reason'] ?? ''),
            'enabled'                   => 1,
        );
    }

    private static function nullable_decimal($v) {
        if ($v === null || $v === '' || !is_numeric($v)) { return null; }
        return (float) $v;
    }
}
