<?php

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

class AIEO_Exchanger_Product_Importer {

    
    public static function apply(array $payload, $match_key, $mode) {
        global $wpdb;

        $existing_id = self::find_existing_product_id($payload, $match_key);

        if ($existing_id <= 0 && $mode === 'update_only') {
            return array('outcome' => 'skipped', 'product_id' => 0);
        }

        $wpdb->query('START TRANSACTION');
        try {
            if ($existing_id > 0) {
                $product_id = self::update_product($existing_id, $payload, $mode);
                $wpdb->query('COMMIT');
                return array('outcome' => 'updated', 'product_id' => $product_id);
            }

            $product_id = self::create_product($payload, $mode);
            $wpdb->query('COMMIT');
            return array('outcome' => 'created', 'product_id' => $product_id);
        } catch (\Throwable $e) {
            $wpdb->query('ROLLBACK');
            return array('outcome' => 'error', 'product_id' => 0, 'error' => $e->getMessage()); 
        }
    }

    
    public static function find_existing_product_id(array $payload, $match_key) {
        $barcode = (string) ($payload['match']['barcode'] ?? '');
        $sku     = (string) ($payload['match']['sku']     ?? '');

        if ($match_key === 'barcode' && $barcode !== '') {
            global $wpdb;
            $pid = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT post_id FROM {$wpdb->postmeta}
                 WHERE meta_key = '_global_unique_id' AND meta_value = %s LIMIT 1",
                $barcode
            ));
            if ($pid > 0) {
                $post = get_post($pid);
                if ($post && $post->post_type === 'product_variation') { $pid = (int) $post->post_parent; }
                if ($pid > 0) { return $pid; }
            }
        }
        if ($match_key === 'sku' && $sku !== '' && function_exists('wc_get_product_id_by_sku')) {
            $pid = (int) wc_get_product_id_by_sku($sku);
            if ($pid > 0) {
                $post = get_post($pid);
                if ($post && $post->post_type === 'product_variation') { $pid = (int) $post->post_parent; }
                if ($pid > 0) { return $pid; }
            }
        }
        return 0;
    }

    
    public static function create_product(array $payload, $mode) {
        $type = (string) ($payload['type'] ?? 'simple');
        if ($type === 'variable') {
            $product = new WC_Product_Variable();
        } else {
            $product = new WC_Product_Simple();
        }
        $product->set_name((string) ($payload['title'] ?? ''));
        if (!empty($payload['slug'])) { $product->set_slug((string) $payload['slug']); }
        $product->set_description((string) ($payload['description'] ?? ''));
        $product->set_short_description((string) ($payload['short_description'] ?? ''));
        $product->set_status((string) ($payload['status'] ?? 'publish'));
        if (!empty($payload['match']['sku'])) { $product->set_sku((string) $payload['match']['sku']); }

        if ($type !== 'variable') {
            self::apply_simple_pricing($product, $payload);
        }
        self::apply_dimensions($product, $payload);
        self::apply_attributes($product, $payload, $mode);
        $product_id = $product->save();

        
        if (!empty($payload['match']['barcode'])) {
            update_post_meta($product_id, '_global_unique_id', (string) $payload['match']['barcode']);
        }

        self::apply_terms($product_id, $payload, $mode);
        self::apply_images($product_id, $product, $payload);
        self::apply_video_meta($product_id, $payload);
        self::apply_extra_meta($product_id, $payload, $mode);

        if ($type === 'variable') {
            self::apply_variations($product_id, $payload, $mode);
        }

        return (int) $product_id;
    }

    
    public static function update_product($product_id, array $payload, $mode) {
        $product = wc_get_product($product_id);
        if (!$product) {
            
            throw new \RuntimeException('product_lookup_failed: ' . $product_id);
        }

        
        $product->set_name((string) ($payload['title'] ?? $product->get_name()));
        $product->set_description((string) ($payload['description'] ?? $product->get_description()));
        $product->set_short_description((string) ($payload['short_description'] ?? $product->get_short_description()));

        if ($product->get_type() !== 'variable') {
            self::apply_simple_pricing($product, $payload);
        }
        self::apply_dimensions($product, $payload);
        if ($mode === 'overwrite') {
            self::apply_attributes($product, $payload, $mode);
        }
        $product->save();

        if (!empty($payload['match']['barcode'])) {
            update_post_meta($product_id, '_global_unique_id', (string) $payload['match']['barcode']);
        }

        if ($mode === 'overwrite') {
            self::apply_terms($product_id, $payload, $mode);
            self::apply_images($product_id, $product, $payload);
            self::apply_video_meta($product_id, $payload);
        }
        self::apply_extra_meta($product_id, $payload, $mode);

        if ($product->get_type() === 'variable' && $mode === 'overwrite') {
            self::apply_variations($product_id, $payload, $mode);
        }

        return (int) $product_id;
    }

    private static function apply_simple_pricing(WC_Product $product, array $payload) {
        if (array_key_exists('regular_price', $payload)) {
            $product->set_regular_price($payload['regular_price'] === null ? '' : (string) $payload['regular_price']);
        }
        if (array_key_exists('sale_price', $payload)) {
            $product->set_sale_price($payload['sale_price'] === null ? '' : (string) $payload['sale_price']);
        }
        if (!empty($payload['stock'])) {
            $stock = $payload['stock'];
            if (isset($stock['manage'])) { $product->set_manage_stock((bool) $stock['manage']); }
            if (isset($stock['quantity']) && $stock['quantity'] !== null) { $product->set_stock_quantity((int) $stock['quantity']); }
            if (!empty($stock['status'])) { $product->set_stock_status((string) $stock['status']); }
        }
    }

    private static function apply_dimensions(WC_Product $product, array $payload) {
        if (!empty($payload['weight']))          { $product->set_weight((string) $payload['weight']); }
        if (!empty($payload['dimensions']['length'])) { $product->set_length((string) $payload['dimensions']['length']); }
        if (!empty($payload['dimensions']['width']))  { $product->set_width((string) $payload['dimensions']['width']); }
        if (!empty($payload['dimensions']['height'])) { $product->set_height((string) $payload['dimensions']['height']); }
    }

    
    private static function apply_attributes(WC_Product $product, array $payload, $mode) {
        if (empty($payload['attributes']) || !is_array($payload['attributes'])) { return; }
        $product_attributes = array();

        foreach ($payload['attributes'] as $attr) {
            if (empty($attr['taxonomy'])) { continue; } 
            $taxonomy = (string) $attr['taxonomy'];

            if (!taxonomy_exists($taxonomy)) {
                if ($mode === 'create_link_only' || $mode === 'update_only') {
                    continue;
                }
                self::ensure_attribute_taxonomy($taxonomy, (string) ($attr['name'] ?? $taxonomy));
                if (!taxonomy_exists($taxonomy)) { continue; }
            }

            $resolution = AIEO_Exchanger_Term_Resolver::resolve_terms((array) $attr['terms'], $taxonomy, $mode);
            if (empty($resolution['term_ids'])) { continue; }

            $a = new WC_Product_Attribute();
            $a->set_id(wc_attribute_taxonomy_id_by_name($taxonomy));
            $a->set_name($taxonomy);
            $a->set_options($resolution['term_ids']);
            $a->set_visible((bool) ($attr['visible']   ?? true));
            $a->set_variation((bool) ($attr['variation'] ?? false));
            $product_attributes[$taxonomy] = $a;
        }
        if (!empty($product_attributes)) {
            $product->set_attributes($product_attributes);
        }
    }

    
    private static function ensure_attribute_taxonomy($taxonomy, $label) {
        $name = preg_replace('/^pa_/', '', $taxonomy);
        if (!$name) { return 0; }
        $attribute_id = wc_attribute_taxonomy_id_by_name($taxonomy);
        if ($attribute_id) { return $attribute_id; }

        $args = array(
            'attribute_label'   => $label !== '' ? $label : $name,
            'attribute_name'    => $name,
            'attribute_type'    => 'select',
            'attribute_orderby' => 'menu_order',
            'attribute_public'  => 0,
        );
        global $wpdb;
        $wpdb->insert($wpdb->prefix . 'woocommerce_attribute_taxonomies', $args);
        delete_transient('wc_attribute_taxonomies');
        if (function_exists('wp_cache_delete')) { wp_cache_delete('woocommerce-attribute-taxonomies', 'options'); }
        
        register_taxonomy($taxonomy, array('product'), array('label' => $label, 'public' => false, 'rewrite' => false));
        return (int) $wpdb->insert_id;
    }

    private static function apply_terms($product_id, array $payload, $mode) {
        foreach (array(
            'brand_terms'    => 'product_brand',
            'category_terms' => 'product_cat',
            'need_terms'     => 'pa_need',
        ) as $key => $taxonomy) {
            if (!taxonomy_exists($taxonomy)) { continue; }
            $entries = (array) ($payload[$key] ?? array());
            $resolution = AIEO_Exchanger_Term_Resolver::resolve_terms($entries, $taxonomy, $mode);
            if (!empty($resolution['term_ids']) || $mode === 'overwrite') {
                wp_set_object_terms((int) $product_id, $resolution['term_ids'], $taxonomy, false);
            }
        }
    }

    private static function apply_images($product_id, WC_Product $product, array $payload) {
        
        if (!empty($payload['images'][0]['src'])) {
            $aid = AIEO_Exchanger_Image_Resolver::resolve((string) $payload['images'][0]['src'], $product_id, 'thumbnail_id');
            if ($aid > 0) {
                set_post_thumbnail($product_id, $aid);
            }
        }
        
        if (!empty($payload['gallery']) && is_array($payload['gallery'])) {
            $gallery_ids = array();
            foreach ($payload['gallery'] as $g) {
                $src = (string) ($g['src'] ?? '');
                if ($src === '') { continue; }
                $aid = AIEO_Exchanger_Image_Resolver::resolve($src, $product_id, '');
                if ($aid > 0) { $gallery_ids[] = $aid; }
            }
            if (!empty($gallery_ids)) {
                update_post_meta($product_id, '_product_image_gallery', implode(',', $gallery_ids));
            }
        }
    }

    private static function apply_video_meta($product_id, array $payload) {
        if (empty($payload['video']) || !is_array($payload['video'])) { return; }
        $v = $payload['video'];
        update_post_meta($product_id, '_merchant_enable_featured_video',  !empty($v['enable_featured']) ? '1' : '');
        update_post_meta($product_id, '_merchant_product_video_url',       (string) ($v['url'] ?? ''));
        update_post_meta($product_id, '_merchant_product_video_autoplay', !empty($v['autoplay']) ? '1' : '');
        update_post_meta($product_id, '_merchant_product_video_aspect_ratio', (string) ($v['aspect_ratio'] ?? ''));
        update_post_meta($product_id, '_merchant_videos_in_gallery',      !empty($v['include_in_gallery']) ? '1' : '');
        update_post_meta($product_id, '_merchant_video_position',          (string) ($v['position'] ?? ''));
    }

    private static function apply_extra_meta($product_id, array $payload, $mode) {
        if (empty($payload['extra_meta']) || !is_array($payload['extra_meta'])) { return; }
        foreach ($payload['extra_meta'] as $k => $v) {
            if (!is_string($k)) { continue; }
            $existing = get_post_meta((int) $product_id, $k, true);
            if ($existing !== '' && $mode === 'update_only')   { continue; }
            if ($existing !== '' && $mode !== 'overwrite' && $mode !== 'create_with_term_meta') {
                continue;
            }
            update_post_meta((int) $product_id, $k, is_scalar($v) ? (string) $v : $v);
        }
    }

    
    private static function apply_variations($product_id, array $payload, $mode) {
        if (empty($payload['variations']) || !is_array($payload['variations'])) { return; }

        if ($mode === 'overwrite') {
            $existing = wc_get_products(array(
                'parent'  => (int) $product_id,
                'type'    => 'variation',
                'limit'   => -1,
                'status'  => array('publish', 'private'),
                'return'  => 'ids',
            ));
            foreach ((array) $existing as $eid) {
                wp_delete_post((int) $eid, true);
            }
        }

        foreach ($payload['variations'] as $vp) {
            $vid = self::find_variation_id_by_match($product_id, $vp);

            $variation = $vid > 0 ? wc_get_product($vid) : new WC_Product_Variation();
            if (!$variation) { continue; }

            if (!($variation instanceof WC_Product_Variation)) {
                $variation = new WC_Product_Variation();
            }
            $variation->set_parent_id((int) $product_id);
            if (!empty($vp['match']['sku']))     { $variation->set_sku((string) $vp['match']['sku']); }
            if (array_key_exists('regular_price', $vp)) {
                $variation->set_regular_price($vp['regular_price'] === null ? '' : (string) $vp['regular_price']);
            }
            if (array_key_exists('sale_price', $vp)) {
                $variation->set_sale_price($vp['sale_price'] === null ? '' : (string) $vp['sale_price']);
            }
            if (!empty($vp['stock']) && is_array($vp['stock'])) {
                if (isset($vp['stock']['quantity']) && $vp['stock']['quantity'] !== null) { $variation->set_stock_quantity((int) $vp['stock']['quantity']); }
                if (!empty($vp['stock']['status'])) { $variation->set_stock_status((string) $vp['stock']['status']); }
            }
            if (isset($vp['manage_stock'])) { $variation->set_manage_stock((bool) $vp['manage_stock']); }
            if (!empty($vp['weight']))      { $variation->set_weight((string) $vp['weight']); }
            $variation->set_status((string) ($vp['status'] ?? 'publish'));

            if (!empty($vp['attributes']) && is_array($vp['attributes'])) {
                $variation->set_attributes($vp['attributes']);
            }
            $vid_saved = $variation->save();

            if (!empty($vp['match']['barcode'])) {
                update_post_meta($vid_saved, '_global_unique_id', (string) $vp['match']['barcode']);
            }

            
            if (!empty($vp['image']['src'])) {
                $aid = AIEO_Exchanger_Image_Resolver::resolve((string) $vp['image']['src'], $vid_saved, '');
                if ($aid > 0) { set_post_thumbnail($vid_saved, $aid); }
            }
            
            
            
            
            if (!empty($vp['variation_gallery']) && is_array($vp['variation_gallery'])) {
                $gids = array();
                foreach ($vp['variation_gallery'] as $g) {
                    $src = (string) ($g['src'] ?? '');
                    if ($src === '') { continue; }
                    $aid = AIEO_Exchanger_Image_Resolver::resolve($src, $vid_saved, '');
                    if ($aid > 0) { $gids[] = $aid; }
                }
                if (!empty($gids)) {
                    update_post_meta($vid_saved, '_product_image_gallery', implode(',', $gids));
                    update_post_meta($vid_saved, '_wc_variation_gallery_legacy_fallback_disabled', 'yes');
                    delete_post_meta($vid_saved, 'botiga_variation_gallery');
                }
            }
        }

        
        WC_Product_Variable::sync($product_id);
    }

    
    private static function find_variation_id_by_match($product_id, array $vp) {
        $sku = (string) ($vp['match']['sku'] ?? '');
        if ($sku !== '' && function_exists('wc_get_product_id_by_sku')) {
            $vid = (int) wc_get_product_id_by_sku($sku);
            if ($vid > 0) {
                $post = get_post($vid);
                if ($post && $post->post_type === 'product_variation' && (int) $post->post_parent === (int) $product_id) {
                    return $vid;
                }
            }
        }
        $barcode = (string) ($vp['match']['barcode'] ?? '');
        if ($barcode !== '') {
            global $wpdb;
            $vid = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT pm.post_id FROM {$wpdb->postmeta} pm
                 INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
                 WHERE pm.meta_key = '_global_unique_id' AND pm.meta_value = %s
                   AND p.post_type = 'product_variation' AND p.post_parent = %d
                 LIMIT 1",
                $barcode, (int) $product_id
            ));
            if ($vid > 0) { return $vid; }
        }
        return 0;
    }
}
