<?php
/**
 * Dry Run Service - Simulates imports without saving data.
 *
 * @package PrimeLink
 */

namespace PrimeLink\Modules\Imports\Service;

use PrimeLink\Modules\Imports\Parsers\ParserFactory;
use PrimeLink\Helpers\ValidatorHelper;

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

final class DryRunService {

    /**
     * Run a dry run import (test mode).
     *
     * @param int   $import_id Import ID.
     * @param array $options   Test options.
     * @return array Results with validation report.
     */
    public static function run( $import_id, $options = array() ) {
        $import_id = absint( $import_id );
        $options   = wp_parse_args( $options, array(
            'limit'              => 10,
            'validate_required'  => true,
            'validate_format'    => true,
            'check_duplicates'   => true,
            'skip_unchanged'     => false,
        ) );

        $draft = ImportRunner::get_draft( $import_id );
        if ( empty( $draft ) ) {
            return array(
                'success' => false,
                'error'   => 'Import draft not found.',
            );
        }

        $import_type = $draft['type'] ?? ( $draft['step_data'][1]['type'] ?? 'product' );
        if ( $import_type === 'customers' ) {
            $import_type = 'customer';
        } elseif ( $import_type === 'coupons' ) {
            $import_type = 'coupon';
        }

        $file = ImportRunner::extract_file_from_draft( $draft );
        if ( empty( $file ) || empty( $file['path'] ) ) {
            return array(
                'success' => false,
                'error'   => 'Import file not found.',
            );
        }

        $parser = ParserFactory::make( $file['type'] );
        $filters = $draft['step_data'][4]['filters'] ?? array();
        $filters = apply_filters( 'primelink_import_filters', $filters, $import_id, $file );

        $parser_args = array(
            'xpath'    => $draft['step_data'][4]['xpath'] ?? '',
            'max_rows' => $options['limit'],
            'filters'  => $filters,
        );
        $parser_args = apply_filters( 'primelink_import_parser_args', $parser_args, $import_id, $file );

        try {
            $parsed = $parser->preview( $file['path'], $parser_args );
            $parsed = apply_filters( 'primelink_import_parser_result', $parsed, $import_id, $file, $parser_args );
            $headers = $parsed['headers'] ?? array();
            $rows    = $parsed['rows'] ?? array();
            
            // Apply filters to rows
            $filters_normalized = ImportRunner::normalize_filters( $filters );
            $rows = ImportRunner::apply_filters_to_rows( $headers, $rows, $filters_normalized );
            
            // Limit rows
            if ( $options['limit'] > 0 && count( $rows ) > $options['limit'] ) {
                $rows = array_slice( $rows, 0, $options['limit'] );
            }
        } catch ( \Throwable $e ) {
            return array(
                'success' => false,
                'error'   => 'Failed to parse file: ' . $e->getMessage(),
            );
        }

        $mapping     = $draft['step_data'][5]['mapping'] ?? array();
        $custom_fields = $draft['step_data'][5]['custom_fields'] ?? array();
        $match_by    = $draft['step_data'][6]['match_by'] ?? 'sku';
        $mode        = $draft['step_data'][6]['mode'] ?? 'create_update';

        $results = array(
            'total'         => count( $rows ),
            'processed'     => 0,
            'would_create'  => 0,
            'would_update' => 0,
            'would_skip'    => 0,
            'errors'        => 0,
            'warnings'      => 0,
            'validation'    => array(
                'errors'   => array(),
                'warnings' => array(),
            ),
            'sample_items'  => array(),
        );

        foreach ( $rows as $index => $row ) {
            $item = ImportRunner::row_to_item( $headers, $row );

            // Apply filters
            if ( ! ImportRunner::row_matches_filters( $item, $filters ) ) {
                $results['would_skip']++;
                continue;
            }

            // Apply mapping
            try {
                $mapped = ImportRunner::apply_mapping_to_item( $item, $mapping, $custom_fields, $import_type );
            } catch ( \Throwable $e ) {
                $results['errors']++;
                $results['validation']['errors'][] = array(
                    'row'    => $index + 1,
                    'field'  => 'mapping',
                    'message' => 'Mapping error: ' . $e->getMessage(),
                );
                continue;
            }

            // Validation
            $validation = self::validate_item( $mapped, $import_type, $options );
            if ( ! empty( $validation['errors'] ) ) {
                $results['errors']++;
                foreach ( $validation['errors'] as $error ) {
                    $results['validation']['errors'][] = array(
                        'row'    => $index + 1,
                        'field'  => $error['field'] ?? 'unknown',
                        'message' => $error['message'] ?? 'Validation error',
                    );
                }
            }
            if ( ! empty( $validation['warnings'] ) ) {
                $results['warnings']++;
                foreach ( $validation['warnings'] as $warning ) {
                    $results['validation']['warnings'][] = array(
                        'row'    => $index + 1,
                        'field'  => $warning['field'] ?? 'unknown',
                        'message' => $warning['message'] ?? 'Validation warning',
                    );
                }
            }

            // Check if would create or update
            $existing_id = 0;
            if ( $options['check_duplicates'] ) {
                $existing_id = self::find_existing_item( $mapped, $import_type, $match_by );
            }

            if ( ! $existing_id && $mode !== 'update_only' ) {
                $results['would_create']++;
            } elseif ( $existing_id && $mode !== 'new_only' ) {
                // Check incremental import
                if ( $options['skip_unchanged'] ) {
                    $should_update = self::check_incremental_update( $existing_id, $mapped, $import_type, $draft );
                    if ( ! $should_update ) {
                        $results['would_skip']++;
                        continue;
                    }
                }
                $results['would_update']++;
            } else {
                $results['would_skip']++;
            }

            // Store sample items (first 5)
            if ( count( $results['sample_items'] ) < 5 ) {
                $results['sample_items'][] = array(
                    'row'     => $index + 1,
                    'mapped'  => $mapped,
                    'action'  => $existing_id ? 'update' : 'create',
                    'item_id' => $existing_id,
                );
            }

            $results['processed']++;
        }

        $results['success'] = true;
        return $results;
    }

