<?php
/**
 * GGM Commerce Image Re-association Tool
 *
 * Helps match uploaded images to products after importing
 * Works with manifest.json from image package export
 *
 * @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_Image_Reassociation {

    /**
     * Constructor
     */
    public function __construct() {
        // AJAX handlers
        add_action('wp_ajax_ggmc_scan_media_for_products', [$this, 'ajax_scan_media']);
        add_action('wp_ajax_ggmc_reassociate_images', [$this, 'ajax_reassociate_images']);
        add_action('wp_ajax_ggmc_upload_image_manifest', [$this, 'ajax_upload_manifest']);
    }

    /**
     * Scan media library for images that match product SKUs
     *
     * @param array $options Scan options
     * @return array Scan results with matches
     */
    public function scan_media_for_products($options = []) {
        global $wpdb;

        $results = [
            'total_media' => 0,
            'total_products' => 0,
            'matches' => [],
            'unmatched_images' => [],
            'products_without_images' => [],
        ];

        // Get all products
        $products = $wpdb->get_results(
            "SELECT id, sku, name, image, gallery_images
             FROM {$wpdb->prefix}ggmc_products
             WHERE status != 'deleted'",
            ARRAY_A
        );

        $results['total_products'] = count($products);

        // Build SKU lookup
        $sku_to_product = [];
        $products_needing_images = [];

        foreach ($products as $product) {
            $sku_to_product[$product['sku']] = $product;

            // Check if product needs images
            if (empty($product['image'])) {
                $products_needing_images[$product['sku']] = $product;
            }
        }

        // Get media library images
        $attachments = get_posts([
            'post_type' => 'attachment',
            'post_mime_type' => 'image',
            'posts_per_page' => -1,
            'post_status' => 'inherit',
        ]);

        $results['total_media'] = count($attachments);

        // Build patterns to match
        $patterns = [];
        foreach ($products as $product) {
            $sku = $product['sku'];
            $patterns[$sku] = [
                'product_id' => $product['id'],
                'sku' => $sku,
                'name' => $product['name'],
                'current_image' => $product['image'],
                'patterns' => [
                    // Exact SKU match
                    strtolower($sku),
                    // SKU with common prefixes/suffixes
                    strtolower($sku) . '_',
                    strtolower($sku) . '-',
                    '_' . strtolower($sku),
                    '-' . strtolower($sku),
                    // SKU at start or end of filename
                    '^' . preg_quote(strtolower($sku), '/'),
                    preg_quote(strtolower($sku), '/') . '$',
                ],
            ];
        }

        // Scan each attachment
        foreach ($attachments as $attachment) {
            $filename = basename(get_attached_file($attachment->ID));
            $filename_lower = strtolower(pathinfo($filename, PATHINFO_FILENAME));

            $matched = false;

            foreach ($patterns as $sku => $pattern_data) {
                // Check each pattern
                foreach ($pattern_data['patterns'] as $pattern) {
                    if (strpos($pattern, '^') === 0 || strpos($pattern, '$') !== false) {
                        // Regex pattern
                        if (preg_match('/' . $pattern . '/i', $filename_lower)) {
                            $results['matches'][] = [
                                'attachment_id' => $attachment->ID,
                                'filename' => $filename,
                                'url' => wp_get_attachment_url($attachment->ID),
                                'product_id' => $pattern_data['product_id'],
                                'product_sku' => $sku,
                                'product_name' => $pattern_data['name'],
                                'has_image' => !empty($pattern_data['current_image']),
                                'match_type' => 'sku_pattern',
                            ];
                            $matched = true;
                            break 2;
                        }
                    } else {
                        // Simple substring match
                        if (strpos($filename_lower, $pattern) !== false) {
                            $results['matches'][] = [
                                'attachment_id' => $attachment->ID,
                                'filename' => $filename,
                                'url' => wp_get_attachment_url($attachment->ID),
                                'product_id' => $pattern_data['product_id'],
                                'product_sku' => $sku,
                                'product_name' => $pattern_data['name'],
                                'has_image' => !empty($pattern_data['current_image']),
                                'match_type' => 'sku_substring',
                            ];
                            $matched = true;
                            break 2;
                        }
                    }
                }
            }

            if (!$matched) {
                $results['unmatched_images'][] = [
                    'attachment_id' => $attachment->ID,
                    'filename' => $filename,
                    'url' => wp_get_attachment_url($attachment->ID),
                ];
            }
        }

        // Get products without images
        foreach ($products_needing_images as $sku => $product) {
            // Check if we found a match for this product
            $found_match = false;
            foreach ($results['matches'] as $match) {
                if ($match['product_sku'] === $sku) {
                    $found_match = true;
                    break;
                }
            }

            if (!$found_match) {
                $results['products_without_images'][] = [
                    'product_id' => $product['id'],
                    'sku' => $sku,
                    'name' => $product['name'],
                ];
            }
        }

        return $results;
    }

    /**
     * Match images using manifest from export
     *
     * @param array $manifest Manifest data from export
     * @return array Match results
     */
    public function match_from_manifest($manifest) {
        global $wpdb;

        $results = [
            'matches' => [],
            'missing_products' => [],
            'missing_images' => [],
        ];

        if (empty($manifest['images'])) {
            return $results;
        }

        foreach ($manifest['images'] as $image_info) {
            $sku = $image_info['product_sku'];
            $filename = $image_info['filename'];
            $is_primary = !empty($image_info['is_primary']);

            // Find product by SKU
            $product = $wpdb->get_row($wpdb->prepare(
                "SELECT id, name FROM {$wpdb->prefix}ggmc_products WHERE sku = %s AND status != 'deleted'",
                $sku
            ), ARRAY_A);

            if (!$product) {
                $results['missing_products'][] = [
                    'sku' => $sku,
                    'filename' => $filename,
                ];
                continue;
            }

            // Find image in media library
            $attachment = $this->find_attachment_by_filename($filename);

            if (!$attachment) {
                $results['missing_images'][] = [
                    'filename' => $filename,
                    'product_sku' => $sku,
                    'product_name' => $product['name'],
                ];
                continue;
            }

            $results['matches'][] = [
                'attachment_id' => $attachment->ID,
                'filename' => $filename,
                'url' => wp_get_attachment_url($attachment->ID),
                'product_id' => $product['id'],
                'product_sku' => $sku,
                'product_name' => $product['name'],
                'is_primary' => $is_primary,
            ];
        }

        return $results;
    }

    /**
     * Find attachment by filename
     *
     * @param string $filename Filename to search for
     * @return WP_Post|null Attachment post or null
     */
    private function find_attachment_by_filename($filename) {
        global $wpdb;

        // First try exact match
        $attachment_id = $wpdb->get_var($wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts}
             WHERE post_type = 'attachment'
             AND guid LIKE %s",
            '%' . $wpdb->esc_like($filename)
        ));

        if ($attachment_id) {
            return get_post($attachment_id);
        }

        // Try matching without extension
        $name_without_ext = pathinfo($filename, PATHINFO_FILENAME);
        $attachment_id = $wpdb->get_var($wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts}
             WHERE post_type = 'attachment'
             AND (post_title = %s OR post_name = %s)",
            $name_without_ext,
            sanitize_title($name_without_ext)
        ));

        if ($attachment_id) {
            return get_post($attachment_id);
        }

        // Search by _wp_attached_file meta
        $attachment_id = $wpdb->get_var($wpdb->prepare(
            "SELECT post_id FROM {$wpdb->postmeta}
             WHERE meta_key = '_wp_attached_file'
             AND meta_value LIKE %s",
            '%' . $wpdb->esc_like($filename)
        ));

        if ($attachment_id) {
            return get_post($attachment_id);
        }

        return null;
    }

    /**
     * Apply image associations to products
     *
     * @param array $associations Array of associations to apply
     * @return array Results of the operation
     */
    public function apply_associations($associations) {
        global $wpdb;

        $results = [
            'success' => true,
            'updated' => 0,
            'skipped' => 0,
            'errors' => [],
        ];

        // Group by product
        $products_updates = [];
        foreach ($associations as $assoc) {
            $product_id = $assoc['product_id'];
            $attachment_id = $assoc['attachment_id'];
            $is_primary = !empty($assoc['is_primary']);

            if (!isset($products_updates[$product_id])) {
                $products_updates[$product_id] = [
                    'primary' => null,
                    'gallery' => [],
                ];
            }

            if ($is_primary) {
                $products_updates[$product_id]['primary'] = $attachment_id;
            } else {
                $products_updates[$product_id]['gallery'][] = $attachment_id;
            }
        }

        // Apply updates
        foreach ($products_updates as $product_id => $images) {
            $update_data = [];

            if ($images['primary']) {
                $update_data['image'] = $images['primary'];
            }

            if (!empty($images['gallery'])) {
                // Get existing gallery
                $existing = $wpdb->get_var($wpdb->prepare(
                    "SELECT gallery_images FROM {$wpdb->prefix}ggmc_products WHERE id = %d",
                    $product_id
                ));

                $gallery = $existing ? explode(',', $existing) : [];
                $gallery = array_merge($gallery, $images['gallery']);
                $gallery = array_unique($gallery);

                $update_data['gallery_images'] = implode(',', $gallery);
            }

            if (!empty($update_data)) {
                $update_data['updated_at'] = current_time('mysql');

                $updated = $wpdb->update(
                    $wpdb->prefix . 'ggmc_products',
                    $update_data,
                    ['id' => $product_id]
                );

                if ($updated !== false) {
                    $results['updated']++;
                } else {
                    $results['errors'][] = [
                        'product_id' => $product_id,
                        'message' => 'Database update failed',
                    ];
                }
            } else {
                $results['skipped']++;
            }
        }

        return $results;
    }

    /**
     * AJAX handler: Scan media library for product matches
     */
    public function ajax_scan_media() {
        // Verify nonce
        if (!check_ajax_referer('ggmc_import_export', 'nonce', false)) {
            wp_send_json_error(['message' => __('Security check failed', 'ggm-commerce')]);
            return;
        }

        // Check capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => __('Permission denied', 'ggm-commerce')]);
            return;
        }

        $results = $this->scan_media_for_products();

        wp_send_json_success($results);
    }

    /**
     * AJAX handler: Upload and process manifest file
     */
    public function ajax_upload_manifest() {
        // Verify nonce
        if (!check_ajax_referer('ggmc_import_export', 'nonce', false)) {
            wp_send_json_error(['message' => __('Security check failed', 'ggm-commerce')]);
            return;
        }

        // Check capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => __('Permission denied', 'ggm-commerce')]);
            return;
        }

        // Check for uploaded file
        if (empty($_FILES['manifest'])) {
            wp_send_json_error(['message' => __('No file uploaded', 'ggm-commerce')]);
            return;
        }

        $file = $_FILES['manifest'];

        // Validate file type
        if ($file['type'] !== 'application/json' && pathinfo($file['name'], PATHINFO_EXTENSION) !== 'json') {
            wp_send_json_error(['message' => __('Invalid file type. Please upload a JSON manifest file.', 'ggm-commerce')]);
            return;
        }

        // Read manifest
        $content = file_get_contents($file['tmp_name']);
        $manifest = json_decode($content, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            wp_send_json_error(['message' => __('Invalid JSON file', 'ggm-commerce')]);
            return;
        }

        // Process manifest
        $results = $this->match_from_manifest($manifest);

        wp_send_json_success([
            'manifest' => $manifest,
            'matches' => $results,
        ]);
    }

    /**
     * AJAX handler: Apply image re-associations
     */
    public function ajax_reassociate_images() {
        // Verify nonce
        if (!check_ajax_referer('ggmc_import_export', 'nonce', false)) {
            wp_send_json_error(['message' => __('Security check failed', 'ggm-commerce')]);
            return;
        }

        // Check capabilities
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => __('Permission denied', 'ggm-commerce')]);
            return;
        }

        // Get associations from request
        $associations = isset($_POST['associations']) ? $_POST['associations'] : [];

        if (empty($associations)) {
            wp_send_json_error(['message' => __('No associations provided', 'ggm-commerce')]);
            return;
        }

        // Sanitize associations
        $clean_associations = [];
        foreach ($associations as $assoc) {
            $clean_associations[] = [
                'product_id' => intval($assoc['product_id']),
                'attachment_id' => intval($assoc['attachment_id']),
                'is_primary' => !empty($assoc['is_primary']),
            ];
        }

        // Apply associations
        $results = $this->apply_associations($clean_associations);

        if ($results['success']) {
            wp_send_json_success([
                'message' => sprintf(
                    /* translators: %d: number of products updated */
                    __('Successfully updated %d products', 'ggm-commerce'),
                    $results['updated']
                ),
                'results' => $results,
            ]);
        } else {
            wp_send_json_error([
                'message' => __('Some updates failed', 'ggm-commerce'),
                'results' => $results,
            ]);
        }
    }
}

// Initialize
new GGM_Commerce_Image_Reassociation();
