<?php

declare(strict_types=1);

namespace CloudXM\NFe\Admin\Controllers;

use CloudXM\NFe\Admin\HasTemplate;
use CloudXM\NFe\Config\Configuration;
use CloudXM\NFe\Services\NFeAutomationService;
use CloudXM\NFe\Services\OrderInvoiceLifecycleService;
use CloudXM\SDK\Support\HasLogger;
use WC_Order;

/**
 * Modern order metabox controller for NFe actions.
 */
class OrderMetaBoxController
{
    use HasTemplate;
    use HasLogger;

    public function __construct(
        private OrderInvoiceLifecycleService $lifecycleService,
        private Configuration $config,
        private ?NFeAutomationService $automationService = null
    ) {
        add_action('add_meta_boxes', [$this, 'registerMetaBox'], 10, 2);
        add_action('admin_enqueue_scripts', [$this, 'enqueueAssets']);
        add_action('wp_ajax_cloudxm_nfe_issue_order', [$this, 'handleIssueOrder']);
        add_action('wp_ajax_cloudxm_nfe_cancel_order', [$this, 'handleCancelOrder']);
        add_action('wp_ajax_cloudxm_nfe_query_status', [$this, 'handleRefreshStatus']);
        add_action('wp_ajax_cloudxm_nfe_force_unlock', [$this, 'handleForceUnlock']);
        add_action('wp_ajax_cloudxm_nfe_save_description', [$this, 'handleSaveDescription']);
        add_action('wp_ajax_cloudxm_nfe_save_schedule_date', [$this, 'handleSaveScheduleDate']);
        add_action('wp_ajax_cloudxm_nfe_schedule_order', [$this, 'handleScheduleOrder']);
        add_action('wp_ajax_cloudxm_nfe_cancel_schedule', [$this, 'handleCancelSchedule']);
        add_action('wp_ajax_cloudxm_nfe_reschedule', [$this, 'handleReschedule']);
        add_action('wp_ajax_cloudxm_nfe_recover_invoice', [$this, 'handleRecoverInvoice']);
        add_action('wp_ajax_cloudxm_nfe_set_ready_now', [$this, 'handleSetReadyNow']);
    }

    public function registerMetaBox(string $postType, mixed $post = null): void
    {
        $screenIds = ['shop_order'];

        if (function_exists('wc_get_page_screen_id')) {
            $screenIds[] = wc_get_page_screen_id('shop-order');
        } else {
            $screenIds[] = 'woocommerce_page_wc-orders';
        }

        $screenIds = array_unique(array_filter($screenIds));
        foreach ($screenIds as $screenId) {
            add_meta_box(
                'cloudxm_nfe_order_meta_box',
                __('CloudXM NFe', 'woocommerce-cloudxm-nfe'),
                [$this, 'renderMetaBox'],
                $screenId,
                'side',
                'default'
            );
        }
    }

    public function renderMetaBox(mixed $postOrOrder): void
    {
        $order = $this->resolveOrder($postOrOrder);
        if (!$order instanceof WC_Order) {
            echo '<p>' . esc_html__('Order not found.', 'woocommerce-cloudxm-nfe') . '</p>';
            return;
        }

        $this->maybeFallbackRefresh($order->get_id());

        $enableCustomDescription = (bool) $this->config->get('enable_custom_description', false);
        $customDescription = $order->get_meta('_cloudxm_nfe_description');
        $autoDescription = $this->buildAutoDescription($order);

        $this->loadTemplate('admin/meta-boxes/order-nfe', [
            'meta' => $this->lifecycleService->buildMetaBoxData($order),
            'enable_custom_description' => $enableCustomDescription,
            'custom_description' => is_string($customDescription) ? $customDescription : '',
            'auto_description' => $autoDescription,
        ]);
    }

