<?php

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

/**
 * Product synchronization handler for FlowDino
 */
class FlowDino_WC_Sync {
    
    /**
     * API instance
     */
    private $api;
    
    /**
     * Database instance
     */
    private $database;
    
    /**
     * Constructor
     */
    public function __construct() {
        $this->api = new FlowDino_WC_API();
        $this->database = new FlowDino_WC_Database();
    }
    
    /**
     * Sync a single product
     */
    public function sync_product($product_id) {
        $product = wc_get_product($product_id);
        
        if (!$product) {
            return array(
                'success' => false,
                /* translators: Message when product is not found during sync */
                'message' => esc_html(__('Product not found', 'flowdino'))
            );
        }
        
        try {
            // Prepare product data for FlowDino
            $product_data = $this->prepare_product_data($product);
            
            // Sync to FlowDino API
            $result = $this->api->sync_product($product_data);
            
            // Update sync status
            if ($result['success']) {
                $flowdino_id = isset($result['data']['id']) ? $result['data']['id'] : null;
                $this->database->update_product_sync_status($product_id, 'synced', $flowdino_id);
            } else {
                $this->database->update_product_sync_status($product_id, 'error', null, $result['message']);
            }
            
            return $result;
            
        } catch (Exception $e) {
            $this->database->update_product_sync_status($product_id, 'error', null, $e->getMessage());
            
            return array(
                'success' => false,
                'message' => esc_html($e->getMessage())
            );
        }
    }
    
