<?php
/**
 * GGM Commerce CSV Importer
 *
 * Handles CSV import functionality for products
 *
 * @package GGM_Commerce
 * @since 1.0.0
 */

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

// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
// phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching
// phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter

class GGM_Commerce_CSV_Importer {

    /**
     * Import session data transient key
     * @var string
     */
    private $session_key;

    /**
     * Current import progress
     * @var array
     */
    private $progress = [
        'total' => 0,
        'processed' => 0,
        'created' => 0,
        'updated' => 0,
        'skipped' => 0,
        'errors' => []
    ];

    /**
     * Batch start timestamp for time-aware processing
     * @var int
     */
    private $batch_start_time = 0;

    /**
     * Constructor
     */
    public function __construct() {
        $this->session_key = 'ggmc_import_' . get_current_user_id();
    }

    /**
     * Parse CSV file and return preview data
     *
     * @param string $file_path Path to CSV file
     * @return array|WP_Error Parsed data or error
     */
    public function parse_csv($file_path) {
        if (!file_exists($file_path)) {
            return new WP_Error('file_not_found', __('CSV file not found', 'ggm-commerce'));
        }

        $handle = fopen($file_path, 'r');
        if (!$handle) {
            return new WP_Error('file_read_error', __('Could not read CSV file', 'ggm-commerce'));
        }

        // Skip BOM if present
        $bom = fread($handle, 3);
        if ($bom !== "\xEF\xBB\xBF") {
            rewind($handle);
        }

        // Read headers
        $headers = fgetcsv($handle);
        if (empty($headers)) {
            fclose($handle);
            return new WP_Error('empty_file', __('CSV file is empty or has no headers', 'ggm-commerce'));
        }

        // Clean headers
        $headers = array_map('trim', $headers);
        $headers = array_map(function($h) {
            return preg_replace('/^\xEF\xBB\xBF/', '', $h);
        }, $headers);

        // Count rows and get sample
        $row_count = 0;
        $sample_rows = [];

        while (($row = fgetcsv($handle)) !== false) {
            $row_count++;
            if (count($sample_rows) < 5) {
                $row_data = [];
                foreach ($headers as $i => $header) {
                    $row_data[$header] = isset($row[$i]) ? $row[$i] : '';
                }
                $sample_rows[] = $row_data;
            }
        }

        fclose($handle);

        return [
            'headers' => $headers,
            'row_count' => $row_count,
            'sample_rows' => $sample_rows,
            'file_path' => $file_path
        ];
    }

    /**
     * Detect the format of the CSV file
     *
     * @param array $headers CSV headers
     * @return string Format type: 'ggm_commerce', 'woocommerce', 'unknown'
     */
    public function detect_format($headers) {
        // WooCommerce indicators
        $woo_headers = ['post_title', '_regular_price', '_sku', '_stock', 'product_cat', '_thumbnail_id'];
        $woo_matches = count(array_intersect($headers, $woo_headers));

        if ($woo_matches >= 3) {
            return 'woocommerce';
        }

        // GGM Commerce indicators
        $ggm_headers = ['name', 'sku', 'price', 'stock', 'categories', 'status', 'product_type'];
        $ggm_matches = count(array_intersect($headers, $ggm_headers));

        if ($ggm_matches >= 3) {
            return 'ggm_commerce';
        }

        return 'unknown';
    }

    /**
     * Initialize import session - call before starting batch imports
     *
     * @param string $file_path Path to CSV file
     * @param array $mapping Column mapping
     * @param array $options Import options
     * @return array|WP_Error Initial state or error
     */
    public function init_import($file_path, $mapping, $options = []) {
        $defaults = [
            'duplicate_handling' => 'update',
            'download_images' => true,
            'create_categories' => true,
            'create_tags' => true,
            'create_attributes' => true,
            'batch_size' => 10, // Process 10 products per batch for responsive UI
        ];

        $options = wp_parse_args($options, $defaults);

        // Parse CSV to get headers and count
        $handle = fopen($file_path, 'r');
        if (!$handle) {
            return new WP_Error('file_read_error', __('Could not read CSV file', 'ggm-commerce'));
        }

        // Skip BOM
        $bom = fread($handle, 3);
        if ($bom !== "\xEF\xBB\xBF") {
            rewind($handle);
        }

        // Read headers
        $headers = fgetcsv($handle);
        $headers = array_map('trim', $headers);

        // Count total rows
        $total = 0;
        while (fgetcsv($handle) !== false) {
            $total++;
        }
        fclose($handle);

        // Initialize progress
        $this->progress = [
            'total' => $total,
            'processed' => 0,
            'created' => 0,
            'updated' => 0,
            'skipped' => 0,
            'errors' => [],
            'skipped_images' => [],
            'current_product' => '',
            'status' => 'running',
            'file_path' => $file_path,
            'headers' => $headers,
            'mapping' => $mapping,
            'options' => $options,
            'current_row' => 0,
        ];

        $this->save_progress();

        return [
            'total' => $total,
            'batch_size' => $options['batch_size'],
            'status' => 'initialized'
        ];
    }