    /**
     * Silently refresh status when an emission is scheduled/async_pending and overdue.
     * Swallows all exceptions so the meta box always renders.
     */
    private function maybeFallbackRefresh(int $orderId): void
    {
        try {
            $meta = $this->lifecycleService->buildMetaBoxData(wc_get_order($orderId));
            $status = $meta['emission_status'] ?? '';

            $needsRefresh = false;

            if ($status === 'scheduled') {
                $scheduledAt = $meta['scheduled_at'] ?? '';
                if ($scheduledAt !== '' && strtotime($scheduledAt) < time()) {
                    $needsRefresh = true;
                }
            } elseif ($status === 'async_pending') {
                $needsRefresh = true;
            }

            if ($needsRefresh) {
                $result = $this->lifecycleService->refreshStatus($orderId);
                if (($result['success'] ?? false) && $result['status'] === 'issued') {
                    $order = wc_get_order($orderId);
                    if ($order) {
                        $order->update_meta_data('_cloudxm_nfe_fallback_refresh', true);
                        $order->save();
                    }
                }
            }
        } catch (\Throwable $e) {
            $this->log()->warning('nfe.fallback_refresh_error', [
                'order_id' => $orderId,
                'error'    => $e->getMessage(),
            ]);
        }
    }

    public function enqueueAssets(string $hook): void
    {
        if (strpos($hook, 'woocommerce_page_wc-orders') === false && strpos($hook, 'post.php') === false) {
            return;
        }

        wp_enqueue_style(
            'cloudxm-nfe-admin-order-metabox',
            CLOUDXM_NFE_URL . 'assets/css/admin-order-metabox.css',
            [],
            CLOUDXM_NFE_VERSION
        );

        wp_enqueue_script(
            'cloudxm-nfe-admin-order-metabox',
            CLOUDXM_NFE_URL . 'assets/js/admin-order-metabox.js',
            ['jquery'],
            CLOUDXM_NFE_VERSION,
            true
        );

        $scheduleTz = $this->config->getScheduleTimezone();
        $tzOffset = (new \DateTime('now', new \DateTimeZone($scheduleTz)))->format('P'); // e.g. "-03:00"

        wp_localize_script('cloudxm-nfe-admin-order-metabox', 'cloudxm_nfe_admin', [
            'ajax_url' => admin_url('admin-ajax.php'),
            'api_url' => rest_url('cloudxm/v1'),
            'timezone_offset' => $tzOffset,
            'nonces' => [
                'issue_order' => wp_create_nonce('cloudxm_nfe_issue_order'),
                'cancel_order' => wp_create_nonce('cloudxm_nfe_cancel_order'),
                'query_status' => wp_create_nonce('cloudxm_nfe_query_status'),
                'force_unlock' => wp_create_nonce('cloudxm_nfe_force_unlock'),
                'save_description' => wp_create_nonce('cloudxm_nfe_save_description'),
                'save_schedule_date' => wp_create_nonce('cloudxm_nfe_save_schedule_date'),
                'schedule_order' => wp_create_nonce('cloudxm_nfe_schedule_order'),
                'cancel_schedule' => wp_create_nonce('cloudxm_nfe_cancel_schedule'),
                'reschedule' => wp_create_nonce('cloudxm_nfe_reschedule'),
                'recover_invoice' => wp_create_nonce('cloudxm_nfe_recover_invoice'),
                'set_ready_now' => wp_create_nonce('cloudxm_nfe_set_ready_now'),
            ],
            'i18n' => [
                'confirm_issue' => __('Are you sure you want to issue NFe for this order?', 'woocommerce-cloudxm-nfe'),
                'issuing' => __('Issuing...', 'woocommerce-cloudxm-nfe'),
                'success_issue' => __('NFe issued successfully.', 'woocommerce-cloudxm-nfe'),
                'error_issue' => __('Error issuing NFe.', 'woocommerce-cloudxm-nfe'),
                'issue_button' => __('Issue NFe', 'woocommerce-cloudxm-nfe'),
                'issue_now_button' => __('Issue Now', 'woocommerce-cloudxm-nfe'),
                'prompt_cancel' => __('Enter cancellation reason:', 'woocommerce-cloudxm-nfe'),
                'cancelling' => __('Cancelling...', 'woocommerce-cloudxm-nfe'),
                'success_cancel' => __('NFe cancelled successfully.', 'woocommerce-cloudxm-nfe'),
                'error_cancel' => __('Error cancelling NFe.', 'woocommerce-cloudxm-nfe'),
                'cancel_button' => __('Cancel NFe', 'woocommerce-cloudxm-nfe'),
                'querying' => __('Querying...', 'woocommerce-cloudxm-nfe'),
                'success_query' => __('Status queried successfully.', 'woocommerce-cloudxm-nfe'),
                'error_query' => __('Error querying status.', 'woocommerce-cloudxm-nfe'),
                'query_button' => __('Refresh SEFIN Status', 'woocommerce-cloudxm-nfe'),
                'reissue_button' => __('Re-issue NFe', 'woocommerce-cloudxm-nfe'),
                'prompt_force_unlock' => __('WARNING: This will clear NFe data without cancelling on server. Only use if the server has lost the invoice record. Enter reason:', 'woocommerce-cloudxm-nfe'),
                'force_unlocking' => __('Force unlocking...', 'woocommerce-cloudxm-nfe'),
                'success_force_unlock' => __('NFe data cleared successfully.', 'woocommerce-cloudxm-nfe'),
                'error_force_unlock' => __('Error force unlocking NFe.', 'woocommerce-cloudxm-nfe'),
                'force_unlock_button' => __('Force Unlock', 'woocommerce-cloudxm-nfe'),
                // Scheduling strings
                'scheduling' => __('Scheduling...', 'woocommerce-cloudxm-nfe'),
                'success_schedule' => __('NFe scheduled successfully.', 'woocommerce-cloudxm-nfe'),
                'error_schedule' => __('Error scheduling NFe.', 'woocommerce-cloudxm-nfe'),
                'schedule_button' => __('Schedule NFe', 'woocommerce-cloudxm-nfe'),
                'cancel_schedule_button' => __('Cancel Schedule', 'woocommerce-cloudxm-nfe'),
                'reschedule_button' => __('Reschedule', 'woocommerce-cloudxm-nfe'),
                'cancelling_schedule' => __('Cancelling schedule...', 'woocommerce-cloudxm-nfe'),
                'success_cancel_schedule' => __('Schedule cancelled successfully.', 'woocommerce-cloudxm-nfe'),
                'error_cancel_schedule' => __('Error cancelling schedule.', 'woocommerce-cloudxm-nfe'),
                'rescheduling' => __('Rescheduling...', 'woocommerce-cloudxm-nfe'),
                'success_reschedule' => __('NFe rescheduled successfully.', 'woocommerce-cloudxm-nfe'),
                'error_reschedule' => __('Error rescheduling NFe.', 'woocommerce-cloudxm-nfe'),
                'prompt_schedule_date' => __('Select scheduled date and time:', 'woocommerce-cloudxm-nfe'),
                'prompt_reschedule_date' => __('Select new scheduled date and time:', 'woocommerce-cloudxm-nfe'),
                'prompt_schedule_cancelled' => __('Schedule new NFe for this order (previous NFe was cancelled):', 'woocommerce-cloudxm-nfe'),
                'custom_date' => __('Custom date:', 'woocommerce-cloudxm-nfe'),
                'error_past_date' => __('Scheduled date must be in the future.', 'woocommerce-cloudxm-nfe'),
                'error_invalid_date' => __('Invalid date format.', 'woocommerce-cloudxm-nfe'),
                'confirm_cancel_schedule' => __('Are you sure you want to cancel this scheduled NFe?', 'woocommerce-cloudxm-nfe'),
                'confirm_reschedule' => __('Are you sure you want to reschedule this NFe?', 'woocommerce-cloudxm-nfe'),
                // Added for JS modals
                'cancellation_reason' => __('Cancellation Reason', 'woocommerce-cloudxm-nfe'),
                'cancel' => __('Cancel', 'woocommerce-cloudxm-nfe'),
                'prompt_cancel_placeholder' => __('Enter the reason for cancelling this NFe...', 'woocommerce-cloudxm-nfe'),
                'force_unlock_reason' => __('Force Unlock Reason', 'woocommerce-cloudxm-nfe'),
                'prompt_force_unlock_placeholder' => __('Enter the reason for force unlocking this NFe...', 'woocommerce-cloudxm-nfe'),
                'characters' => __('characters', 'woocommerce-cloudxm-nfe'),
                'close' => __('Close', 'woocommerce-cloudxm-nfe'),
                'success' => __('Success', 'woocommerce-cloudxm-nfe'),
                'error' => __('Error', 'woocommerce-cloudxm-nfe'),
                'operation_completed' => __('Operation completed!', 'woocommerce-cloudxm-nfe'),
                'processing_nfe' => __('Processing NFe...', 'woocommerce-cloudxm-nfe'),
                'issuing_nfe' => __('Issuing NFe', 'woocommerce-cloudxm-nfe'),
                'cancelling_nfe' => __('Cancelling NFe', 'woocommerce-cloudxm-nfe'),
                'reissuing_nfe' => __('Re-issuing NFe', 'woocommerce-cloudxm-nfe'),
                'processing_issue' => __('Your NFe is being processed. This may take 10-15 seconds.', 'woocommerce-cloudxm-nfe'),
                'processing_cancel' => __('Your cancellation is being processed. This may take 5-10 seconds.', 'woocommerce-cloudxm-nfe'),
                'processing_reissue' => __('Your NFe is being re-issued. This may take 10-15 seconds.', 'woocommerce-cloudxm-nfe'),
                'nfe_issued_success' => __('NFe issued successfully!', 'woocommerce-cloudxm-nfe'),
                'nfe_cancelled_success' => __('NFe cancelled successfully!', 'woocommerce-cloudxm-nfe'),
                'save_button' => __('Salvar', 'woocommerce-cloudxm-nfe'),
                'environment_label' => Configuration::getEnvironmentLabel($this->config->getEnvironment()),
                // Recovery strings
                'recover_dps_title' => __('Recover NFSe by DPS', 'woocommerce-cloudxm-nfe'),
                'recover_dps_series' => __('Series', 'woocommerce-cloudxm-nfe'),
                'recover_dps_series_placeholder' => __('e.g. 1', 'woocommerce-cloudxm-nfe'),
                'recover_dps_number' => __('DPS Number', 'woocommerce-cloudxm-nfe'),
                'recover_dps_number_placeholder' => __('e.g. 20271', 'woocommerce-cloudxm-nfe'),
                'recovering_dps' => __('Recovering NFSe...', 'woocommerce-cloudxm-nfe'),
                'success_recover_dps' => __('NFSe recovered successfully!', 'woocommerce-cloudxm-nfe'),
                'error_recover_dps' => __('Error recovering NFSe.', 'woocommerce-cloudxm-nfe'),
                'recover_dps_invalid' => __('Please enter a valid series and DPS number.', 'woocommerce-cloudxm-nfe'),
                'recover_dps_loading' => __('Your recovery request is being processed. This may take 20-30 seconds.', 'woocommerce-cloudxm-nfe'),
            ],
        ]);
    }

