<?php
/**
 * Incremental Import Service - Smart Update Detection
 *
 * @package PrimeLink
 */

namespace PrimeLink\Modules\Imports\Service;

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

/**
 * Handles incremental import logic: hash tracking, change detection, smart updates.
 */
final class IncrementalImportService {

    /**
     * Meta key for storing product hash.
     */
    const HASH_META_KEY = '_mt_primelink_import_hash';

    /**
     * Meta key for storing last import ID.
     */
    const LAST_IMPORT_META_KEY = '_mt_primelink_last_import_id';

    /**
     * Meta key for storing last import timestamp.
     */
    const LAST_IMPORT_TIME_META_KEY = '_mt_primelink_last_import_time';

    /**
     * Generate hash for product data to detect changes.
     *
     * @param array $mapped Mapped product data.
     * @param array $fields Fields to include in hash (empty = all).
     * @return string MD5 hash.
     */
    public static function generate_hash( $mapped, $fields = array() ) {
        // Build data array for hashing
        $hash_data = array();

        if ( empty( $fields ) ) {
            // Include all relevant fields
            $hash_data = array(
                'title'       => $mapped['post']['post_title'] ?? '',
                'content'     => $mapped['post']['post_content'] ?? '',
                'excerpt'     => $mapped['post']['post_excerpt'] ?? '',
                'sku'         => $mapped['product']['sku'] ?? '',
                'price'       => $mapped['product']['regular_price'] ?? '',
                'sale_price'  => $mapped['product']['sale_price'] ?? '',
                'stock'       => $mapped['product']['stock'] ?? '',
                'stock_status' => $mapped['product']['stock_status'] ?? '',
                'weight'      => $mapped['product']['weight'] ?? '',
                'length'      => $mapped['product']['length'] ?? '',
                'width'       => $mapped['product']['width'] ?? '',
                'height'      => $mapped['product']['height'] ?? '',
                'images'      => self::normalize_images( $mapped['images'] ?? array() ),
                'categories'  => self::normalize_array( $mapped['tax']['product_cat'] ?? array() ),
                'tags'        => self::normalize_array( $mapped['tax']['product_tag'] ?? array() ),
            );
        } else {
            // Include only specified fields
            foreach ( $fields as $field ) {
                switch ( $field ) {
                    case 'title':
                        $hash_data['title'] = $mapped['post']['post_title'] ?? '';
                        break;
                    case 'content':
                        $hash_data['content'] = $mapped['post']['post_content'] ?? '';
                        $hash_data['excerpt'] = $mapped['post']['post_excerpt'] ?? '';
                        break;
                    case 'product_data':
                        $hash_data['sku']         = $mapped['product']['sku'] ?? '';
                        $hash_data['price']       = $mapped['product']['regular_price'] ?? '';
                        $hash_data['sale_price'] = $mapped['product']['sale_price'] ?? '';
                        $hash_data['stock']       = $mapped['product']['stock'] ?? '';
                        $hash_data['stock_status'] = $mapped['product']['stock_status'] ?? '';
                        $hash_data['weight']      = $mapped['product']['weight'] ?? '';
                        $hash_data['length']      = $mapped['product']['length'] ?? '';
                        $hash_data['width']       = $mapped['product']['width'] ?? '';
                        $hash_data['height']      = $mapped['product']['height'] ?? '';
                        break;
                    case 'images':
                        $hash_data['images'] = self::normalize_images( $mapped['images'] ?? array() );
                        break;
                    case 'taxonomies':
                        $hash_data['categories'] = self::normalize_array( $mapped['tax']['product_cat'] ?? array() );
                        $hash_data['tags']       = self::normalize_array( $mapped['tax']['product_tag'] ?? array() );
                        break;
                }
            }
        }

        // Normalize and hash
        $hash_string = wp_json_encode( $hash_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES );
        return md5( $hash_string );
    }

    /**
     * Get stored hash for a product.
     *
     * @param int $product_id Product ID.
     * @return string|false Hash or false if not found.
     */
    public static function get_stored_hash( $product_id ) {
        return get_post_meta( $product_id, self::HASH_META_KEY, true );
    }