    /**
     * Process the next batch of imports
     *
     * @return array Batch result with progress info
     */
    public function process_batch() {
        // Try to extend execution time for image-heavy imports
        @set_time_limit(120);

        // Load current progress
        $this->progress = $this->get_progress();

        if (empty($this->progress) || $this->progress['status'] !== 'running') {
            return new WP_Error('no_session', __('No active import session', 'ggm-commerce'));
        }

        $file_path = $this->progress['file_path'];
        $headers = $this->progress['headers'];
        $mapping = $this->progress['mapping'];
        $options = $this->progress['options'];
        $start_row = $this->progress['current_row'];
        $batch_size = isset($options['batch_size']) ? $options['batch_size'] : 10;

        // Track time to avoid gateway/PHP execution timeout
        $this->batch_start_time = time();
        // Use 25 seconds as safety limit — most web server gateway timeouts are 30-60s
        // and we need to finish and return a response before the gateway kills us
        $time_limit = 25;

        // Open file
        $handle = fopen($file_path, 'r');
        if (!$handle) {
            $this->progress['status'] = 'error';
            $this->save_progress();
            return new WP_Error('file_read_error', __('Could not read CSV file', 'ggm-commerce'));
        }

        // Skip BOM
        $bom = fread($handle, 3);
        if ($bom !== "\xEF\xBB\xBF") {
            rewind($handle);
        }

        // Skip header row
        fgetcsv($handle);

        // Skip to current position
        for ($i = 0; $i < $start_row; $i++) {
            fgetcsv($handle);
        }

        // Process batch
        $processed_in_batch = 0;
        while ($processed_in_batch < $batch_size && ($row = fgetcsv($handle)) !== false) {
            // Check if we're running low on time before starting next product
            $elapsed = time() - $this->batch_start_time;
            if ($processed_in_batch > 0 && $elapsed >= $time_limit) {
                break; // Save progress and let the next AJAX call continue
            }

            $row_data = [];
            foreach ($headers as $idx => $header) {
                $row_data[$header] = isset($row[$idx]) ? $row[$idx] : '';
            }

            // Update current product name for UI
            $product_name = '';
            foreach ($mapping as $csv_col => $field) {
                if ($field === 'name' && isset($row_data[$csv_col])) {
                    $product_name = $row_data[$csv_col];
                    break;
                }
            }
            $this->progress['current_product'] = $product_name;

            $result = $this->import_single_product($row_data, $mapping, $options);

            if (is_wp_error($result)) {
                $this->progress['errors'][] = [
                    'row' => $this->progress['processed'] + 1,
                    'message' => $result->get_error_message(),
                    'data' => $product_name ?: 'Unknown'
                ];
            } elseif ($result === 'created') {
                $this->progress['created']++;
            } elseif ($result === 'updated') {
                $this->progress['updated']++;
            } else {
                $this->progress['skipped']++;
            }

            $this->progress['processed']++;
            $this->progress['current_row']++;
            $processed_in_batch++;

            // Save progress after each product so work isn't lost on timeout
            $this->save_progress();
        }

        fclose($handle);

        // Check if complete
        if ($this->progress['processed'] >= $this->progress['total']) {
            $this->progress['status'] = 'complete';
            $this->progress['current_product'] = '';

            // Save import report if there are skipped images or errors
            if (!empty($this->progress['skipped_images']) || !empty($this->progress['errors'])) {
                $this->save_import_report();
            }
        }

        $this->save_progress();

        return [
            'total' => $this->progress['total'],
            'processed' => $this->progress['processed'],
            'created' => $this->progress['created'],
            'updated' => $this->progress['updated'],
            'skipped' => $this->progress['skipped'],
            'errors' => $this->progress['errors'],
            'skipped_images' => isset($this->progress['skipped_images']) ? $this->progress['skipped_images'] : [],
            'current_product' => $this->progress['current_product'],
            'status' => $this->progress['status'],
            'batch_processed' => $processed_in_batch,
        ];
    }

    /**
     * Import products from CSV (legacy single-call method)
     * Kept for backwards compatibility but not recommended for large imports
     *
     * @param string $file_path Path to CSV file
     * @param array $mapping Column mapping
     * @param array $options Import options
     * @return array Import results
     */
    public function import_products($file_path, $mapping, $options = []) {
        // Initialize import
        $init_result = $this->init_import($file_path, $mapping, $options);
        if (is_wp_error($init_result)) {
            return $init_result;
        }

        // Process all batches until complete
        do {
            $batch_result = $this->process_batch();
            if (is_wp_error($batch_result)) {
                return $batch_result;
            }
        } while ($batch_result['status'] === 'running');

        return $this->progress;
    }