    /**
     * Prepare product data for FlowDino API
     */
    /**
     * Prepare product data in the exact format expected by FlowDino API.
     * Mirrors prepare_product_data_for_flowdino_api() in the Products tab.
     */
    private function prepare_product_data($product) {
        $default_color = get_option('flowdino_default_color', '');
        $default_brand = get_option('flowdino_default_brand', '');
        $shop_url      = get_site_url();

        $data = array(
            'source'           => 'WooCommerce',
            'title'            => $product->get_name(),
            'external_key'     => $shop_url . '-' . $product->get_id(),
            'description'      => $product->get_description() ?: $product->get_short_description(),
            'short_description' => $product->get_short_description(),
            'reference'        => $product->get_sku() ?: 'WC-' . $product->get_id(),
            'price'            => floatval($product->get_price()),
            'tax_included_price' => floatval($product->get_price()),
            'weight'           => floatval($product->get_weight() ?: 0),
            'width'            => floatval($product->get_width() ?: 0),
            'height'           => floatval($product->get_height() ?: 0),
            'depth'            => floatval($product->get_length() ?: 0),
            'quantity'         => intval($product->get_stock_quantity() ?: 0),
            'active'           => $product->get_status() === 'publish' ? 1 : 0,
            'url'              => $product->get_permalink(),
        );

        // Category (first mapped one)
        $categories = wp_get_post_terms($product->get_id(), 'product_cat');
        if (!empty($categories) && !is_wp_error($categories)) {
            foreach ($categories as $category) {
                $mapped = get_option('flowdino_category_mapping_' . $category->term_id, '');
                if (!empty($mapped)) {
                    $data['category'] = intval($mapped);
                    break;
                }
            }
        }

        // Colors
        $colors = array();
        foreach (array('pa_color', 'pa_colour', 'pa_couleur') as $taxonomy) {
            $terms = wp_get_post_terms($product->get_id(), $taxonomy);
            if (!is_wp_error($terms)) {
                foreach ($terms as $term) {
                    $mapped = get_option('flowdino_color_mapping_' . $term->term_id, '');
                    if (!empty($mapped)) {
                        $colors[] = intval($mapped);
                    }
                }
            }
        }
        if (empty($colors) && !empty($default_color)) {
            $colors[] = intval($default_color);
        }
        $data['colors'] = $colors;

        // Materials
        $materials = array();
        foreach (array('pa_material', 'pa_matiere', 'pa_materiau') as $taxonomy) {
            $terms = wp_get_post_terms($product->get_id(), $taxonomy);
            if (!is_wp_error($terms)) {
                foreach ($terms as $term) {
                    $mapped = get_option('flowdino_material_mapping_' . $term->term_id, '');
                    if (!empty($mapped)) {
                        $materials[] = intval($mapped);
                    }
                }
            }
        }
        $data['materials'] = $materials;

        // Tags
        $tags            = array();
        $tag_source_type = get_option( 'flowdino_tag_source_type', 'attribute' );
        if ( 'shipping_class' === $tag_source_type ) {
            $terms = wp_get_post_terms( $product->get_id(), 'product_shipping_class' );
            if ( ! is_wp_error( $terms ) ) {
                foreach ( $terms as $term ) {
                    $mapped = get_option( 'flowdino_tag_mapping_' . $term->term_id, '' );
                    if ( ! empty( $mapped ) ) {
                        $tags[] = intval( $mapped );
                    }
                }
            }
        } else {
            $tag_taxonomy = get_option( 'flowdino_tag_attribute', '' );
            if ( ! empty( $tag_taxonomy ) && taxonomy_exists( $tag_taxonomy ) ) {
                $terms = wp_get_post_terms( $product->get_id(), $tag_taxonomy );
                if ( ! is_wp_error( $terms ) ) {
                    foreach ( $terms as $term ) {
                        $mapped = get_option( 'flowdino_tag_mapping_' . $term->term_id, '' );
                        if ( ! empty( $mapped ) ) {
                            $tags[] = intval( $mapped );
                        }
                    }
                }
            }
        }
        $data['tags'] = $tags;

        // Video game rating (first mapped)
        $vgrating_taxonomy = get_option('flowdino_vgrating_attribute', '');
        if (!empty($vgrating_taxonomy) && taxonomy_exists($vgrating_taxonomy)) {
            $terms = wp_get_post_terms($product->get_id(), $vgrating_taxonomy);
            if (!is_wp_error($terms) && !empty($terms)) {
                $mapped = get_option('flowdino_vgrating_mapping_' . $terms[0]->term_id, '');
                if (!empty($mapped)) {
                    $data['videoGameRating'] = intval($mapped);
                }
            }
        }

        // Size (first mapped)
        foreach (array('pa_size', 'pa_taille') as $taxonomy) {
            $terms = wp_get_post_terms($product->get_id(), $taxonomy);
            if (!is_wp_error($terms) && !empty($terms)) {
                $mapped = get_option('flowdino_size_mapping_' . $terms[0]->term_id, '');
                if (!empty($mapped)) {
                    $data['size'] = intval($mapped);
                    break;
                }
            }
        }

        // Brand
        foreach (array('product_brand', 'pwb-brand', 'yith_product_brand', 'pa_brand', 'pa_marque') as $taxonomy) {
            $terms = wp_get_post_terms($product->get_id(), $taxonomy);
            if (!is_wp_error($terms) && !empty($terms)) {
                $mapped = get_option('flowdino_brand_mapping_' . $terms[0]->term_id, '');
                if (!empty($mapped)) {
                    $data['brandId'] = intval($mapped);
                    break;
                }
            }
        }
        if (!isset($data['brandId']) && !empty($default_brand)) {
            $data['brandId'] = intval($default_brand);
        }

        // Images (associative array with string-index keys, as expected by FlowDino)
        $image_ids = $product->get_gallery_image_ids();
        array_unshift($image_ids, $product->get_image_id());
        $image_urls = array();
        foreach ($image_ids as $index => $image_id) {
            if ($image_id) {
                $url = wp_get_attachment_url($image_id);
                if ($url) {
                    $image_urls[(string) $index] = $url;
                }
            }
        }
        $data['imageUrls'] = $image_urls;

        return $data;
    }
    
    /**
     * Sync a single product variation to FlowDino.
     * Each variation is sent as an independent article.
     *
     * @param int $variation_id WooCommerce variation post ID.
     * @return array Result array with 'success' boolean and 'message'.
     */
    public function sync_variation($variation_id) {
        $variation = wc_get_product($variation_id);
        if (!$variation || !$variation->is_type('variation')) {
            return array('success' => false, 'message' => esc_html__('Variation not found', 'flowdino'));
        }

        try {
            $product_data = $this->prepare_variation_data($variation);
            $result       = $this->api->sync_product($product_data, true);

            if (isset($result['success']) && $result['success']) {
                update_post_meta($variation_id, '_flowdino_sync_status', 'synced');
                update_post_meta($variation_id, '_flowdino_last_sync', current_time('mysql'));
            } else {
                update_post_meta($variation_id, '_flowdino_sync_status', 'error');
            }

            return $result;
        } catch (Exception $e) {
            update_post_meta($variation_id, '_flowdino_sync_status', 'error');
            return array('success' => false, 'message' => esc_html($e->getMessage()));
        }
    }