    /**
     * Store hash for a product.
     *
     * @param int    $product_id Product ID.
     * @param string $hash Hash value.
     * @param int    $import_id Import ID.
     * @return bool Success.
     */
    public static function store_hash( $product_id, $hash, $import_id = 0 ) {
        $updated = update_post_meta( $product_id, self::HASH_META_KEY, $hash );
        if ( $import_id > 0 ) {
            update_post_meta( $product_id, self::LAST_IMPORT_META_KEY, absint( $import_id ) );
            update_post_meta( $product_id, self::LAST_IMPORT_TIME_META_KEY, current_time( 'mysql' ) );
        }
        return $updated !== false;
    }

    /**
     * Check if product data has changed.
     *
     * @param int    $product_id Product ID.
     * @param array  $mapped Mapped product data.
     * @param array  $fields Fields to compare (empty = all).
     * @return bool True if changed, false if unchanged.
     */
    public static function has_changed( $product_id, $mapped, $fields = array() ) {
        $stored_hash = self::get_stored_hash( $product_id );
        if ( empty( $stored_hash ) ) {
            // No hash stored = new or never tracked = consider changed
            return true;
        }

        $current_hash = self::generate_hash( $mapped, $fields );
        return $stored_hash !== $current_hash;
    }

    /**
     * Check if product should be updated based on incremental settings.
     *
     * @param int    $product_id Product ID.
     * @param array  $mapped Mapped product data.
     * @param array  $settings Incremental import settings.
     * @return array Result with 'should_update' and 'reason'.
     */
    public static function should_update( $product_id, $mapped, $settings ) {
        $enabled = ! empty( $settings['enabled'] );
        if ( ! $enabled ) {
            return array(
                'should_update' => true,
                'reason'        => 'incremental_disabled',
            );
        }

        $mode = $settings['mode'] ?? 'all';
        $fields = ! empty( $settings['fields'] ) ? (array) $settings['fields'] : array();

        // Check if changed
        $changed = self::has_changed( $product_id, $mapped, $fields );

        if ( ! $changed ) {
            return array(
                'should_update' => false,
                'reason'        => 'no_changes',
            );
        }

        // If mode is 'price_stock_only', check if only price/stock changed
        if ( $mode === 'price_stock_only' ) {
            $price_stock_fields = array( 'product_data' );
            $price_stock_changed = self::has_changed( $product_id, $mapped, $price_stock_fields );
            if ( ! $price_stock_changed ) {
                return array(
                    'should_update' => false,
                    'reason'        => 'only_non_price_stock_changed',
                );
            }
        }

        return array(
            'should_update' => true,
            'reason'        => 'changed',
        );
    }

    /**
     * Normalize images array for consistent hashing.
     *
     * @param array $images Images array.
     * @return array Normalized array.
     */
    private static function normalize_images( $images ) {
        if ( ! is_array( $images ) ) {
            return array();
        }
        // Sort and normalize URLs
        $normalized = array();
        foreach ( $images as $img ) {
            if ( is_string( $img ) ) {
                $normalized[] = trim( $img );
            } elseif ( is_array( $img ) && isset( $img['url'] ) ) {
                $normalized[] = trim( $img['url'] );
            }
        }
        sort( $normalized );
        return $normalized;
    }

    /**
     * Normalize array for consistent hashing.
     *
     * @param array|string $data Data to normalize.
     * @return array Normalized array.
     */
    private static function normalize_array( $data ) {
        if ( is_string( $data ) ) {
            // Comma-separated string
            $data = array_map( 'trim', explode( ',', $data ) );
        }
        if ( ! is_array( $data ) ) {
            return array();
        }
        $normalized = array_map( 'trim', $data );
        sort( $normalized );
        return array_filter( $normalized );
    }

    /**
     * Get statistics about incremental import.
     *
     * @param int $import_id Import ID.
     * @return array Statistics.
     */
    public static function get_statistics( $import_id ) {
        global $wpdb;

        $stats = array(
            'total_tracked'    => 0,
            'unchanged'        => 0,
            'changed'          => 0,
            'new_items'        => 0,
        );

        // Count products with hash from this import
        $meta_query = $wpdb->prepare(
            "SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} 
            WHERE meta_key = %s AND meta_value = %d",
            self::LAST_IMPORT_META_KEY,
            $import_id
        );
        $stats['total_tracked'] = (int) $wpdb->get_var( $meta_query );

        return $stats;
    }
}