    /**
     * Import a single product
     *
     * @param array $row_data Row data from CSV
     * @param array $mapping Column mapping
     * @param array $options Import options
     * @return string|WP_Error Result: 'created', 'updated', 'skipped', or WP_Error
     */
    private function import_single_product($row_data, $mapping, $options) {
        global $wpdb;

        // Map CSV data to product fields
        $product_data = $this->map_row_to_product($row_data, $mapping);

        // Validate required fields
        $validation = $this->validate_product_data($product_data);
        if (is_wp_error($validation)) {
            return $validation;
        }

        // Check for existing product by SKU
        $existing_product = null;
        if (!empty($product_data['sku'])) {
            $existing_product = $wpdb->get_row($wpdb->prepare(
                "SELECT * FROM {$wpdb->prefix}ggmc_products WHERE sku = %s",
                $product_data['sku']
            ));
        }

        // Handle duplicates
        if ($existing_product) {
            switch ($options['duplicate_handling']) {
                case 'skip':
                    return 'skipped';

                case 'update':
                    return $this->update_product($existing_product->id, $product_data, $row_data, $mapping, $options);

                case 'create':
                    // Continue to create (will have duplicate SKU)
                    break;
            }
        }

        // Create new product
        return $this->create_product($product_data, $row_data, $mapping, $options);
    }

    /**
     * Map CSV row to product data
     *
     * @param array $row_data CSV row data
     * @param array $mapping Column mapping
     * @return array Product data
     */
    private function map_row_to_product($row_data, $mapping) {
        $product_data = [];

        // Standard field mappings
        $standard_fields = [
            'name', 'slug', 'sku', 'description', 'short_description',
            'price', 'sale_price', 'stock', 'stock_status', 'manage_stock',
            'weight', 'length', 'width', 'height', 'featured', 'status',
            'product_type', 'tax_rate_id', 'requires_shipping', 'is_virtual',
            'is_downloadable', 'has_variations', 'variation_mode'
        ];

        foreach ($standard_fields as $field) {
            if (isset($mapping[$field]) && $mapping[$field] !== '' && isset($row_data[$mapping[$field]])) {
                $product_data[$field] = $row_data[$mapping[$field]];
            }
        }

        // Set defaults
        $product_data['status'] = $product_data['status'] ?? 'active';
        $product_data['product_type'] = $product_data['product_type'] ?? 'simple';
        $product_data['stock_status'] = $product_data['stock_status'] ?? 'instock';
        $product_data['manage_stock'] = isset($product_data['manage_stock']) ? (int)$product_data['manage_stock'] : 1;

        // Generate slug if not provided
        if (empty($product_data['slug']) && !empty($product_data['name'])) {
            $product_data['slug'] = sanitize_title($product_data['name']);
        }

        return $product_data;
    }

    /**
     * Validate product data
     *
     * @param array $product_data Product data
     * @return true|WP_Error
     */
    private function validate_product_data($product_data) {
        if (empty($product_data['name'])) {
            return new WP_Error('missing_name', __('Product name is required', 'ggm-commerce'));
        }

        if (isset($product_data['price']) && $product_data['price'] !== '' && !is_numeric($product_data['price'])) {
            return new WP_Error('invalid_price', __('Price must be a number', 'ggm-commerce'));
        }

        if (isset($product_data['stock']) && $product_data['stock'] !== '' && !is_numeric($product_data['stock'])) {
            return new WP_Error('invalid_stock', __('Stock must be a number', 'ggm-commerce'));
        }

        return true;
    }

    /**
     * Create a new product
     *
     * @param array $product_data Product data
     * @param array $row_data Original CSV row
     * @param array $mapping Column mapping
     * @param array $options Import options
     * @return string|WP_Error
     */
    private function create_product($product_data, $row_data, $mapping, $options) {
        global $wpdb;

        // Prepare data for insert
        $insert_data = [
            'name' => sanitize_text_field($product_data['name']),
            'slug' => sanitize_title($product_data['slug'] ?? $product_data['name']),
            'sku' => sanitize_text_field($product_data['sku'] ?? ''),
            'description' => wp_kses_post($product_data['description'] ?? ''),
            'short_description' => wp_kses_post($product_data['short_description'] ?? ''),
            'price' => floatval($product_data['price'] ?? 0),
            'sale_price' => !empty($product_data['sale_price']) ? floatval($product_data['sale_price']) : null,
            'stock' => intval($product_data['stock'] ?? 0),
            'stock_status' => sanitize_text_field($product_data['stock_status'] ?? 'instock'),
            'manage_stock' => intval($product_data['manage_stock'] ?? 1),
            'weight' => !empty($product_data['weight']) ? floatval($product_data['weight']) : null,
            'length' => !empty($product_data['length']) ? floatval($product_data['length']) : null,
            'width' => !empty($product_data['width']) ? floatval($product_data['width']) : null,
            'height' => !empty($product_data['height']) ? floatval($product_data['height']) : null,
            'featured' => intval($product_data['featured'] ?? 0),
            'status' => sanitize_text_field($product_data['status'] ?? 'active'),
            'product_type' => sanitize_text_field($product_data['product_type'] ?? 'simple'),
            'requires_shipping' => intval($product_data['requires_shipping'] ?? 1),
            'is_virtual' => intval($product_data['is_virtual'] ?? 0),
            'is_downloadable' => intval($product_data['is_downloadable'] ?? 0),
            'has_variations' => intval($product_data['has_variations'] ?? 0),
            'variation_mode' => sanitize_text_field($product_data['variation_mode'] ?? 'combined'),
        ];

        // Ensure unique slug
        $insert_data['slug'] = GGM_Commerce_Database::generate_unique_slug($insert_data['name']);

        $result = $wpdb->insert(
            "{$wpdb->prefix}ggmc_products",
            $insert_data
        );

        if (!$result) {
            return new WP_Error('insert_failed', __('Failed to create product', 'ggm-commerce'));
        }

        $product_id = $wpdb->insert_id;

        // Handle related data
        $this->process_product_relationships($product_id, $row_data, $mapping, $options);

        return 'created';
    }