    /**
     * Prepare variation data for the FlowDino API.
     * The variation is sent as an independent article with its own external_key.
     *
     * @param WC_Product_Variation $variation Variation object.
     * @return array Payload ready for sync_product().
     */
    private function prepare_variation_data($variation) {
        $default_color = get_option('flowdino_default_color', '');
        $default_brand = get_option('flowdino_default_brand', '');
        $shop_url      = get_site_url();

        $parent_id = $variation->get_parent_id();
        $parent    = wc_get_product($parent_id);

        // Build human-readable title: "Parent Name - Attr1 / Attr2"
        $attr_labels = array();
        foreach ($variation->get_attributes() as $attr_name => $attr_value) {
            if (empty($attr_value)) continue;
            $term = get_term_by('slug', $attr_value, $attr_name);
            $attr_labels[] = $term ? $term->name : $attr_value;
        }
        $variation_label = !empty($attr_labels) ? implode(' / ', $attr_labels) : '';
        $title = $parent->get_name() . ($variation_label ? ' - ' . $variation_label : '') . ' #' . $variation->get_id();

        // Quantity: variation's own stock, or fall back to parent stock
        $quantity = $variation->get_manage_stock()
            ? intval($variation->get_stock_quantity() ?: 0)
            : ( $parent->get_manage_stock() ? intval($parent->get_stock_quantity() ?: 0) : 0 );

        // Active: parent published + variation published + not out-of-stock
        $active = (
            $parent->get_status() === 'publish' &&
            $variation->get_status() === 'publish' &&
            $variation->get_stock_status() !== 'outofstock'
        ) ? 1 : 0;

        $parent_description    = $parent->get_description() ?: $parent->get_short_description();
        $variation_description = $variation->get_description();
        $combined_description  = !empty($variation_description)
            ? trim( $parent_description . "\n\n" . $variation_description )
            : $parent_description;

        $data = array(
            'source'             => 'WooCommerce',
            'title'              => $title,
            'external_key'       => $shop_url . '-' . $variation->get_id(),
            'description'        => $combined_description,
            'short_description'  => $parent->get_short_description(),
            'reference'          => $variation->get_sku() ?: ('WC-' . $variation->get_id()),
            'price'              => floatval($variation->get_price()),
            'tax_included_price' => floatval($variation->get_price()),
            'weight'             => floatval($variation->get_weight() ?: $parent->get_weight() ?: 0),
            'width'              => floatval($variation->get_width()  ?: $parent->get_width()  ?: 0),
            'height'             => floatval($variation->get_height() ?: $parent->get_height() ?: 0),
            'depth'              => floatval($variation->get_length() ?: $parent->get_length() ?: 0),
            'quantity'           => $quantity,
            'active'             => $active,
            'url'                => $variation->get_permalink(),
        );

        // Category — inherited from parent
        $categories = wp_get_post_terms($parent_id, 'product_cat');
        if (!empty($categories) && !is_wp_error($categories)) {
            foreach ($categories as $cat) {
                $mapped = get_option('flowdino_category_mapping_' . $cat->term_id, '');
                if (!empty($mapped)) {
                    $data['category'] = intval($mapped);
                    break;
                }
            }
        }

        // Colors — variation-specific attribute first, then parent
        $colors           = array();
        $color_taxonomies = array('pa_color', 'pa_colour', 'pa_couleur');
        foreach ($variation->get_attributes() as $attr_name => $attr_value) {
            if (empty($attr_value) || !in_array($attr_name, $color_taxonomies, true)) continue;
            $term = get_term_by('slug', $attr_value, $attr_name);
            if ($term) {
                $mapped = get_option('flowdino_color_mapping_' . $term->term_id, '');
                if (!empty($mapped)) { $colors[] = intval($mapped); }
            }
        }
        if (empty($colors)) {
            foreach ($color_taxonomies as $taxonomy) {
                $terms = wp_get_post_terms($parent_id, $taxonomy);
                if (!is_wp_error($terms)) {
                    foreach ($terms as $term) {
                        $mapped = get_option('flowdino_color_mapping_' . $term->term_id, '');
                        if (!empty($mapped)) { $colors[] = intval($mapped); }
                    }
                }
            }
        }
        if (empty($colors) && !empty($default_color)) { $colors[] = intval($default_color); }
        $data['colors'] = $colors;

        // Materials — from parent
        $materials = array();
        foreach (array('pa_material', 'pa_matiere', 'pa_materiau') as $taxonomy) {
            $terms = wp_get_post_terms($parent_id, $taxonomy);
            if (!is_wp_error($terms)) {
                foreach ($terms as $term) {
                    $mapped = get_option('flowdino_material_mapping_' . $term->term_id, '');
                    if (!empty($mapped)) { $materials[] = intval($mapped); }
                }
            }
        }
        $data['materials'] = $materials;

        // Tags — variation-specific attribute first, then parent; shipping class from parent
        $tags            = array();
        $tag_source_type = get_option( 'flowdino_tag_source_type', 'attribute' );
        if ( 'shipping_class' === $tag_source_type ) {
            $terms = wp_get_post_terms( $parent_id, 'product_shipping_class' );
            if ( ! is_wp_error( $terms ) ) {
                foreach ( $terms as $term ) {
                    $mapped = get_option( 'flowdino_tag_mapping_' . $term->term_id, '' );
                    if ( ! empty( $mapped ) ) { $tags[] = intval( $mapped ); }
                }
            }
        } else {
            $tag_taxonomy = get_option( 'flowdino_tag_attribute', '' );
            if ( ! empty( $tag_taxonomy ) && taxonomy_exists( $tag_taxonomy ) ) {
                $tag_set = false;
                foreach ( $variation->get_attributes() as $attr_name => $attr_value ) {
                    if ( empty( $attr_value ) || $attr_name !== $tag_taxonomy ) { continue; }
                    $term = get_term_by( 'slug', $attr_value, $attr_name );
                    if ( $term ) {
                        $mapped = get_option( 'flowdino_tag_mapping_' . $term->term_id, '' );
                        if ( ! empty( $mapped ) ) { $tags[] = intval( $mapped ); $tag_set = true; }
                    }
                }
                if ( ! $tag_set ) {
                    $terms = wp_get_post_terms( $parent_id, $tag_taxonomy );
                    if ( ! is_wp_error( $terms ) ) {
                        foreach ( $terms as $term ) {
                            $mapped = get_option( 'flowdino_tag_mapping_' . $term->term_id, '' );
                            if ( ! empty( $mapped ) ) { $tags[] = intval( $mapped ); }
                        }
                    }
                }
            }
        }
        $data['tags'] = $tags;

        // Size — variation-specific first, then parent
        $size_taxonomies = array('pa_size', 'pa_taille');
        $size_set        = false;
        foreach ($variation->get_attributes() as $attr_name => $attr_value) {
            if (empty($attr_value) || !in_array($attr_name, $size_taxonomies, true)) continue;
            $term = get_term_by('slug', $attr_value, $attr_name);
            if ($term) {
                $mapped = get_option('flowdino_size_mapping_' . $term->term_id, '');
                if (!empty($mapped)) { $data['size'] = intval($mapped); $size_set = true; break; }
            }
        }
        if (!$size_set) {
            foreach ($size_taxonomies as $taxonomy) {
                $terms = wp_get_post_terms($parent_id, $taxonomy);
                if (!is_wp_error($terms) && !empty($terms)) {
                    $mapped = get_option('flowdino_size_mapping_' . $terms[0]->term_id, '');
                    if (!empty($mapped)) { $data['size'] = intval($mapped); break; }
                }
            }
        }

        // Brand — from parent
        foreach (array('product_brand', 'pwb-brand', 'yith_product_brand', 'pa_brand', 'pa_marque') as $taxonomy) {
            $terms = wp_get_post_terms($parent_id, $taxonomy);
            if (!is_wp_error($terms) && !empty($terms)) {
                $mapped = get_option('flowdino_brand_mapping_' . $terms[0]->term_id, '');
                if (!empty($mapped)) { $data['brandId'] = intval($mapped); break; }
            }
        }
        if (!isset($data['brandId']) && !empty($default_brand)) { $data['brandId'] = intval($default_brand); }

        // Video game rating — from parent
        $vgrating_taxonomy = get_option('flowdino_vgrating_attribute', '');
        if (!empty($vgrating_taxonomy) && taxonomy_exists($vgrating_taxonomy)) {
            $terms = wp_get_post_terms($parent_id, $vgrating_taxonomy);
            if (!is_wp_error($terms) && !empty($terms)) {
                $mapped = get_option('flowdino_vgrating_mapping_' . $terms[0]->term_id, '');
                if (!empty($mapped)) { $data['videoGameRating'] = intval($mapped); }
            }
        }

        // Images — variation image first, then parent gallery
        $image_urls = array();
        $idx = 0;
        $variation_img_id = $variation->get_image_id();
        if ($variation_img_id) {
            $url = wp_get_attachment_url($variation_img_id);
            if ($url) { $image_urls[(string)$idx] = $url; $idx++; }
        }
        $parent_image_ids = $parent->get_gallery_image_ids();
        array_unshift($parent_image_ids, $parent->get_image_id());
        foreach ($parent_image_ids as $img_id) {
            if ($img_id) {
                $url = wp_get_attachment_url($img_id);
                if ($url) { $image_urls[(string)$idx] = $url; $idx++; }
            }
        }
        $data['imageUrls'] = $image_urls;

        // Variation overlay
        if (!empty($variation_label) && get_option('flowdino_variation_overlay_enabled', 0)) {
            $overlay = array('content' => $variation_label);
            $pos = get_option('flowdino_variation_overlay_position', 'top-left');
            if (!empty($pos)) { $overlay['position'] = $pos; }
            $col = get_option('flowdino_variation_overlay_color', '#1B5897');
            if (!empty($col)) { $overlay['color'] = $col; }
            $sz = intval(get_option('flowdino_variation_overlay_size', 30));
            if ($sz > 0) { $overlay['size'] = $sz; }
            $msk = get_option('flowdino_variation_overlay_mask', '');
            if (!empty($msk)) { $overlay['mask'] = $msk; }
            $data['variation'] = $overlay;
        }

        return $data;
    }