    /**
     * Validate an item.
     *
     * @param array  $mapped      Mapped item data.
     * @param string $import_type Import type.
     * @param array  $options     Validation options.
     * @return array Validation results.
     */
    private static function validate_item( $mapped, $import_type, $options ) {
        $errors   = array();
        $warnings = array();

        if ( $import_type === 'product' ) {
            $product_data = $mapped['product'] ?? array();

            // Required fields
            if ( $options['validate_required'] ) {
                if ( empty( $mapped['post']['post_title'] ) ) {
                    $errors[] = array(
                        'field'   => 'post_title',
                        'message' => 'Product title is required.',
                    );
                }
            }

            // Format validation
            if ( $options['validate_format'] ) {
                // Price validation
                if ( ! empty( $product_data['regular_price'] ) ) {
                    $validation = ValidatorHelper::validate( $product_data['regular_price'], array(
                        'Numeric' => array( 'type' => 'float' ),
                        'PositiveOrZero' => true,
                    ) );
                    if ( ! $validation['valid'] ) {
                        foreach ( $validation['errors'] as $error ) {
                            $errors[] = array(
                                'field'   => 'regular_price',
                                'message' => 'Regular price: ' . $error,
                            );
                        }
                    }
                }

                if ( ! empty( $product_data['sale_price'] ) ) {
                    $validation = ValidatorHelper::validate( $product_data['sale_price'], array(
                        'Numeric' => array( 'type' => 'float' ),
                        'PositiveOrZero' => true,
                    ) );
                    if ( ! $validation['valid'] ) {
                        foreach ( $validation['errors'] as $error ) {
                            $errors[] = array(
                                'field'   => 'sale_price',
                                'message' => 'Sale price: ' . $error,
                            );
                        }
                    }
                }

                // Stock validation
                if ( isset( $product_data['stock'] ) && $product_data['stock'] !== '' ) {
                    $validation = ValidatorHelper::validate( $product_data['stock'], array(
                        'Numeric' => array( 'type' => 'int' ),
                        'PositiveOrZero' => true,
                    ) );
                    if ( ! $validation['valid'] ) {
                        foreach ( $validation['errors'] as $error ) {
                            $errors[] = array(
                                'field'   => 'stock',
                                'message' => 'Stock quantity: ' . $error,
                            );
                        }
                    }
                }

                // SKU uniqueness warning
                if ( ! empty( $product_data['sku'] ) ) {
                    $existing = wc_get_product_id_by_sku( $product_data['sku'] );
                    if ( $existing ) {
                        $warnings[] = array(
                            'field'   => 'sku',
                            'message' => 'SKU already exists (product #' . $existing . '). Will update existing product.',
                        );
                    }
                }
            }
        } elseif ( $import_type === 'order' ) {
            $order_data = $mapped['order'] ?? array();

            if ( $options['validate_required'] ) {
                if ( empty( $order_data['billing_email'] ) && empty( $order_data['customer_id'] ) ) {
                    $errors[] = array(
                        'field'   => 'billing_email',
                        'message' => 'Order must have either billing email or customer ID.',
                    );
                }
            }

            if ( $options['validate_format'] ) {
                if ( ! empty( $order_data['billing_email'] ) ) {
                    if ( ! ValidatorHelper::is_email( $order_data['billing_email'] ) ) {
                        $errors[] = array(
                            'field'   => 'billing_email',
                            'message' => 'Invalid email format.',
                        );
                    }
                }

                if ( ! empty( $order_data['total'] ) ) {
                    $validation = ValidatorHelper::validate( $order_data['total'], array(
                        'Numeric' => array( 'type' => 'float' ),
                        'PositiveOrZero' => true,
                    ) );
                    if ( ! $validation['valid'] ) {
                        foreach ( $validation['errors'] as $error ) {
                            $errors[] = array(
                                'field'   => 'total',
                                'message' => 'Order total: ' . $error,
                            );
                        }
                    }
                }
            }
        } elseif ( $import_type === 'customer' ) {
            $customer_data = $mapped['customer'] ?? array();

            if ( $options['validate_required'] ) {
                if ( empty( $customer_data['email'] ) && empty( $customer_data['customer_id'] ) && empty( $customer_data['username'] ) ) {
                    $errors[] = array(
                        'field'   => 'email',
                        'message' => 'Customer must have email, customer ID, or username.',
                    );
                }
            }

            if ( $options['validate_format'] ) {
                if ( ! empty( $customer_data['email'] ) ) {
                    if ( ! ValidatorHelper::is_email( $customer_data['email'] ) ) {
                        $errors[] = array(
                            'field'   => 'email',
                            'message' => 'Invalid email format.',
                        );
                    }
                }
            }
        }

        return array(
            'errors'   => $errors,
            'warnings' => $warnings,
        );
    }