    /**
     * Update an existing product
     *
     * @param int $product_id Product ID
     * @param array $product_data Product data
     * @param array $row_data Original CSV row
     * @param array $mapping Column mapping
     * @param array $options Import options
     * @return string|WP_Error
     */
    private function update_product($product_id, $product_data, $row_data, $mapping, $options) {
        global $wpdb;

        $update_data = [];

        // Only update fields that have values in CSV
        $fields = [
            'name', 'description', 'short_description', 'price', 'sale_price',
            'stock', 'stock_status', 'manage_stock', 'weight', 'length',
            'width', 'height', 'featured', 'status', 'product_type',
            'requires_shipping', 'is_virtual', 'is_downloadable',
            'has_variations', 'variation_mode'
        ];

        foreach ($fields as $field) {
            if (isset($product_data[$field]) && $product_data[$field] !== '') {
                switch ($field) {
                    case 'name':
                    case 'description':
                    case 'short_description':
                        $update_data[$field] = $field === 'name'
                            ? sanitize_text_field($product_data[$field])
                            : wp_kses_post($product_data[$field]);
                        break;
                    case 'price':
                    case 'sale_price':
                    case 'weight':
                    case 'length':
                    case 'width':
                    case 'height':
                        $update_data[$field] = floatval($product_data[$field]);
                        break;
                    case 'stock':
                    case 'manage_stock':
                    case 'featured':
                    case 'requires_shipping':
                    case 'is_virtual':
                    case 'is_downloadable':
                    case 'has_variations':
                        $update_data[$field] = intval($product_data[$field]);
                        break;
                    default:
                        $update_data[$field] = sanitize_text_field($product_data[$field]);
                }
            }
        }

        if (!empty($update_data)) {
            $wpdb->update(
                "{$wpdb->prefix}ggmc_products",
                $update_data,
                ['id' => $product_id]
            );
        }

        // Handle related data
        $this->process_product_relationships($product_id, $row_data, $mapping, $options);

        return 'updated';
    }

    /**
     * Process product relationships (categories, tags, images, etc.)
     *
     * @param int $product_id Product ID
     * @param array $row_data Original CSV row
     * @param array $mapping Column mapping
     * @param array $options Import options
     */
    private function process_product_relationships($product_id, $row_data, $mapping, $options) {
        // Process categories
        if (isset($mapping['categories']) && !empty($row_data[$mapping['categories']])) {
            $this->process_categories($product_id, $row_data[$mapping['categories']], $options['create_categories']);
        }

        // Process tags
        if (isset($mapping['tags']) && !empty($row_data[$mapping['tags']])) {
            $this->process_tags($product_id, $row_data[$mapping['tags']], $options['create_tags']);
        }

        // Process main image
        if (isset($mapping['image']) && !empty($row_data[$mapping['image']])) {
            $this->process_image($product_id, $row_data[$mapping['image']], $options['download_images']);
        }

        // Process gallery images
        if (isset($mapping['gallery_images']) && !empty($row_data[$mapping['gallery_images']])) {
            $this->process_gallery($product_id, $row_data[$mapping['gallery_images']], $options['download_images']);
        }

        // Process attributes
        $create_attributes = isset($options['create_attributes']) ? $options['create_attributes'] : false;
        foreach ($mapping as $csv_column => $field) {
            if (strpos($field, 'attr:') === 0 && !empty($row_data[$csv_column])) {
                $attr_name = substr($field, 5);
                $this->process_attribute($product_id, $attr_name, $row_data[$csv_column], $create_attributes);
            }
        }

        // Process barcodes
        if (isset($mapping['barcode_primary']) && !empty($row_data[$mapping['barcode_primary']])) {
            $barcode_type = isset($mapping['barcode_type']) && !empty($row_data[$mapping['barcode_type']])
                ? $row_data[$mapping['barcode_type']]
                : 'EAN-13';
            $this->process_barcode($product_id, $row_data[$mapping['barcode_primary']], $barcode_type, true);
        }

        // Process kit components
        if (isset($mapping['kit_components']) && !empty($row_data[$mapping['kit_components']])) {
            $kit_type = isset($mapping['kit_type']) && !empty($row_data[$mapping['kit_type']])
                ? $row_data[$mapping['kit_type']]
                : 'kit';
            $auto_price = isset($mapping['kit_auto_price']) && isset($row_data[$mapping['kit_auto_price']])
                ? (int)$row_data[$mapping['kit_auto_price']]
                : 1;
            $this->process_kit($product_id, $row_data[$mapping['kit_components']], $kit_type, $auto_price);
        }

        // Process downloads
        if (isset($mapping['downloads']) && !empty($row_data[$mapping['downloads']])) {
            $this->process_downloads($product_id, $row_data[$mapping['downloads']]);
        }

        // Process variations
        if (isset($mapping['variations']) && !empty($row_data[$mapping['variations']])) {
            $this->process_variations($product_id, $row_data[$mapping['variations']]);
        }
    }

