<?php

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

class AIEO_Exchanger_Product_Serializer {

    const VERSION = 1;

    
    public static function serialize($product_id) {
        $product = wc_get_product((int) $product_id);
        if (!$product) { return null; }

        $is_variable = $product->is_type('variable');

        $payload = array(
            'exchanger_version' => self::VERSION,
            'source_site_url'   => home_url(),

            'match' => array(
                'barcode' => (string) get_post_meta($product->get_id(), '_global_unique_id', true),
                'sku'     => (string) $product->get_sku(),
            ),
            'type'              => $product->get_type(),
            'status'            => $product->get_status(),
            'title'             => $product->get_name(),
            'slug'              => $product->get_slug(),
            'description'       => $product->get_description(),
            'short_description' => $product->get_short_description(),

            'regular_price'     => self::nullable_string($product->get_regular_price()),
            'sale_price'        => self::nullable_string($product->get_sale_price()),
            'stock'             => self::stock($product),
            'weight'            => self::nullable_string($product->get_weight()),
            'dimensions'        => array(
                'length' => self::nullable_string($product->get_length()),
                'width'  => self::nullable_string($product->get_width()),
                'height' => self::nullable_string($product->get_height()),
            ),

            'brand_terms'    => self::serialize_taxonomy_terms($product->get_id(), 'product_brand', array('thumbnail_id', 'brand_logo'), array('footer_text')),
            'category_terms' => self::serialize_taxonomy_terms($product->get_id(), 'product_cat',   array('thumbnail_id'), array()),
            'need_terms'     => self::serialize_taxonomy_terms($product->get_id(), 'pa_need',       array(), array()),

            'attributes'     => self::serialize_attributes($product),
            'images'         => self::main_image($product),
            'gallery'        => self::gallery($product),
            'video'          => self::video($product->get_id()),
            'variations'     => $is_variable ? self::variations($product) : array(),

            'extra_meta'     => self::extra_meta($product->get_id()),
        );

        return $payload;
    }

    private static function nullable_string($v) {
        $v = (string) $v;
        return $v === '' ? null : $v;
    }

    private static function stock(WC_Product $product) {
        return array(
            'manage'   => (bool) $product->get_manage_stock(),
            'quantity' => $product->get_manage_stock() ? (int) $product->get_stock_quantity() : null,
            'status'   => (string) $product->get_stock_status(),
        );
    }

    
    private static function serialize_taxonomy_terms($product_id, $taxonomy, array $image_meta_keys, array $passthrough_meta_keys) {
        if (!taxonomy_exists($taxonomy)) { return array(); }
        $terms = wp_get_object_terms((int) $product_id, $taxonomy);
        if (is_wp_error($terms) || empty($terms)) { return array(); }

        $out = array();
        foreach ($terms as $term) {
            $entry = array(
                'slug'        => $term->slug,
                'name'        => $term->name,
                'description' => (string) $term->description,
                'parent_slug' => $term->parent ? self::get_term_slug($term->parent, $taxonomy) : null,
            );
            
            foreach ($image_meta_keys as $mk) {
                $aid = (int) get_term_meta($term->term_id, $mk, true);
                if ($aid > 0) {
                    $url = wp_get_attachment_image_url($aid, 'full');
                    if ($url) {
                        
                        
                        $key = $mk === 'thumbnail_id' ? 'thumbnail' : $mk;
                        $entry[$key] = array('src' => $url);
                    }
                }
            }
            
            $extras = array();
            foreach ($passthrough_meta_keys as $mk) {
                $val = get_term_meta($term->term_id, $mk, true);
                if ($val !== '' && $val !== null) {
                    $extras[$mk] = is_scalar($val) ? (string) $val : $val;
                }
            }
            if (!empty($extras)) { $entry['extra_term_meta'] = $extras; }

            $out[] = $entry;
        }
        return $out;
    }

    private static function get_term_slug($term_id, $taxonomy) {
        $t = get_term((int) $term_id, $taxonomy);
        return ($t && !is_wp_error($t)) ? $t->slug : null;
    }

    
    private static function serialize_attributes(WC_Product $product) {
        $out = array();
        foreach ($product->get_attributes() as $slug => $attr) {
            
            $row = array(
                'taxonomy'  => $attr->is_taxonomy() ? $attr->get_taxonomy() : '',
                'name'      => $attr->is_taxonomy() ? wc_attribute_label($attr->get_name()) : (string) $attr->get_name(),
                'visible'   => (bool) $attr->get_visible(),
                'variation' => (bool) $attr->get_variation(),
                'terms'     => array(),
            );
            if ($attr->is_taxonomy()) {
                $tax = $attr->get_taxonomy();
                foreach ($attr->get_terms() ?: array() as $term) {
                    $term_entry = array(
                        'slug'        => $term->slug,
                        'name'        => $term->name,
                        'description' => (string) $term->description,
                    );
                    $swatch = self::resolve_term_swatch($term->term_id);
                    if ($swatch) { $term_entry['swatch'] = $swatch; }
                    $row['terms'][] = $term_entry;
                }
            } else {
                
                foreach ($attr->get_options() as $val) {
                    $val = (string) $val;
                    if ($val === '') { continue; }
                    $row['terms'][] = array(
                        'slug' => sanitize_title($val),
                        'name' => $val,
                    );
                }
            }
            $out[] = $row;
        }
        return $out;
    }

    
    public static function resolve_term_swatch($term_id) {
        $term_id = (int) $term_id;
        $img_id  = (int) get_term_meta($term_id, 'product_attribute_image', true);
        if ($img_id > 0) {
            $url = wp_get_attachment_image_url($img_id, 'full');
            if ($url) { return array('type' => 'image', 'src' => $url); }
        }
        $type = (string) get_term_meta($term_id, 'product_attribute_color_type', true);
        if ($type === 'gradient') {
            $c1  = (string) get_term_meta($term_id, 'product_attribute_color_gradient_color_1', true);
            $c2  = (string) get_term_meta($term_id, 'product_attribute_color_gradient_color_2', true);
            $dir = (string) get_term_meta($term_id, 'product_attribute_color_gradient_direction', true);
            if ($c1 !== '' || $c2 !== '') {
                return array('type' => 'gradient', 'from' => $c1, 'to' => $c2, 'direction' => $dir ?: 'to right');
            }
        }
        if ($type === 'multiple') {
            $colors = array();
            for ($i = 1; $i <= 4; $i++) {
                $c = (string) get_term_meta($term_id, 'product_attribute_color_multiple_color_' . $i, true);
                if ($c !== '') { $colors[] = $c; }
            }
            $dir = (string) get_term_meta($term_id, 'product_attribute_color_multiple_direction', true);
            if (!empty($colors)) {
                return array('type' => 'multiple', 'colors' => $colors, 'direction' => $dir ?: 'to right');
            }
        }
        
        $color = (string) get_term_meta($term_id, 'product_attribute_color', true);
        if ($color !== '') {
            return array('type' => 'color', 'value' => $color);
        }
        return null;
    }