    /**
     * Update stock for a product
     */
    public function update_stock($product_id) {
        $product = wc_get_product($product_id);

        if (!$product) {
            return false;
        }

        $sync_status = $this->database->get_product_sync_status($product_id);

        if (!$sync_status || !$sync_status->flowdino_id) {
            // Product not synced yet, do full sync
            return $this->sync_product($product_id);
        }

        // Prepare stock update data
        $stock_data = array(
            'id' => $sync_status->flowdino_id,
            'stock_quantity' => $product->get_stock_quantity(),
            'stock_status' => $product->get_stock_status()
        );

        // Send stock update to FlowDino
        $result = $this->api->sync_product($stock_data);
        
        if ($result['success']) {
            $this->database->update_product_sync_status($product_id, 'synced', $sync_status->flowdino_id);
        } else {
            $this->database->update_product_sync_status($product_id, 'error', $sync_status->flowdino_id, $result['message']);
        }
        
        return $result;
    }
    
    /**
     * Delete product from FlowDino
     */
    public function delete_product($product_id) {
        $sync_status = $this->database->get_product_sync_status($product_id);
        
        if ($sync_status && $sync_status->flowdino_id) {
            $result = $this->api->delete_product($sync_status->flowdino_id);
            
            if ($result) {
                // Remove from sync table
                global $wpdb;
                $table = $wpdb->prefix . 'flowdino_product_sync';
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table delete for plugin-specific sync status cleanup
                $wpdb->delete($table, array('product_id' => $product_id));
            }
            
            return $result;
        }
        
        return true; // Product wasn't synced, so consider it "deleted"
    }
    