    /**
     * Process product categories
     */
    private function process_categories($product_id, $categories_string, $create_missing) {
        global $wpdb;

        // Clear existing categories
        $wpdb->delete("{$wpdb->prefix}ggmc_product_categories", ['product_id' => $product_id]);

        $categories = array_map('trim', explode(',', $categories_string));

        foreach ($categories as $category_name) {
            if (empty($category_name)) continue;

            // Find or create category
            $category = $wpdb->get_row($wpdb->prepare(
                "SELECT id FROM {$wpdb->prefix}ggmc_categories WHERE name = %s OR slug = %s",
                $category_name,
                sanitize_title($category_name)
            ));

            if (!$category && $create_missing) {
                $wpdb->insert("{$wpdb->prefix}ggmc_categories", [
                    'name' => sanitize_text_field($category_name),
                    'slug' => sanitize_title($category_name),
                    'status' => 'active'
                ]);
                $category_id = $wpdb->insert_id;
            } elseif ($category) {
                $category_id = $category->id;
            } else {
                continue;
            }

            // Link product to category
            $wpdb->insert("{$wpdb->prefix}ggmc_product_categories", [
                'product_id' => $product_id,
                'category_id' => $category_id
            ]);
        }
    }

    /**
     * Process product tags
     */
    private function process_tags($product_id, $tags_string, $create_missing) {
        global $wpdb;

        // Clear existing tags
        $wpdb->delete("{$wpdb->prefix}ggmc_product_tags", ['product_id' => $product_id]);

        $tags = array_map('trim', explode(',', $tags_string));

        foreach ($tags as $tag_name) {
            if (empty($tag_name)) continue;

            // Find or create tag
            $tag = $wpdb->get_row($wpdb->prepare(
                "SELECT id FROM {$wpdb->prefix}ggmc_tags WHERE name = %s OR slug = %s",
                $tag_name,
                sanitize_title($tag_name)
            ));

            if (!$tag && $create_missing) {
                $wpdb->insert("{$wpdb->prefix}ggmc_tags", [
                    'name' => sanitize_text_field($tag_name),
                    'slug' => sanitize_title($tag_name),
                    'status' => 'active'
                ]);
                $tag_id = $wpdb->insert_id;
            } elseif ($tag) {
                $tag_id = $tag->id;
            } else {
                continue;
            }

            // Link product to tag
            $wpdb->insert("{$wpdb->prefix}ggmc_product_tags", [
                'product_id' => $product_id,
                'tag_id' => $tag_id
            ]);
        }
    }

    /**
     * Process product main image
     */
    private function process_image($product_id, $image_value, $download_from_url) {
        global $wpdb;

        $image_id = $this->resolve_image($image_value, $download_from_url);

        if ($image_id) {
            $wpdb->update(
                "{$wpdb->prefix}ggmc_products",
                ['image_id' => $image_id],
                ['id' => $product_id]
            );
        } elseif ($download_from_url && filter_var($image_value, FILTER_VALIDATE_URL)) {
            $product_name = $this->progress['current_product'] ?? '';
            $this->progress['skipped_images'][] = [
                'product' => $product_name,
                'url' => $image_value,
                'reason' => 'download_failed',
                'type' => 'main',
            ];
        }
    }