    private static function main_image(WC_Product $product) {
        $aid = (int) $product->get_image_id();
        if ($aid <= 0) { return array(); }
        $url = wp_get_attachment_image_url($aid, 'full');
        if (!$url) { return array(); }
        $alt = (string) get_post_meta($aid, '_wp_attachment_image_alt', true);
        return array(array('src' => $url, 'alt' => $alt));
    }

    private static function gallery(WC_Product $product) {
        $ids = (array) $product->get_gallery_image_ids();
        $out = array();
        foreach ($ids as $aid) {
            $url = wp_get_attachment_image_url((int) $aid, 'full');
            if ($url) { $out[] = array('src' => $url); }
        }
        return $out;
    }

    
    private static function video($product_id) {
        $url = (string) get_post_meta($product_id, '_merchant_product_video_url', true);
        if ($url === '') { return null; }
        return array(
            'enable_featured'    => (string) get_post_meta($product_id, '_merchant_enable_featured_video', true) === '1',
            'url'                => $url,
            'autoplay'           => (string) get_post_meta($product_id, '_merchant_product_video_autoplay', true) === '1',
            'aspect_ratio'       => (string) get_post_meta($product_id, '_merchant_product_video_aspect_ratio', true),
            'include_in_gallery' => (string) get_post_meta($product_id, '_merchant_videos_in_gallery', true) === '1',
            'position'           => (string) get_post_meta($product_id, '_merchant_video_position', true),
        );
    }

    private static function variations(WC_Product $product) {
        $variation_ids = $product->get_children();
        $out = array();
        foreach ($variation_ids as $vid) {
            $v = wc_get_product((int) $vid);
            if (!$v) { continue; }

            
            $img = null;
            $img_id = (int) $v->get_image_id();
            if ($img_id > 0) {
                $url = wp_get_attachment_image_url($img_id, 'full');
                if ($url) { $img = array('src' => $url); }
            }

            
            
            
            
            $variation_gallery = array();
            $vg_ids = class_exists('AIEO_DMM_Variations_Gallery')
                ? AIEO_DMM_Variations_Gallery::resolve_image_ids((int) $vid, 'serializer')
                : array();
            if (empty($vg_ids)) {
                
                $legacy = get_post_meta((int) $vid, 'botiga_variation_gallery', true);
                if (is_array($legacy)) {
                    foreach ($legacy as $aid) {
                        if (is_numeric($aid) && (int) $aid > 0) { $vg_ids[] = (int) $aid; }
                    }
                }
            }
            foreach ($vg_ids as $aid) {
                $url = wp_get_attachment_image_url((int) $aid, 'full');
                if ($url) { $variation_gallery[] = array('src' => $url); }
            }

            
            $attrs = array();
            foreach ($v->get_variation_attributes() as $tax_key => $term_slug) {
                $attrs[$tax_key] = (string) $term_slug;
            }

            $out[] = array(
                'match' => array(
                    'barcode' => (string) get_post_meta((int) $vid, '_global_unique_id', true),
                    'sku'     => (string) $v->get_sku(),
                ),
                'status'        => $v->get_status(),
                'enabled'       => $v->variation_is_active(),
                'manage_stock'  => (bool) $v->get_manage_stock(),
                'downloadable'  => (bool) $v->get_downloadable(),
                'virtual'       => (bool) $v->get_virtual(),
                'attributes'    => $attrs,
                'regular_price' => self::nullable_string($v->get_regular_price()),
                'sale_price'    => self::nullable_string($v->get_sale_price()),
                'stock'         => array(
                    'quantity' => $v->get_manage_stock() ? (int) $v->get_stock_quantity() : null,
                    'status'   => (string) $v->get_stock_status(),
                ),
                'weight'        => self::nullable_string($v->get_weight()),
                'image'             => $img,
                'variation_gallery' => $variation_gallery,
            );
        }
        return $out;
    }

    
    private static function extra_meta($product_id) {
        $whitelist = apply_filters('aieo_exchanger_product_meta_whitelist', array(
            '_purchase_note',
            '_aieo_dmm_floor',
            '_aieo_dmm_priority_pin',
        ), (int) $product_id);

        $out = array();
        foreach ($whitelist as $key) {
            $v = get_post_meta((int) $product_id, $key, true);
            if ($v !== '' && $v !== null && !is_array($v) && !is_object($v)) {
                $out[$key] = (string) $v;
            }
        }
        return $out;
    }
}