    public function handleIssueOrder(): void
    {
        try {
            check_ajax_referer('cloudxm_nfe_issue_order', 'nonce');
            if (!current_user_can('manage_woocommerce')) {
                wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;

            if ($orderId === 0) {
                wp_send_json_error(['message' => __('Invalid order ID.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $result = $this->lifecycleService->issueInvoice($orderId);

            if ($result['success'] ?? false) {
                wp_send_json_success([
                    'status' => 'completed',
                    'message' => __('NFe issued successfully.', 'woocommerce-cloudxm-nfe'),
                ]);
            }

            wp_send_json_error(['message' => $result['message'] ?? __('Failed to issue NFe.', 'woocommerce-cloudxm-nfe')]);
        } catch (\Throwable $e) {
            $this->log()->error('nfe.ajax-issue-order.exception', [
                'order_id' => $_POST['order_id'] ?? null,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(['message' => __('Failed to issue NFe.', 'woocommerce-cloudxm-nfe') . ' ' . $e->getMessage()]);
        }
    }

    public function handleCancelOrder(): void
    {
        try {
            check_ajax_referer('cloudxm_nfe_cancel_order', 'nonce');
            if (!current_user_can('manage_woocommerce')) {
                wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;
            $reason = isset($_POST['reason']) ? sanitize_text_field((string) $_POST['reason']) : '';
            
            if ($orderId === 0) {
                wp_send_json_error(['message' => __('Invalid order ID.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            if ($reason === '') {
                wp_send_json_error(['message' => __('Cancellation reason is required.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $result = $this->lifecycleService->cancelInvoice($orderId, $reason);

            if ($result['success'] ?? false) {
                wp_send_json_success([
                    'status' => 'completed',
                    'message' => __('NFe cancelled successfully.', 'woocommerce-cloudxm-nfe'),
                ]);
            }

            wp_send_json_error(['message' => $result['message'] ?? __('Failed to cancel NFe.', 'woocommerce-cloudxm-nfe')]);
        } catch (\Throwable $e) {
            $this->log()->error('nfe.ajax-cancel-order.exception', [
                'order_id' => $_POST['order_id'] ?? null,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(['message' => __('Failed to cancel NFe.', 'woocommerce-cloudxm-nfe') . ' ' . $e->getMessage()]);
        }
    }

    public function handleRefreshStatus(): void
    {
        try {
            check_ajax_referer('cloudxm_nfe_query_status', 'nonce');
            if (!current_user_can('manage_woocommerce')) {
                wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;
            $result = $this->lifecycleService->refreshStatus($orderId);

            if ($result['success'] ?? false) {
                wp_send_json_success(['message' => $result['message']]);
                return;
            }

            wp_send_json_error(['message' => $result['message'] ?? __('Failed to refresh status.', 'woocommerce-cloudxm-nfe')]);
        } catch (\Throwable $e) {
            $this->log()->error('nfe.ajax-refresh-status.exception', [
                'order_id' => $_POST['order_id'] ?? null,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(['message' => __('Failed to refresh status.', 'woocommerce-cloudxm-nfe') . ' ' . $e->getMessage()]);
        }
    }

    public function handleForceUnlock(): void
    {
        try {
            check_ajax_referer('cloudxm_nfe_force_unlock', 'nonce');
            if (!current_user_can('manage_woocommerce')) {
                wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;
            $reason = isset($_POST['reason']) ? sanitize_text_field((string) $_POST['reason']) : '';

            if ($orderId === 0) {
                wp_send_json_error(['message' => __('Invalid order ID.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            if ($reason === '') {
                wp_send_json_error(['message' => __('Reason is required for force unlock.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $result = $this->lifecycleService->forceUnlock($orderId, $reason);

            if ($result['success'] ?? false) {
                wp_send_json_success(['message' => $result['message']]);
                return;
            }

            wp_send_json_error(['message' => $result['message'] ?? __('Failed to force unlock NFe.', 'woocommerce-cloudxm-nfe')]);
        } catch (\Throwable $e) {
            $this->log()->error('nfe.ajax-force-unlock.exception', [
                'order_id' => $_POST['order_id'] ?? null,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(['message' => __('Failed to force unlock NFe.', 'woocommerce-cloudxm-nfe') . ' ' . $e->getMessage()]);
        }
    }

    private function resolveOrder(mixed $postOrOrder): ?WC_Order
    {
        if ($postOrOrder instanceof WC_Order) {
            return $postOrOrder;
        }

        if ($postOrOrder instanceof \WP_Post) {
            $order = wc_get_order($postOrOrder->ID);
            return $order instanceof WC_Order ? $order : null;
        }

        if (is_numeric($postOrOrder)) {
            $order = wc_get_order((int) $postOrOrder);
            return $order instanceof WC_Order ? $order : null;
        }

        return null;
    }

    private function buildAutoDescription(WC_Order $order): string
    {
        $descriptions = [];
        $items = $order->get_items();

        foreach ($items as $item) {
            $product = $item->get_product();
            if ($product) {
                $descriptions[] = $item->get_name() . ' x' . $item->get_quantity();
            }
        }

        if ($order->get_shipping_total() > 0) {
            $descriptions[] = __('Shipping', 'cloudxm-nfe');
        }

        return implode(', ', $descriptions);
    }

    public function handleSaveDescription(): void
    {
        check_ajax_referer('cloudxm_nfe_save_description', 'nonce');
        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
            return;
        }

        $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;
        if ($orderId === 0) {
            wp_send_json_error(['message' => __('Invalid order ID.', 'woocommerce-cloudxm-nfe')]);
            return;
        }

        $description = isset($_POST['description']) ? sanitize_textarea_field((string) $_POST['description']) : '';

        $order = wc_get_order($orderId);
        if (!$order instanceof WC_Order) {
            wp_send_json_error(['message' => __('Order not found.', 'woocommerce-cloudxm-nfe')]);
            return;
        }

        if (!empty($description)) {
            $order->update_meta_data('_cloudxm_nfe_description', $description);
        } else {
            $order->delete_meta_data('_cloudxm_nfe_description');
        }
        $order->save();

        wp_send_json_success(['message' => __('Description saved.', 'woocommerce-cloudxm-nfe')]);
    }

    /**
     * Handle save schedule date AJAX request
     */
    public function handleSaveScheduleDate(): void
    {
        check_ajax_referer('cloudxm_nfe_save_schedule_date', 'nonce');
        if (!current_user_can('manage_woocommerce')) {
            wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
            return;
        }

        $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;
        if ($orderId === 0) {
            wp_send_json_error(['message' => __('Invalid order ID.', 'woocommerce-cloudxm-nfe')]);
            return;
        }

        $scheduleDate = isset($_POST['schedule_date']) ? sanitize_text_field((string) $_POST['schedule_date']) : '';

        $order = wc_get_order($orderId);
        if (!$order instanceof WC_Order) {
            wp_send_json_error(['message' => __('Order not found.', 'woocommerce-cloudxm-nfe')]);
            return;
        }

        $scheduleFieldKey = $this->config->getScheduleDateField();

        // Save or delete the schedule date
        if (!empty($scheduleDate)) {
            // Validate the date format and ensure it's in the future
            try {
                $scheduleDateTime = new \DateTime($scheduleDate, new \DateTimeZone($this->config->getScheduleTimezone()));
                if ($scheduleDateTime->getTimestamp() <= time()) {
                    wp_send_json_error(['message' => __('Scheduled date must be in the future.', 'woocommerce-cloudxm-nfe')]);
                    return;
                }
                // Convert to ISO 8601 format for storage
                $order->update_meta_data($scheduleFieldKey, $scheduleDateTime->format(\DateTime::ATOM));
            } catch (\Exception $e) {
                wp_send_json_error(['message' => __('Invalid date format.', 'woocommerce-cloudxm-nfe')]);
                return;
            }
        } else {
            $order->delete_meta_data($scheduleFieldKey);
        }
        $order->save();

        wp_send_json_success(['message' => __('Schedule date saved.', 'woocommerce-cloudxm-nfe')]);
    }

    /**
     * Handle schedule order AJAX request
     */
    public function handleScheduleOrder(): void
    {
        try {
            check_ajax_referer('cloudxm_nfe_schedule_order', 'nonce');
            if (!current_user_can('manage_woocommerce')) {
                wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;
            if ($orderId === 0) {
                wp_send_json_error(['message' => __('Invalid order ID.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $customDate = isset($_POST['custom_schedule_date']) ? sanitize_text_field((string) $_POST['custom_schedule_date']) : '';
            $isCancelledInvoice = isset($_POST['is_cancelled_invoice']) && $_POST['is_cancelled_invoice'] === '1';

            $order = wc_get_order($orderId);
            if (!$order instanceof WC_Order) {
                wp_send_json_error(['message' => __('Order not found.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $scheduledAt = null;
            if ($customDate !== '') {
                try {
                    $scheduledDateTime = new \DateTime($customDate, new \DateTimeZone($this->config->getScheduleTimezone()));
                    if ($scheduledDateTime->getTimestamp() <= time()) {
                        wp_send_json_error(['message' => __('Scheduled date must be in the future.', 'woocommerce-cloudxm-nfe')]);
                        return;
                    }
                    $scheduledAt = $scheduledDateTime->format(\DateTime::ATOM);
                } catch (\Exception $e) {
                    wp_send_json_error(['message' => __('Invalid date format.', 'woocommerce-cloudxm-nfe')]);
                    return;
                }
            }

            if ($scheduledAt === null) {
                wp_send_json_error(['message' => __('Please provide a scheduled date.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $result = $this->lifecycleService->scheduleInvoice($orderId, $scheduledAt);

            if ($result['success'] ?? false) {
                wp_send_json_success([
                    'message' => __('NFe scheduled successfully.', 'woocommerce-cloudxm-nfe'),
                    'scheduled_at' => $result['scheduled_for'] ?? $scheduledAt,
                    'invoice_id' => $result['invoice_id'] ?? null,
                    'emission_id' => $result['emission_id'] ?? null,
                    'status' => $result['status'] ?? 'scheduled',
                ]);
            }

            wp_send_json_error(['message' => $result['message'] ?? __('Failed to schedule NFe.', 'woocommerce-cloudxm-nfe')]);
        } catch (\Throwable $e) {
            $this->log()->error('nfe.ajax-schedule-order.exception', [
                'order_id' => $_POST['order_id'] ?? null,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(['message' => __('Failed to schedule NFe.', 'woocommerce-cloudxm-nfe') . ' ' . $e->getMessage()]);
        }
    }

    /**
     * Handle cancel schedule AJAX request
     */
    public function handleCancelSchedule(): void
    {
        try {
            check_ajax_referer('cloudxm_nfe_cancel_schedule', 'nonce');
            if (!current_user_can('manage_woocommerce')) {
                wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;
            if ($orderId === 0) {
                wp_send_json_error(['message' => __('Invalid order ID.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $order = wc_get_order($orderId);
            if (!$order instanceof WC_Order) {
                wp_send_json_error(['message' => __('Order not found.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $emissionStatus = $order->get_meta('_cloudxm_nfe_emission_status');
            $invoiceId = (string) $order->get_meta('_cloudxm_nfe_invoice_id');

            $emission = $this->lifecycleService->getEmissionRepo()->findByOrderId($orderId);
            if ($emission && !empty($emission['status'])) {
                $emissionStatus = $emission['status'];
                if (empty($invoiceId)) {
                    $invoiceId = $emission['invoice_id'] ?? '';
                }
            }

            if (!in_array($emissionStatus, ['scheduled', 'async_pending'], true)) {
                wp_send_json_error(['message' => __('This invoice cannot be cancelled (only scheduled invoices can be cancelled).', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $result = $this->lifecycleService->cancelScheduledInvoice($orderId, 'Schedule cancelled by user');

            if ($result['success'] ?? false) {
                wp_send_json_success([
                    'message' => $result['message'] ?? __('Schedule cancelled successfully.', 'woocommerce-cloudxm-nfe'),
                    'reload' => true
                ]);
            }

            wp_send_json_error(['message' => $result['message'] ?? __('Failed to cancel schedule.', 'woocommerce-cloudxm-nfe')]);
        } catch (\Throwable $e) {
            $this->log()->error('nfe.ajax-cancel-schedule.exception', [
                'order_id' => $_POST['order_id'] ?? null,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(['message' => __('Failed to cancel schedule.', 'woocommerce-cloudxm-nfe') . ' ' . $e->getMessage()]);
        }
    }

    /**
     * Handle reschedule AJAX request
     */
    public function handleReschedule(): void
    {
        try {
            check_ajax_referer('cloudxm_nfe_reschedule', 'nonce');
            if (!current_user_can('manage_woocommerce')) {
                wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;
            if ($orderId === 0) {
                wp_send_json_error(['message' => __('Invalid order ID.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $customDate = isset($_POST['custom_schedule_date']) ? sanitize_text_field((string) $_POST['custom_schedule_date']) : '';
            if ($customDate === '') {
                wp_send_json_error(['message' => __('Please provide a new scheduled date.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $order = wc_get_order($orderId);
            if (!$order instanceof WC_Order) {
                wp_send_json_error(['message' => __('Order not found.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            try {
                $scheduledDateTime = new \DateTime($customDate, wp_timezone());
                if ($scheduledDateTime->getTimestamp() <= time()) {
                    wp_send_json_error(['message' => __('Scheduled date must be in the future.', 'woocommerce-cloudxm-nfe')]);
                    return;
                }
                $scheduledAt = $scheduledDateTime->format(\DateTime::ATOM);
            } catch (\Exception $e) {
                wp_send_json_error(['message' => __('Invalid date format.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $result = $this->lifecycleService->rescheduleInvoice($orderId, $scheduledAt);

            if ($result['success'] ?? false) {
                wp_send_json_success([
                    'message' => __('NFe rescheduled successfully.', 'woocommerce-cloudxm-nfe'),
                    'scheduled_at' => $result['scheduled_for'] ?? $scheduledAt,
                ]);
            }

            wp_send_json_error(['message' => $result['message'] ?? __('Failed to reschedule NFe.', 'woocommerce-cloudxm-nfe')]);
        } catch (\Throwable $e) {
            $this->log()->error('nfe.ajax-reschedule.exception', [
                'order_id' => $_POST['order_id'] ?? null,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(['message' => __('Failed to reschedule NFe.', 'woocommerce-cloudxm-nfe') . ' ' . $e->getMessage()]);
        }
    }

    public function handleRecoverInvoice(): void
    {
        try {
            check_ajax_referer('cloudxm_nfe_recover_invoice', 'nonce');
            if (!current_user_can('manage_woocommerce')) {
                wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;
            if ($orderId === 0) {
                wp_send_json_error(['message' => __('Invalid order ID.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $series = isset($_POST['series']) ? sanitize_text_field((string) $_POST['series']) : '';
            $dpsNumber = isset($_POST['dps_number']) ? (int) $_POST['dps_number'] : 0;

            if ($series === '' || $dpsNumber <= 0) {
                wp_send_json_error(['message' => __('Provide a series and DPS number.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $result = $this->lifecycleService->recoverInvoice($orderId, $series, $dpsNumber);

            if (!$result['success']) {
                wp_send_json_error(['message' => $result['message'] ?? __('Error recovering NFSe.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            wp_send_json_success([
                'message' => __('NFSe recovered successfully. Reloading...', 'woocommerce-cloudxm-nfe'),
                'reload' => true,
            ]);
        } catch (\Throwable $e) {
            $this->log()->error('nfe.ajax-recover-invoice.exception', [
                'order_id' => $_POST['order_id'] ?? null,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(['message' => __('Error recovering NFSe.', 'woocommerce-cloudxm-nfe') . ' ' . $e->getMessage()]);
        }
    }

    // -------------------------------------------------------------------------
    // Per-order flag AJAX handlers (CLO-11)
    // -------------------------------------------------------------------------

    /**
     * AJAX: Mark an order as "ready now" for immediate NFe issuance.
     *
     * Sets _cloudxm_nfe_auto_status = 'ready_now' on the order, which triggers the
     * updated_post_meta hook in CoreServiceProvider → NFeAutomationService.
     */
    public function handleSetReadyNow(): void
    {
        try {
            check_ajax_referer('cloudxm_nfe_set_ready_now', 'nonce');
            if (!current_user_can('manage_woocommerce')) {
                wp_send_json_error(['message' => __('Insufficient permissions.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = isset($_POST['order_id']) ? (int) $_POST['order_id'] : 0;
            if ($orderId === 0) {
                wp_send_json_error(['message' => __('Invalid order ID.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $order = wc_get_order($orderId);
            if (!$order instanceof WC_Order) {
                wp_send_json_error(['message' => __('Order not found.', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            // Set the status — the updated_post_meta hook processes it
            $order->update_meta_data(Configuration::META_AUTO_STATUS, Configuration::AUTO_READY_NOW);
            $order->save();

            // Run immediately so the admin sees the result
            if ($this->automationService) {
                $this->automationService->processOrderFlags($orderId);
            }

            wp_send_json_success([
                'message' => __('NFe marked as ready. Processing started.', 'woocommerce-cloudxm-nfe'),
                'reload' => true,
            ]);
        } catch (\Throwable $e) {
            $this->log()->error('nfe.ajax-set-ready-now.exception', [
                'order_id' => $_POST['order_id'] ?? null,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
            wp_send_json_error(['message' => __('Failed to mark order as ready.', 'woocommerce-cloudxm-nfe') . ' ' . $e->getMessage()]);
        }
    }

}
