<?php
/**
 * GGM Commerce WooCommerce Mapper
 *
 * Handles conversion of WooCommerce export format to GGM Commerce format
 *
 * @package GGM_Commerce
 * @since 1.0.0
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

class GGM_Commerce_WooCommerce_Mapper {

    /**
     * WooCommerce to GGM Commerce field mapping
     * @var array
     */
    const FIELD_MAP = [
        // Post fields
        'ID' => 'id',
        'post_title' => 'name',
        'post_name' => 'slug',
        'post_content' => 'description',
        'post_excerpt' => 'short_description',
        'post_status' => 'status',

        // Basic product meta
        '_sku' => 'sku',
        '_regular_price' => 'price',
        '_sale_price' => 'sale_price',
        '_stock' => 'stock',
        '_stock_status' => 'stock_status',
        '_manage_stock' => 'manage_stock',

        // Shipping
        '_weight' => 'weight',
        '_length' => 'length',
        '_width' => 'width',
        '_height' => 'height',
        '_virtual' => 'is_virtual',

        // Type
        '_downloadable' => 'is_downloadable',
        'product_type' => 'product_type',

        // Images
        '_thumbnail_id' => 'image',
        '_product_image_gallery' => 'gallery_images',

        // Taxonomy
        'product_cat' => 'categories',
        'product_tag' => 'tags',

        // Featured
        '_featured' => 'featured',
    ];

    /**
     * WooCommerce headers that indicate this is a WooCommerce export
     * @var array
     */
    const WOO_INDICATORS = [
        'post_title',
        '_regular_price',
        '_sku',
        '_stock',
        'product_cat',
        '_thumbnail_id',
        'post_content',
        '_weight',
        'product_type'
    ];

    /**
     * Check if headers indicate WooCommerce format
     *
     * @param array $headers CSV headers
     * @return bool True if WooCommerce format detected
     */
    public function is_woocommerce_format($headers) {
        $matches = 0;

        foreach ($headers as $header) {
            if (in_array($header, self::WOO_INDICATORS)) {
                $matches++;
            }
        }

        // If 3 or more WooCommerce-specific headers found, it's likely a WooCommerce export
        return $matches >= 3;
    }

    /**
     * Convert a WooCommerce row to GGM Commerce format
     *
     * @param array $row WooCommerce data row
     * @return array GGM Commerce formatted row
     */
    public function convert_row($row) {
        $converted = [];

        foreach ($row as $woo_field => $value) {
            // Direct field mapping
            if (isset(self::FIELD_MAP[$woo_field])) {
                $ggm_field = self::FIELD_MAP[$woo_field];
                $converted[$ggm_field] = $this->convert_value($woo_field, $value);
                continue;
            }

            // Handle attributes (pa_*)
            if (strpos($woo_field, 'pa_') === 0) {
                $attr_name = ucfirst(str_replace('pa_', '', $woo_field));
                $attr_name = str_replace('-', ' ', $attr_name);
                $converted['attr:' . $attr_name] = $value;
                continue;
            }

            // Handle meta (meta:*)
            if (strpos($woo_field, 'meta:') === 0) {
                $meta_key = substr($woo_field, 5);
                if (isset(self::FIELD_MAP[$meta_key])) {
                    $converted[self::FIELD_MAP[$meta_key]] = $this->convert_value($meta_key, $value);
                }
                continue;
            }
        }

        // Post-processing conversions
        $converted = $this->post_process_row($converted, $row);

        return $converted;
    }

    /**
     * Convert a single value based on field type
     *
     * @param string $field WooCommerce field name
     * @param mixed $value Original value
     * @return mixed Converted value
     */
    private function convert_value($field, $value) {
        switch ($field) {
            // Status conversion
            case 'post_status':
                return $this->convert_status($value);

            // Stock status conversion
            case '_stock_status':
                return $this->convert_stock_status($value);

            // Boolean conversions
            case '_manage_stock':
            case '_virtual':
            case '_downloadable':
            case '_featured':
                return $this->convert_boolean($value);

            // Image gallery (comma-separated IDs in WooCommerce)
            case '_product_image_gallery':
                return $value; // Keep as-is, will be processed later

            // Categories and tags (may have hierarchy)
            case 'product_cat':
            case 'product_tag':
                return $this->convert_taxonomy($value);

            // Product type
            case 'product_type':
                return $this->convert_product_type($value);

            default:
                return $value;
        }
    }

    /**
     * Convert WooCommerce post status to GGM status
     *
     * @param string $status WooCommerce status
     * @return string GGM status
     */
    private function convert_status($status) {
        $map = [
            'publish' => 'active',
            'draft' => 'draft',
            'pending' => 'draft',
            'private' => 'draft',
            'trash' => 'archived',
            'future' => 'draft',
        ];

        return isset($map[$status]) ? $map[$status] : 'active';
    }

    /**
     * Convert WooCommerce stock status
     *
     * @param string $status WooCommerce stock status
     * @return string GGM stock status
     */
    private function convert_stock_status($status) {
        $map = [
            'instock' => 'instock',
            'outofstock' => 'outofstock',
            'onbackorder' => 'backorder',
        ];

        return isset($map[$status]) ? $map[$status] : 'instock';
    }

    /**
     * Convert boolean value
     *
     * @param mixed $value Value to convert
     * @return int 1 or 0
     */
    private function convert_boolean($value) {
        if (is_bool($value)) {
            return $value ? 1 : 0;
        }

        $true_values = ['yes', 'true', '1', 1, true];

        if (in_array(strtolower($value), $true_values, true) || in_array($value, $true_values, true)) {
            return 1;
        }

        return 0;
    }

    /**
     * Convert taxonomy value (handle hierarchy)
     *
     * @param string $value Taxonomy value (may include hierarchy with >)
     * @return string Cleaned taxonomy value
     */
    private function convert_taxonomy($value) {
        // WooCommerce exports hierarchical categories like "Parent > Child"
        // We'll take the last item in the hierarchy
        $parts = explode(',', $value);
        $cleaned = [];

        foreach ($parts as $part) {
            $part = trim($part);
            if (strpos($part, '>') !== false) {
                // Take the last part of hierarchy
                $hierarchy = explode('>', $part);
                $cleaned[] = trim(end($hierarchy));
            } else {
                $cleaned[] = $part;
            }
        }

        return implode(',', array_unique(array_filter($cleaned)));
    }

    /**
     * Convert WooCommerce product type to GGM type
     *
     * @param string $type WooCommerce type
     * @return string GGM type
     */
    private function convert_product_type($type) {
        $map = [
            'simple' => 'simple',
            'variable' => 'simple', // We handle variations separately
            'grouped' => 'kit',
            'external' => 'simple',
            'subscription' => 'simple',
            'bundle' => 'kit',
        ];

        return isset($map[$type]) ? $map[$type] : 'simple';
    }

    /**
     * Post-process the converted row
     *
     * @param array $converted Converted row
     * @param array $original Original WooCommerce row
     * @return array Processed row
     */
    private function post_process_row($converted, $original) {
        // Handle variations flag
        if (isset($original['product_type']) && $original['product_type'] === 'variable') {
            $converted['has_variations'] = 1;
            $converted['variation_mode'] = 'combined';
        }

        // Handle backorder stock status
        if (isset($original['_backorders']) && $original['_backorders'] === 'yes') {
            $converted['stock_status'] = 'backorder';
        }

        // Set requires_shipping based on virtual
        if (isset($converted['is_virtual']) && $converted['is_virtual'] == 1) {
            $converted['requires_shipping'] = 0;
        } else {
            $converted['requires_shipping'] = 1;
        }

        // Handle tax status
        if (isset($original['_tax_status']) && $original['_tax_status'] === 'none') {
            $converted['tax_rate_id'] = ''; // No tax
        }

        // Process downloadable files if present
        if (isset($original['_downloadable_files']) && !empty($original['_downloadable_files'])) {
            $converted['downloads'] = $this->convert_downloads($original['_downloadable_files']);
        }

        return $converted;
    }

    /**
     * Convert WooCommerce downloadable files format
     *
     * @param string $downloads_data WooCommerce downloads data
     * @return string JSON encoded downloads for GGM format
     */
    private function convert_downloads($downloads_data) {
        // WooCommerce exports downloads in various formats
        // Attempt to parse and convert
        $downloads = [];

        // Try JSON first
        $decoded = json_decode($downloads_data, true);
        if (is_array($decoded)) {
            foreach ($decoded as $download) {
                $downloads[] = [
                    'name' => isset($download['name']) ? $download['name'] : 'Download',
                    'url' => isset($download['file']) ? $download['file'] : '',
                    'limit' => -1,
                    'expiry_days' => -1
                ];
            }
        }

        return wp_json_encode($downloads);
    }

    /**
     * Get the full field mapping
     *
     * @return array Field mapping array
     */
    public function get_field_map() {
        return self::FIELD_MAP;
    }

    /**
     * Generate a mapping configuration for WooCommerce import
     *
     * @param array $csv_headers CSV headers from WooCommerce export
     * @return array Mapping configuration
     */
    public function generate_mapping($csv_headers) {
        $mapping = [];

        foreach ($csv_headers as $header) {
            // Check direct mapping
            if (isset(self::FIELD_MAP[$header])) {
                $mapping[$header] = self::FIELD_MAP[$header];
                continue;
            }

            // Handle attribute columns (pa_*)
            if (strpos($header, 'pa_') === 0) {
                $attr_name = ucfirst(str_replace('pa_', '', $header));
                $attr_name = str_replace('-', ' ', $attr_name);
                $mapping[$header] = 'attr:' . $attr_name;
                continue;
            }

            // Handle meta columns
            if (strpos($header, 'meta:') === 0) {
                $meta_key = substr($header, 5);
                if (isset(self::FIELD_MAP[$meta_key])) {
                    $mapping[$header] = self::FIELD_MAP[$meta_key];
                    continue;
                }
            }

            // Skip unmapped columns
            $mapping[$header] = '';
        }

        return $mapping;
    }

    /**
     * Process variations from WooCommerce export
     *
     * @param array $products Array of converted products
     * @return array Products with variations processed
     */
    public function process_variations($products) {
        $parents = [];
        $variations = [];

        // Separate parent products and variations
        foreach ($products as $product) {
            if (isset($product['post_parent']) && !empty($product['post_parent'])) {
                $variations[$product['post_parent']][] = $product;
            } else {
                $parents[$product['id']] = $product;
            }
        }

        // Attach variations to parents
        foreach ($variations as $parent_id => $product_variations) {
            if (isset($parents[$parent_id])) {
                $parents[$parent_id]['variations'] = wp_json_encode(
                    array_map(function($v) {
                        return [
                            'sku' => $v['sku'] ?? '',
                            'price' => $v['price'] ?? null,
                            'sale_price' => $v['sale_price'] ?? null,
                            'stock' => $v['stock'] ?? null,
                            'stock_status' => $v['stock_status'] ?? 'instock',
                            'is_default' => 0,
                            'image' => $v['image'] ?? '',
                            'attributes' => $this->extract_variation_attributes($v)
                        ];
                    }, $product_variations)
                );
                $parents[$parent_id]['has_variations'] = 1;
            }
        }

        return array_values($parents);
    }

    /**
     * Extract variation attributes from a variation product
     *
     * @param array $variation Variation data
     * @return array Attributes
     */
    private function extract_variation_attributes($variation) {
        $attributes = [];

        foreach ($variation as $key => $value) {
            if (strpos($key, 'attr:') === 0 && !empty($value)) {
                $attr_name = substr($key, 5);
                $attributes[$attr_name] = $value;
            }
        }

        return $attributes;
    }

    /**
     * Get list of WooCommerce indicator headers for detection
     *
     * @return array Indicator headers
     */
    public function get_indicator_headers() {
        return self::WOO_INDICATORS;
    }

    /**
     * Get human-readable format information
     *
     * @return array Format info
     */
    public function get_format_info() {
        return [
            'name' => __('WooCommerce Export', 'ggm-commerce'),
            'description' => __('Standard WooCommerce product export CSV format', 'ggm-commerce'),
            'indicators' => self::WOO_INDICATORS,
            'supported_fields' => array_keys(self::FIELD_MAP)
        ];
    }
}