    /**
     * Process product gallery images
     */
    private function process_gallery($product_id, $gallery_string, $download_from_url) {
        global $wpdb;

        $images = array_map('trim', explode(',', $gallery_string));
        $gallery_ids = [];
        $product_name = $this->progress['current_product'] ?? '';
        $hit_time_limit = false;

        foreach ($images as $image_value) {
            if (empty($image_value)) continue;

            // Once we've hit the time limit, track all remaining as skipped
            if ($hit_time_limit) {
                $this->progress['skipped_images'][] = [
                    'product' => $product_name,
                    'url' => $image_value,
                    'reason' => 'timeout',
                ];
                continue;
            }

            // Check time before downloading
            if ($download_from_url && $this->batch_start_time > 0) {
                $elapsed = time() - $this->batch_start_time;
                if ($elapsed >= 20) {
                    $hit_time_limit = true;
                    $this->progress['skipped_images'][] = [
                        'product' => $product_name,
                        'url' => $image_value,
                        'reason' => 'timeout',
                    ];
                    continue;
                }
            }

            $image_id = $this->resolve_image($image_value, $download_from_url);
            if ($image_id) {
                $gallery_ids[] = $image_id;
            } elseif ($download_from_url && filter_var($image_value, FILTER_VALIDATE_URL)) {
                $this->progress['skipped_images'][] = [
                    'product' => $product_name,
                    'url' => $image_value,
                    'reason' => 'download_failed',
                ];
            }
        }

        if (!empty($gallery_ids)) {
            $wpdb->update(
                "{$wpdb->prefix}ggmc_products",
                ['gallery_ids' => wp_json_encode($gallery_ids)],
                ['id' => $product_id]
            );
        }
    }

    /**
     * Resolve image value to media ID
     *
     * @param string $image_value URL or media ID
     * @param bool $download_from_url Whether to download from URL
     * @return int|null Media ID or null
     */
    private function resolve_image($image_value, $download_from_url) {
        // Check if it's already a media ID
        if (is_numeric($image_value)) {
            $attachment = get_post($image_value);
            if ($attachment && $attachment->post_type === 'attachment') {
                return (int)$image_value;
            }
        }

        // It's a URL
        if (filter_var($image_value, FILTER_VALIDATE_URL)) {
            if ($download_from_url) {
                return $this->download_image($image_value);
            }
        }

        return null;
    }

    /**
     * Download image from URL and add to media library
     *
     * @param string $url Image URL
     * @return int|null Media ID or null on failure
     */
    private function download_image($url) {
        require_once(ABSPATH . 'wp-admin/includes/file.php');
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        require_once(ABSPATH . 'wp-admin/includes/media.php');

        // Download file with a 5-second timeout per image to prevent gateway timeouts
        $temp_file = download_url($url, 5);

        if (is_wp_error($temp_file)) {
            return null;
        }

        // Get filename from URL
        $filename = basename(parse_url($url, PHP_URL_PATH));
        if (empty($filename)) {
            $filename = 'imported-image-' . time() . '.jpg';
        }

        // Prepare file array
        $file_array = [
            'name' => $filename,
            'tmp_name' => $temp_file
        ];

        // Upload to media library
        $attachment_id = media_handle_sideload($file_array, 0);

        // Clean up temp file if sideload failed
        if (is_wp_error($attachment_id)) {
            @unlink($temp_file);
            return null;
        }

        return $attachment_id;
    }

    /**
     * Process product attribute
     *
     * @param int $product_id Product ID
     * @param string $attr_name Attribute name
     * @param string $attr_value Attribute value
     * @param bool $create_missing Whether to create missing attributes
     */
    private function process_attribute($product_id, $attr_name, $attr_value, $create_missing = false) {
        global $wpdb;

        // Find attribute by name
        $attribute = $wpdb->get_row($wpdb->prepare(
            "SELECT id FROM {$wpdb->prefix}ggmc_attributes WHERE name = %s",
            $attr_name
        ));

        if (!$attribute && $create_missing) {
            // Create the missing attribute
            $wpdb->insert("{$wpdb->prefix}ggmc_attributes", [
                'name' => sanitize_text_field($attr_name),
                'attribute_type' => 'text', // Default to text type
                'status' => 'active'
            ]);
            $attribute_id = $wpdb->insert_id;
        } elseif ($attribute) {
            $attribute_id = $attribute->id;
        } else {
            return; // Attribute doesn't exist and we're not creating it
        }

        // Check if product already has this attribute
        $existing = $wpdb->get_row($wpdb->prepare(
            "SELECT id FROM {$wpdb->prefix}ggmc_product_attribute_values
             WHERE product_id = %d AND attribute_id = %d",
            $product_id,
            $attribute_id
        ));

        if ($existing) {
            $wpdb->update(
                "{$wpdb->prefix}ggmc_product_attribute_values",
                ['attribute_value' => sanitize_text_field($attr_value)],
                ['id' => $existing->id]
            );
        } else {
            $wpdb->insert("{$wpdb->prefix}ggmc_product_attribute_values", [
                'product_id' => $product_id,
                'attribute_id' => $attribute_id,
                'attribute_value' => sanitize_text_field($attr_value)
            ]);
        }
    }