    /**
     * Find existing item (simulation).
     *
     * @param array  $mapped      Mapped data.
     * @param string $import_type Import type.
     * @param string $match_by    Match by field.
     * @return int Existing item ID or 0.
     */
    private static function find_existing_item( $mapped, $import_type, $match_by ) {
        if ( $import_type === 'product' ) {
            $product_data = $mapped['product'] ?? array();

            if ( $match_by === 'sku' && ! empty( $product_data['sku'] ) ) {
                return wc_get_product_id_by_sku( $product_data['sku'] );
            }

            if ( $match_by === 'title' && ! empty( $mapped['post']['post_title'] ) ) {
                $posts = get_posts( array(
                    'post_type'   => 'product',
                    'title'       => $mapped['post']['post_title'],
                    'numberposts' => 1,
                    'fields'      => 'ids',
                ) );
                return ! empty( $posts ) ? $posts[0] : 0;
            }
        } elseif ( $import_type === 'order' ) {
            $order_data = $mapped['order'] ?? array();
            if ( ! empty( $order_data['order_number'] ) ) {
                $orders = wc_get_orders( array(
                    'limit'        => 1,
                    'return'       => 'ids',
                    'meta_key'     => '_order_number',
                    'meta_value'   => $order_data['order_number'],
                ) );
                return ! empty( $orders ) ? $orders[0] : 0;
            }
        } elseif ( $import_type === 'customer' ) {
            $customer_data = $mapped['customer'] ?? array();
            if ( ! empty( $customer_data['email'] ) ) {
                $user = get_user_by( 'email', $customer_data['email'] );
                return $user ? $user->ID : 0;
            }
        }

        return 0;
    }

    /**
     * Check if item should be updated (incremental import simulation).
     *
     * @param int    $item_id     Item ID.
     * @param array  $mapped      Mapped data.
     * @param string $import_type Import type.
     * @param array  $draft       Import draft.
     * @return bool
     */
    private static function check_incremental_update( $item_id, $mapped, $import_type, $draft ) {
        $incremental = $draft['step_data'][6]['incremental'] ?? array();
        if ( empty( $incremental['enabled'] ) ) {
            return true;
        }

        $fields = ! empty( $incremental['fields'] ) ? (array) $incremental['fields'] : array();
        $hash   = IncrementalImportService::generate_hash( $mapped, $fields );
        $stored = IncrementalImportService::get_stored_hash( $item_id );

        return $hash !== $stored;
    }
}

