<?php
/**
 * Export REST endpoints.
 *
 * @package PrimeLink
 */

namespace PrimeLink\Core\Rest;

use PrimeLink\Modules\Exports\Service\ExportRunner;
use PrimeLink\Modules\Exports\Service\ExportStatisticsService;

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

final class ExportRest {

    public static function register() {
        add_action( 'rest_api_init', array( __CLASS__, 'routes' ) );
    }

    public static function routes() {

        register_rest_route( 'primelink/v1', '/export/create-draft', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'create_draft' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
        ) );

        register_rest_route( 'primelink/v1', '/export/save-step', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'save_step' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
                'step'      => array( 'required' => true, 'type' => 'integer' ),
                'data'      => array(
                    'required' => false,
                    'type'     => 'object',
                ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/get-draft', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'get_draft' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/delete-draft', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'delete_draft' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/preview', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'preview' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
                'page'      => array( 'required' => false, 'type' => 'integer' ),
                'per_page'  => array( 'required' => false, 'type' => 'integer' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/run/start', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'run_start' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/run/status', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'run_status' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/run/pause', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'run_pause' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/run/resume', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'run_resume' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/download', array(
            'methods'             => 'GET',
            'callback'            => array( __CLASS__, 'download' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/templates', array(
            'methods'             => 'GET',
            'callback'            => array( __CLASS__, 'list_templates' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'type' => array( 'required' => false, 'type' => 'string' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/templates/save', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'save_template' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
        ) );

        register_rest_route( 'primelink/v1', '/export/templates/load', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'load_template' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
        ) );

        register_rest_route( 'primelink/v1', '/export/templates/delete', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'delete_template' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
        ) );

        register_rest_route( 'primelink/v1', '/export/schedule', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'schedule_export' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
                'run_at'    => array( 'required' => false, 'type' => 'string' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/log', array(
            'methods'             => 'POST',
            'callback'            => array( __CLASS__, 'get_log' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
            'args' => array(
                'export_id' => array( 'required' => true, 'type' => 'integer' ),
            ),
        ) );

        register_rest_route( 'primelink/v1', '/export/statistics', array(
            'methods'             => 'GET',
            'callback'            => array( __CLASS__, 'get_statistics' ),
            'permission_callback' => array( __CLASS__, 'permission' ),
        ) );

    }

    /**
     * Permission callback for REST API endpoints.
     * Envato compliant: Verifies user capabilities and nonce.
     *
     * @param \WP_REST_Request|null $request Request object.
     * @return bool|WP_Error
     */
    public static function permission( $request = null ) {
        // Check user capabilities first (filterable for WooCommerce/Envato compliance).
        // Default to manage_woocommerce if WooCommerce is active, otherwise manage_options.
        $default_capability = class_exists( 'WooCommerce' ) ? 'manage_woocommerce' : 'manage_options';
        $capability         = apply_filters( 'mt_primelink_capability', $default_capability );
        if ( ! current_user_can( $capability ) ) {
            return new \WP_Error(
                'rest_forbidden',
                __( 'You are not allowed to manage PrimeLink exports.', 'primelink' ),
                array( 'status' => rest_authorization_required_code() )
            );
        }

        // For POST/PUT/DELETE requests, verify nonce explicitly (Envato compliance)
        if ( $request instanceof \WP_REST_Request ) {
            $method = $request->get_method();
            if ( in_array( $method, array( 'POST', 'PUT', 'DELETE', 'PATCH' ), true ) ) {
                $nonce = $request->get_header( 'X-WP-Nonce' );
                if ( ! $nonce || ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
                    return new \WP_Error(
                        'rest_forbidden',
                        __( 'Invalid nonce. Please refresh the page and try again.', 'primelink' ),
                        array( 'status' => 403 )
                    );
                }
            }

            // Apply rate limiting (exclude polling endpoints for active exports)
            $settings = get_option( 'mt_primelink_settings', array() );
            $rate_limit_enabled = $settings['rate_limit_enabled'] ?? true;
            // Increased default limits to support multiple concurrent exports
            $rate_limit_max = absint( $settings['rate_limit_max'] ?? 500 ); // Increased from 100 to 500
            $rate_limit_window = absint( $settings['rate_limit_window'] ?? 60 );
            
            // Exclude polling/read-only endpoints from rate limiting
            $route = $request->get_route();
            $polling_endpoints = array(
                '/export/run/status',    // Status polling
                '/settings',            // Settings (read-only, low impact)
            );
            
            $is_polling_endpoint = false;
            foreach ( $polling_endpoints as $endpoint ) {
                if ( strpos( $route, $endpoint ) !== false ) {
                    $is_polling_endpoint = true;
                    break;
                }
            }

            // Only apply rate limiting to non-polling endpoints
            if ( $rate_limit_enabled && ! $is_polling_endpoint ) {
                $rate_limit_result = \PrimeLink\Helpers\RateLimiterHelper::check_request(
                    $request,
                    array(
                        'limit'    => $rate_limit_max,
                        'interval' => $rate_limit_window,
                        'policy'   => 'fixed_window',
                    )
                );

                // If rate limited, return error
                if ( is_wp_error( $rate_limit_result ) ) {
                    return $rate_limit_result;
                }
            }
        }

        return true;
    }

    public static function create_draft() {
        $drafts = get_option( 'mt_primelink_export_drafts', array() );

        $id = time();
        $drafts[ $id ] = array(
            'created_at'    => current_time( 'mysql' ),
            'step_data'     => array(),
            'current_step'  => 1,
        );

        update_option( 'mt_primelink_export_drafts', $drafts, false );

        return array( 'export_id' => $id );
    }

    public static function save_step( $request ) {
        $export_id = absint( $request['export_id'] );
        $step      = absint( $request['step'] );
        $data      = $request['data'] ?? array();

        $drafts = get_option( 'mt_primelink_export_drafts', array() );
        if ( empty( $drafts[ $export_id ] ) ) {
            return new \WP_REST_Response( array( 'message' => 'Draft not found.' ), 404 );
        }

        $draft = $drafts[ $export_id ];

        // Merge data into step_data
        if ( empty( $draft['step_data'] ) ) {
            $draft['step_data'] = array();
        }
        if ( empty( $draft['step_data'][ $step ] ) ) {
            $draft['step_data'][ $step ] = array();
        }

        $draft['step_data'][ $step ] = array_replace_recursive( $draft['step_data'][ $step ], (array) $data );
        $draft['current_step'] = max( $draft['current_step'], $step );

        // Set export type on root if step 1 is saved
        if ( $step === 1 && isset( $data['export_type'] ) ) {
            $draft['type'] = sanitize_text_field( $data['export_type'] );
        }

        $drafts[ $export_id ] = $draft;
        update_option( 'mt_primelink_export_drafts', $drafts, false );

        return array(
            'export_id' => $export_id,
            'saved'     => true,
        );
    }

    public static function get_draft( $request ) {
        $export_id = absint( $request['export_id'] );

        $drafts = get_option( 'mt_primelink_export_drafts', array() );
        if ( empty( $drafts[ $export_id ] ) ) {
            return new \WP_REST_Response( array( 'message' => 'Draft not found.' ), 404 );
        }

        return $drafts[ $export_id ];
    }

    public static function delete_draft( $request ) {
        // Get export_id from request body (POST) or query params
        $export_id = absint( $request->get_param( 'export_id' ) );
        
        if ( ! $export_id ) {
            return new \WP_REST_Response( array( 'message' => 'Export ID is required.' ), 400 );
        }

        $drafts = get_option( 'mt_primelink_export_drafts', array() );
        if ( isset( $drafts[ $export_id ] ) ) {
            unset( $drafts[ $export_id ] );
            update_option( 'mt_primelink_export_drafts', $drafts, false );
        }

        // Also delete export state if exists
        delete_option( 'mt_primelink_export_state_' . $export_id );
        
        // Also clear any scheduled events for this export
        wp_clear_scheduled_hook( 'mt_primelink_export_start_scheduled', array( $export_id ) );
        wp_clear_scheduled_hook( 'mt_primelink_export_tick', array( $export_id ) );

        return array( 'deleted' => true, 'export_id' => $export_id );
    }

    public static function preview( $request ) {
        $export_id = absint( $request['export_id'] );
        $page      = isset( $request['page'] ) ? max( 1, absint( $request['page'] ) ) : 1;
        $per_page  = isset( $request['per_page'] ) ? max( 1, min( 200, absint( $request['per_page'] ) ) ) : 20;

        $drafts = get_option( 'mt_primelink_export_drafts', array() );
        if ( empty( $drafts[ $export_id ] ) ) {
            return new \WP_REST_Response( array( 'message' => 'Draft not found.' ), 404 );
        }

        $draft = $drafts[ $export_id ];
        $export_type = $draft['type'] ?? 'products';

        // Get mapping and filters from step data
        $step2_data = $draft['step_data'][2] ?? array();
        $step3_data = $draft['step_data'][3] ?? array();
        
        // Mapping from step 2
        $mapping = $step2_data['mapping'] ?? array();
        $row_filters = $step2_data['row_filters'] ?? array();
        
        // Filters from step 3 (product filters: categories, tags, status)
        $filters = $step3_data['filters'] ?? array();

        // Normalize filters - ensure arrays
        if ( ! empty( $filters['categories'] ) && ! is_array( $filters['categories'] ) ) {
            $filters['categories'] = array( $filters['categories'] );
        }
        if ( ! empty( $filters['tags'] ) && ! is_array( $filters['tags'] ) ) {
            $filters['tags'] = array( $filters['tags'] );
        }

        // Normalize mapping - ensure it's an array
        if ( ! is_array( $mapping ) ) {
            $mapping = array();
        }

        // Get preview data from ExportRunner
        try {
            $preview = ExportRunner::get_preview( $export_type, $mapping, $filters, $row_filters, $page, $per_page );
            return $preview;
        } catch ( \Throwable $e ) {
            return new \WP_REST_Response( array(
                'message' => 'Preview failed: ' . $e->getMessage(),
                'error'   => $e->getMessage(),
                'file'    => $e->getFile(),
                'line'    => $e->getLine(),
                'debug'   => array(
                    'export_type' => $export_type,
                    'mapping'     => $mapping,
                    'filters'     => $filters,
                    'row_filters' => $row_filters,
                    'step2_data'  => $step2_data,
                    'step3_data'  => $step3_data,
                ),
            ), 500 );
        }
    }

    public static function run_start( $request ) {
        $export_id = absint( $request['export_id'] );
        $background = ! empty( $request['background'] );
        $destination = $request['destination'] ?? 'download';

        $drafts = get_option( 'mt_primelink_export_drafts', array() );
        if ( empty( $drafts[ $export_id ] ) ) {
            return new \WP_REST_Response( array( 'message' => 'Draft not found.' ), 404 );
        }

        $draft = $drafts[ $export_id ];
        
        // Save destination to step 3 data
        if ( ! isset( $draft['step_data'][3] ) ) {
            $draft['step_data'][3] = array();
        }
        $draft['step_data'][3]['destination'] = $destination;
        $drafts[ $export_id ] = $draft;
        update_option( 'mt_primelink_export_drafts', $drafts, false );

        // Start export
        $result = ExportRunner::start( $export_id, $draft, $background );

        return $result;
    }

    public static function run_status( $request ) {
        $export_id = absint( $request['export_id'] );

        $state = ExportRunner::get_state( $export_id );
        
        // Return in format expected by frontend
        return array(
            'status'   => $state['status'] ?? 'idle',
            'progress' => $state['progress'] ?? 0,
            'current'  => $state['current'] ?? 0,
            'total'    => $state['total'] ?? 0,
            'file_url' => $state['file_url'] ?? '',
            'file_path' => $state['file_path'] ?? '',
            'log'      => $state['log'] ?? array(),
        );
    }

    public static function run_pause( $request ) {
        $export_id = absint( $request['export_id'] );
        return ExportRunner::pause( $export_id );
    }

    public static function run_resume( $request ) {
        $export_id = absint( $request['export_id'] );
        return ExportRunner::resume( $export_id );
    }

    public static function download( $request ) {
        $export_id = absint( $request['export_id'] );

        $state = ExportRunner::get_state( $export_id );
        
        if ( empty( $state['file_path'] ) || ! file_exists( $state['file_path'] ) ) {
            return new \WP_REST_Response( array( 'message' => 'Export file not found.' ), 404 );
        }

        $file_path = $state['file_path'];
        $file_name = basename( $file_path );
        
        // Get file URL if available, otherwise construct it
        if ( ! empty( $state['file_url'] ) ) {
            // Redirect to file URL for download
            wp_redirect( $state['file_url'] );
            exit;
        }
        
        // If no URL, serve file directly
        $mime_type = 'application/octet-stream';
        if ( strpos( $file_name, '.csv' ) !== false ) {
            $mime_type = 'text/csv';
        } elseif ( strpos( $file_name, '.xml' ) !== false ) {
            $mime_type = 'application/xml';
        } elseif ( strpos( $file_name, '.xlsx' ) !== false ) {
            $mime_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
        }

        // Serve file with proper headers
        header( 'Content-Type: ' . $mime_type );
        header( 'Content-Disposition: attachment; filename="' . esc_attr( $file_name ) . '"' );
        header( 'Content-Length: ' . filesize( $file_path ) );
        header( 'Cache-Control: must-revalidate' );
        header( 'Pragma: public' );

        readfile( $file_path );
        exit;
    }

    /**
     * List export templates.
     *
     * @param \WP_REST_Request $request Request.
     * @return \WP_REST_Response
     */
    public static function list_templates( $request ) {
        $templates = get_option( 'mt_primelink_export_templates', array() );
        if ( ! is_array( $templates ) ) {
            $templates = array();
        }

        // Get type parameter from GET request (query string)
        $type = $request->get_param( 'type' );
        if ( empty( $type ) && isset( $request['type'] ) ) {
            $type = $request['type'];
        }
        $type = sanitize_text_field( $type );
        
        $names = array_keys( $templates );
        
        // Filter by type if provided - strict filtering: only show templates with the correct prefix
        if ( $type === 'order' ) {
            // Show only templates that start with "order:"
            $names = array_filter( $names, function( $name ) {
                return strpos( $name, 'order:' ) === 0;
            } );
        } elseif ( $type === 'product' ) {
            // Show only templates that start with "product:" or have no prefix (for backward compatibility with old templates)
            $names = array_filter( $names, function( $name ) {
                return strpos( $name, 'product:' ) === 0 || ( strpos( $name, 'order:' ) !== 0 && strpos( $name, 'customer:' ) !== 0 && strpos( $name, 'coupon:' ) !== 0 && strpos( $name, 'category:' ) !== 0 && strpos( $name, 'tag:' ) !== 0 && strpos( $name, 'attribute:' ) !== 0 && strpos( $name, 'variation:' ) !== 0 && strpos( $name, 'review:' ) !== 0 && strpos( $name, 'download:' ) !== 0 );
            } );
        } elseif ( $type === 'customer' ) {
            // Show only templates that start with "customer:"
            $names = array_filter( $names, function( $name ) {
                return strpos( $name, 'customer:' ) === 0;
            } );
        } elseif ( $type === 'coupon' ) {
            // Show only templates that start with "coupon:"
            $names = array_filter( $names, function( $name ) {
                return strpos( $name, 'coupon:' ) === 0;
            } );
        } elseif ( $type === 'category' || $type === 'categories' ) {
            // Show only templates that start with "category:"
            $names = array_filter( $names, function( $name ) {
                return strpos( $name, 'category:' ) === 0;
            } );
        } elseif ( $type === 'tag' || $type === 'tags' ) {
            // Show only templates that start with "tag:"
            $names = array_filter( $names, function( $name ) {
                return strpos( $name, 'tag:' ) === 0;
            } );
        } elseif ( $type === 'attribute' || $type === 'attributes' ) {
            // Show only templates that start with "attribute:"
            $names = array_filter( $names, function( $name ) {
                return strpos( $name, 'attribute:' ) === 0;
            } );
        } elseif ( $type === 'variation' || $type === 'variations' ) {
            // Show only templates that start with "variation:"
            $names = array_filter( $names, function( $name ) {
                return strpos( $name, 'variation:' ) === 0;
            } );
        } elseif ( $type === 'review' || $type === 'reviews' ) {
            // Show only templates that start with "review:"
            $names = array_filter( $names, function( $name ) {
                return strpos( $name, 'review:' ) === 0;
            } );
        } elseif ( $type === 'download' || $type === 'downloads' ) {
            // Show only templates that start with "download:"
            $names = array_filter( $names, function( $name ) {
                return strpos( $name, 'download:' ) === 0;
            } );
        }
        // If no type specified, return all (for backward compatibility)
        
        $names = array_values( $names );
        sort( $names );

        return new \WP_REST_Response( array(
            'templates' => $names,
        ) );
    }

    /**
     * Save export template.
     *
     * @param \WP_REST_Request $request Request.
     * @return \WP_REST_Response
     */
    public static function save_template( $request ) {
        $name = sanitize_text_field( $request['name'] );
        $data = (array) $request['data'];
        $type = isset( $request['type'] ) ? sanitize_text_field( $request['type'] ) : '';

        if ( empty( $name ) ) {
            return new \WP_REST_Response( array( 'message' => 'Template name is required.' ), 400 );
        }

        // Add prefix based on type
        $prefix = '';
        if ( $type === 'orders' || $type === 'order' ) {
            $prefix = 'order:';
        } elseif ( $type === 'products' || $type === 'product' ) {
            $prefix = 'product:';
        } elseif ( $type === 'customers' || $type === 'customer' ) {
            $prefix = 'customer:';
        } elseif ( $type === 'coupons' || $type === 'coupon' ) {
            $prefix = 'coupon:';
        } elseif ( $type === 'categories' || $type === 'category' ) {
            $prefix = 'category:';
        } elseif ( $type === 'tags' || $type === 'tag' ) {
            $prefix = 'tag:';
        } elseif ( $type === 'attributes' || $type === 'attribute' ) {
            $prefix = 'attribute:';
        } elseif ( $type === 'variations' || $type === 'variation' ) {
            $prefix = 'variation:';
        } elseif ( $type === 'reviews' || $type === 'review' ) {
            $prefix = 'review:';
        } elseif ( $type === 'downloads' || $type === 'download' ) {
            $prefix = 'download:';
        }
        
        // Only add prefix if name doesn't already have one
        if ( $prefix && strpos( $name, $prefix ) !== 0 ) {
            $name = preg_replace( '/^(order|product|customer|coupon|category|tag|attribute|variation|review|download):/', '', $name );
            $name = $prefix . $name;
        }

        $templates = get_option( 'mt_primelink_export_templates', array() );
        if ( ! is_array( $templates ) ) {
            $templates = array();
        }

        $templates[ $name ] = array(
            'updated_at' => current_time( 'mysql' ),
            'data'       => $data,
            'type'       => $type,
        );

        $saved = update_option( 'mt_primelink_export_templates', $templates, false );

        return new \WP_REST_Response( array(
            'success' => true,
            'name'    => $name,
        ) );
    }

    /**
     * Load export template.
     *
     * @param \WP_REST_Request $request Request.
     * @return \WP_REST_Response
     */
    public static function load_template( $request ) {
        $name = sanitize_text_field( $request['name'] );

        if ( empty( $name ) ) {
            return new \WP_REST_Response( array( 'message' => 'Template name is required.' ), 400 );
        }

        $templates = get_option( 'mt_primelink_export_templates', array() );
        if ( ! is_array( $templates ) || ! isset( $templates[ $name ] ) ) {
            return new \WP_REST_Response( array( 'message' => 'Template not found.' ), 404 );
        }

        return new \WP_REST_Response( array(
            'success' => true,
            'data'    => $templates[ $name ]['data'] ?? array(),
        ) );
    }

    /**
     * Delete export template.
     *
     * @param \WP_REST_Request $request Request.
     * @return \WP_REST_Response
     */
    public static function delete_template( $request ) {
        $name = sanitize_text_field( $request['name'] );

        if ( empty( $name ) ) {
            return new \WP_REST_Response( array( 'message' => 'Template name is required.' ), 400 );
        }

        $templates = get_option( 'mt_primelink_export_templates', array() );
        if ( ! is_array( $templates ) || ! isset( $templates[ $name ] ) ) {
            return new \WP_REST_Response( array( 'message' => 'Template not found.' ), 404 );
        }

        unset( $templates[ $name ] );
        update_option( 'mt_primelink_export_templates', $templates, false );

        return new \WP_REST_Response( array(
            'success' => true,
        ) );
    }

    /**
     * Schedule export.
     *
     * @param \WP_REST_Request $request Request.
     * @return \WP_REST_Response
     */
    public static function schedule_export( $request ) {
        $export_id = absint( $request['export_id'] );
        $run_at    = isset( $request['run_at'] ) ? sanitize_text_field( $request['run_at'] ) : '';

        if ( $export_id < 1 ) {
            return new \WP_REST_Response( array( 'message' => 'Export ID is required.' ), 400 );
        }

        // If explicit run_at provided, schedule one-time event
        if ( $run_at ) {
            $timestamp = strtotime( $run_at );
            if ( ! $timestamp || $timestamp < time() ) {
                return new \WP_REST_Response( array( 'message' => 'Run time must be in the future.' ), 400 );
            }
            wp_schedule_single_event( $timestamp, 'mt_primelink_export_start_scheduled', array( $export_id ) );
            
            // Persist next run for external cron fallback
            $drafts = get_option( 'mt_primelink_export_drafts', array() );
            if ( isset( $drafts[ $export_id ] ) ) {
                if ( ! isset( $drafts[ $export_id ]['step_data'][3]['schedule'] ) ) {
                    $drafts[ $export_id ]['step_data'][3]['schedule'] = array();
                }
                $drafts[ $export_id ]['step_data'][3]['schedule']['next_run'] = $timestamp;
                $drafts[ $export_id ]['step_data'][3]['schedule']['enabled'] = true;
                update_option( 'mt_primelink_export_drafts', $drafts, false );
            }
            
            return new \WP_REST_Response( array(
                'scheduled' => true,
                'run_at'    => date_i18n( 'Y-m-d H:i:s', $timestamp ),
                'recurring' => false,
            ) );
        }

        // If no explicit time provided, use draft schedule config (step 3).
        $drafts = get_option( 'mt_primelink_export_drafts', array() );
        $draft  = $drafts[ $export_id ] ?? array();
        $schedule = $draft['step_data'][3]['schedule'] ?? array();
        $enabled  = ! empty( $schedule['enabled'] );
        if ( ! $enabled ) {
            return new \WP_REST_Response( array( 'message' => 'Scheduling is not enabled in step 3.' ), 400 );
        }
        $interval = isset( $schedule['interval'] ) ? $schedule['interval'] : 'daily';
        $start    = isset( $schedule['start_time'] ) ? $schedule['start_time'] : '';

        $start_ts = $start ? strtotime( 'today ' . $start ) : time();
        if ( $start_ts < time() ) {
            $start_ts = time() + 60; // next minute
        }

        $recurrence = in_array( $interval, array( 'hourly', 'twicedaily', 'daily', 'weekly', 'monthly' ), true ) ? $interval : 'daily';

        // Clear existing scheduled events for this export
        $crons = _get_cron_array();
        if ( is_array( $crons ) ) {
            foreach ( $crons as $timestamp => $hooks ) {
                if ( isset( $hooks['mt_primelink_export_start_scheduled'] ) ) {
                    foreach ( $hooks['mt_primelink_export_start_scheduled'] as $sig => $data ) {
                        if ( isset( $data['args'][0] ) && absint( $data['args'][0] ) === $export_id ) {
                            wp_unschedule_event( $timestamp, 'mt_primelink_export_start_scheduled', array( $export_id ) );
                        }
                    }
                }
            }
        }

        wp_schedule_event( $start_ts, $recurrence, 'mt_primelink_export_start_scheduled', array( $export_id ) );
        // Persist next run for external cron fallback.
        $drafts = get_option( 'mt_primelink_export_drafts', array() );
        if ( isset( $drafts[ $export_id ]['step_data'][3]['schedule'] ) ) {
            $drafts[ $export_id ]['step_data'][3]['schedule']['next_run'] = $start_ts;
            $drafts[ $export_id ]['step_data'][3]['schedule']['interval'] = $recurrence;
            update_option( 'mt_primelink_export_drafts', $drafts, false );
        }

        return new \WP_REST_Response( array(
            'scheduled' => true,
            'run_at'    => date_i18n( 'Y-m-d H:i:s', $start_ts ),
            'recurring' => $recurrence,
        ) );
    }

    /**
     * Get export log.
     *
     * @param \WP_REST_Request $request Request.
     * @return \WP_REST_Response
     */
    public static function get_log( $request ) {
        $export_id = absint( $request['export_id'] );
        if ( $export_id < 1 ) {
            return new \WP_REST_Response( array( 'message' => 'Invalid export ID.' ), 400 );
        }
        $state = ExportRunner::get_state( $export_id );
        $log   = isset( $state['log'] ) && is_array( $state['log'] ) ? $state['log'] : array();
        return new \WP_REST_Response( array( 'log' => $log ) );
    }

    public static function get_statistics( $request ) {
        try {
            $args = array(
                'date_from' => sanitize_text_field( $request['date_from'] ?? '' ),
                'date_to'   => sanitize_text_field( $request['date_to'] ?? '' ),
                'export_id' => absint( $request['export_id'] ?? 0 ),
                'type'      => sanitize_text_field( $request['type'] ?? '' ),
            );

            $stats = ExportStatisticsService::get_statistics( $args );
            return new \WP_REST_Response( $stats, 200 );
        } catch ( \Exception $e ) {
            return new \WP_REST_Response( array(
                'message' => 'Failed to load statistics: ' . $e->getMessage(),
                'error'   => $e->getMessage(),
            ), 500 );
        }
    }
}