    /**
     * Process product barcode
     */
    private function process_barcode($product_id, $barcode_value, $barcode_type, $is_primary) {
        global $wpdb;

        // Check if barcode exists for this product
        $existing = $wpdb->get_row($wpdb->prepare(
            "SELECT id FROM {$wpdb->prefix}ggmc_product_barcodes
             WHERE product_id = %d AND barcode_value = %s",
            $product_id,
            $barcode_value
        ));

        if ($existing) {
            $wpdb->update(
                "{$wpdb->prefix}ggmc_product_barcodes",
                [
                    'barcode_type' => sanitize_text_field($barcode_type),
                    'is_primary' => $is_primary ? 1 : 0
                ],
                ['id' => $existing->id]
            );
        } else {
            // If setting as primary, unset other primaries first
            if ($is_primary) {
                $wpdb->update(
                    "{$wpdb->prefix}ggmc_product_barcodes",
                    ['is_primary' => 0],
                    ['product_id' => $product_id]
                );
            }

            $wpdb->insert("{$wpdb->prefix}ggmc_product_barcodes", [
                'product_id' => $product_id,
                'barcode_value' => sanitize_text_field($barcode_value),
                'barcode_type' => sanitize_text_field($barcode_type),
                'is_primary' => $is_primary ? 1 : 0
            ]);
        }
    }

    /**
     * Process product kit
     */
    private function process_kit($product_id, $components_json, $kit_type, $auto_price) {
        global $wpdb;

        $components = json_decode($components_json, true);
        if (!is_array($components) || empty($components)) {
            return;
        }

        // Find or create kit record
        $kit = $wpdb->get_row($wpdb->prepare(
            "SELECT id FROM {$wpdb->prefix}ggmc_product_kits WHERE product_id = %d",
            $product_id
        ));

        if ($kit) {
            $wpdb->update(
                "{$wpdb->prefix}ggmc_product_kits",
                [
                    'kit_type' => sanitize_text_field($kit_type),
                    'auto_calculate_price' => $auto_price
                ],
                ['id' => $kit->id]
            );
            $kit_id = $kit->id;

            // Clear existing components
            $wpdb->delete("{$wpdb->prefix}ggmc_kit_components", ['kit_id' => $kit_id]);
        } else {
            $wpdb->insert("{$wpdb->prefix}ggmc_product_kits", [
                'product_id' => $product_id,
                'kit_type' => sanitize_text_field($kit_type),
                'auto_calculate_price' => $auto_price
            ]);
            $kit_id = $wpdb->insert_id;
        }

        // Add components
        $order = 0;
        foreach ($components as $component) {
            $sku = isset($component['sku']) ? $component['sku'] : '';
            $qty = isset($component['qty']) ? (int)$component['qty'] : 1;

            if (empty($sku)) continue;

            // Find component product by SKU
            $component_product = $wpdb->get_row($wpdb->prepare(
                "SELECT id FROM {$wpdb->prefix}ggmc_products WHERE sku = %s",
                $sku
            ));

            if (!$component_product) continue;

            $wpdb->insert("{$wpdb->prefix}ggmc_kit_components", [
                'kit_id' => $kit_id,
                'component_product_id' => $component_product->id,
                'quantity' => $qty,
                'display_order' => $order++
            ]);
        }
    }

    /**
     * Process product downloads
     */
    private function process_downloads($product_id, $downloads_json) {
        global $wpdb;

        $downloads = json_decode($downloads_json, true);
        if (!is_array($downloads) || empty($downloads)) {
            return;
        }

        // Clear existing downloads
        $wpdb->delete("{$wpdb->prefix}ggmc_product_downloads", ['product_id' => $product_id]);

        $order = 0;
        foreach ($downloads as $download) {
            $name = isset($download['name']) ? $download['name'] : 'Download';
            $url = isset($download['url']) ? $download['url'] : '';
            $limit = isset($download['limit']) ? (int)$download['limit'] : -1;
            $expiry = isset($download['expiry_days']) ? (int)$download['expiry_days'] : -1;

            if (empty($url)) continue;

            $wpdb->insert("{$wpdb->prefix}ggmc_product_downloads", [
                'product_id' => $product_id,
                'name' => sanitize_text_field($name),
                'file_url' => esc_url_raw($url),
                'download_limit' => $limit,
                'access_expiry_days' => $expiry,
                'display_order' => $order++,
                'status' => 'active'
            ]);
        }
    }