    /**
     * Bulk sync products
     */
    public function bulk_sync_products($product_ids) {
        $results = array();
        
        foreach ($product_ids as $product_id) {
            $results[$product_id] = $this->sync_product($product_id);
        }
        
        return $results;
    }
    
    /**
     * Get sync statistics
     */
    public function get_sync_stats() {
        global $wpdb;
        
        $table = $wpdb->prefix . 'flowdino_product_sync';
        
        $stats = array(
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Standard WordPress posts table query for product count statistics
            'total_products' => $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = 'product' AND post_status = 'publish'"),
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table query for plugin-specific sync statistics
            'synced' => $wpdb->get_var("SELECT COUNT(*) FROM " . esc_sql($table) . " WHERE sync_status = 'synced'"),
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table query for plugin-specific sync statistics
            'pending' => $wpdb->get_var("SELECT COUNT(*) FROM " . esc_sql($table) . " WHERE sync_status = 'pending'"),
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table query for plugin-specific sync statistics
            'errors' => $wpdb->get_var("SELECT COUNT(*) FROM " . esc_sql($table) . " WHERE sync_status = 'error'"),
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table query for plugin-specific sync statistics
            'last_sync' => $wpdb->get_var("SELECT MAX(last_sync) FROM " . esc_sql($table))
        );
        
        $stats['not_synced'] = $stats['total_products'] - $stats['synced'] - $stats['pending'] - $stats['errors'];
        
        return $stats;
    }
}