    /**
     * Process product variations
     */
    private function process_variations($product_id, $variations_json) {
        global $wpdb;

        $variations = json_decode($variations_json, true);
        if (!is_array($variations) || empty($variations)) {
            return;
        }

        // Mark product as having variations
        $wpdb->update(
            "{$wpdb->prefix}ggmc_products",
            ['has_variations' => 1],
            ['id' => $product_id]
        );

        foreach ($variations as $variation_data) {
            $sku = isset($variation_data['sku']) ? $variation_data['sku'] : '';
            $attributes = isset($variation_data['attributes']) ? $variation_data['attributes'] : [];

            // Check if variation exists by SKU
            $existing = null;
            if (!empty($sku)) {
                $existing = $wpdb->get_row($wpdb->prepare(
                    "SELECT id FROM {$wpdb->prefix}ggmc_product_variations
                     WHERE product_id = %d AND sku = %s",
                    $product_id,
                    $sku
                ));
            }

            $variation_insert = [
                'product_id' => $product_id,
                'sku' => sanitize_text_field($sku),
                'price' => isset($variation_data['price']) ? floatval($variation_data['price']) : null,
                'sale_price' => isset($variation_data['sale_price']) && $variation_data['sale_price'] !== ''
                    ? floatval($variation_data['sale_price']) : null,
                'stock' => isset($variation_data['stock']) ? intval($variation_data['stock']) : null,
                'stock_status' => isset($variation_data['stock_status'])
                    ? sanitize_text_field($variation_data['stock_status']) : 'instock',
                'is_default' => isset($variation_data['is_default']) ? intval($variation_data['is_default']) : 0,
                'status' => 'active'
            ];

            // Handle variation image
            if (isset($variation_data['image']) && !empty($variation_data['image'])) {
                $variation_insert['image_id'] = $this->resolve_image($variation_data['image'], true);
            }

            if ($existing) {
                $wpdb->update(
                    "{$wpdb->prefix}ggmc_product_variations",
                    $variation_insert,
                    ['id' => $existing->id]
                );
                $variation_id = $existing->id;

                // Clear existing type values
                $wpdb->delete("{$wpdb->prefix}ggmc_variation_type_values", ['variation_id' => $variation_id]);
            } else {
                $wpdb->insert("{$wpdb->prefix}ggmc_product_variations", $variation_insert);
                $variation_id = $wpdb->insert_id;
            }

            // Add type values
            foreach ($attributes as $attr_name => $attr_value) {
                // Find variation type
                $var_type = $wpdb->get_row($wpdb->prepare(
                    "SELECT id FROM {$wpdb->prefix}ggmc_variation_types WHERE name = %s",
                    $attr_name
                ));

                if ($var_type) {
                    $wpdb->insert("{$wpdb->prefix}ggmc_variation_type_values", [
                        'variation_id'      => $variation_id,
                        'variation_type_id' => $var_type->id,
                        'option_value'      => sanitize_text_field($attr_value)
                    ]);
                }
            }
        }
    }

    /**
     * Save import progress to transient
     */
    private function save_progress() {
        set_transient($this->session_key, $this->progress, HOUR_IN_SECONDS);
    }

    /**
     * Get current import progress
     *
     * @return array Progress data
     */
    public function get_progress() {
        $progress = get_transient($this->session_key);
        return $progress ? $progress : $this->progress;
    }

    /**
     * Clear import session
     */
    public function clear_session() {
        delete_transient($this->session_key);
    }

    /**
     * Save import report for later review
     */
    private function save_import_report() {
        $report = [
            'date' => current_time('mysql'),
            'total' => $this->progress['total'],
            'created' => $this->progress['created'],
            'updated' => $this->progress['updated'],
            'skipped' => $this->progress['skipped'],
            'errors' => $this->progress['errors'],
            'skipped_images' => $this->progress['skipped_images'],
        ];

        $reports = get_option('ggmc_import_reports', []);
        $reports[] = $report;

        // Keep only the last 20 reports
        if (count($reports) > 20) {
            $reports = array_slice($reports, -20);
        }

        update_option('ggmc_import_reports', $reports);
    }

    /**
     * Get saved import reports
     *
     * @return array
     */
    public static function get_import_reports() {
        return get_option('ggmc_import_reports', []);
    }

    /**
     * Delete a specific import report
     *
     * @param int $index Report index
     */
    public static function delete_import_report($index) {
        $reports = get_option('ggmc_import_reports', []);
        if (isset($reports[$index])) {
            array_splice($reports, $index, 1);
            update_option('ggmc_import_reports', $reports);
        }
    }

    /**
     * Delete all import reports
     */
    public static function delete_all_import_reports() {
        delete_option('ggmc_import_reports');
    }

    /**
     * Get upload directory for imports
     *
     * @return string Upload directory path
     */
    public function get_upload_directory() {
        $upload_dir = wp_upload_dir();
        $import_dir = $upload_dir['basedir'] . '/ggm-commerce-imports/';

        if (!file_exists($import_dir)) {
            wp_mkdir_p($import_dir);
            file_put_contents($import_dir . 'index.php', '<?php // Silence is golden');
            file_put_contents($import_dir . '.htaccess', "deny from all\n");
        }

        return $import_dir;
    }
}
