<?php

declare(strict_types=1);

namespace CloudXM\NFe\Admin\Controllers;

use CloudXM\NFe\Persistence\NfeEmissionsRepository;
use CloudXM\NFe\Services\NFeFileStorageService;
use CloudXM\NFe\Services\ApiClient;
use CloudXM\NFe\Services\OrderInvoiceLifecycleService;
use CloudXM\SDK\Support\HasLogger;

/**
 * NFe AJAX Controller
 *
 * Handles general NFe AJAX requests
 */
class NFeAjaxController
{
    use HasLogger;

    public function __construct(
        private NfeEmissionsRepository $emissionRepo,
        private NFeFileStorageService $fileStorage,
        private ApiClient $apiClient,
        private OrderInvoiceLifecycleService $lifecycleService
    ) {
        // Register AJAX handlers
        add_action('wp_ajax_nfe_get_invoices', [$this, 'handleGetInvoices']);
        add_action('wp_ajax_nfe_download_file', [$this, 'handleDownloadFile']);
        add_action('wp_ajax_nfe_bulk_download', [$this, 'handleBulkDownload']);
        add_action('wp_ajax_nfe_get_emission_details', [$this, 'handleGetEmissionDetails']);
        add_action('wp_ajax_nfe_get_bulk_ids', [$this, 'handleGetBulkIds']);
        add_action('wp_ajax_nfe_issue_scheduled', [$this, 'handleIssueScheduled']);
        add_action('wp_ajax_nfe_reschedule_invoice', [$this, 'handleRescheduleInvoice']);
        add_action('wp_ajax_nfe_cancel_invoice', [$this, 'handleCancelInvoice']);
    }

    /**
     * Handle get invoices AJAX
     */
    public function handleGetInvoices(): void
    {
        try {
            check_ajax_referer('nfe_invoices', 'nonce');

            if (!current_user_can('manage_options')) {
                wp_send_json_error(['message' => __('Insufficient permissions', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $page = max(1, intval($_POST['page'] ?? 1));
            $perPage = 20; // Fixed per page
            $offset = ($page - 1) * $perPage;

            // Build conditions - show all NFe emissions
            $conditions = [];

            // Year filter
            if (!empty($_POST['year'])) {
                $year = intval($_POST['year']);
                $conditions['emission_date >='] = "{$year}-01-01 00:00:00";
                $conditions['emission_date <='] = "{$year}-12-31 23:59:59";
            }

            // Date range filter
            if (!empty($_POST['start_date'])) {
                $conditions['emission_date >='] = sanitize_text_field($_POST['start_date']) . ' 00:00:00';
            }
            if (!empty($_POST['end_date'])) {
                $conditions['emission_date <='] = sanitize_text_field($_POST['end_date']) . ' 23:59:59';
            }

            // Status filter
            $validStatuses = ['issued', 'cancelled', 'failed', 'processing', 'pending', 'authorized', 'scheduled', 'async_pending'];
            if (!empty($_POST['status']) && in_array($_POST['status'], $validStatuses, true)) {
                $conditions['status'] = sanitize_text_field($_POST['status']);
            }

            // Get total count
            $totalItems = $this->emissionRepo->countByConditions($conditions);

            // Get invoices
            $invoices = $this->emissionRepo->findByConditions($conditions, $perPage, $offset);

            // Format invoices for display
            $formattedInvoices = [];
            foreach ($invoices as $invoice) {
                $formattedInvoices[] = $this->formatInvoiceForDisplay($invoice);
            }

            // Calculate pagination
            $totalPages = ceil($totalItems / $perPage);
            $pagination = [
                'current_page' => $page,
                'total_pages' => $totalPages,
                'total_items' => $totalItems,
                'items_shown' => count($formattedInvoices)
            ];

            wp_send_json_success([
                'invoices' => $formattedInvoices,
                'pagination' => $pagination
            ]);

        } catch (\Exception $e) {
            $this->log()->error('nfe.ajax-get-invoices-failed', [
                'error' => $e->getMessage(),
                'post_data' => $_POST
            ]);

            wp_send_json_error([
                'message' => __('Failed to load invoices.', 'woocommerce-cloudxm-nfe')
            ]);
        }
    }

    /**
     * Handle download file AJAX
     */
    public function handleDownloadFile(): void
    {
        try {
            check_ajax_referer('nfe_invoices', 'nonce');

            if (!current_user_can('manage_options')) {
                wp_die(__('Insufficient permissions', 'woocommerce-cloudxm-nfe'));
            }

            $id = intval($_POST['id'] ?? 0);
            $invoiceId = sanitize_text_field($_POST['invoice_id'] ?? '');
            $type = sanitize_text_field($_POST['type'] ?? '');

            // Support both database ID and invoice_id (from server)
            $invoice = null;
            if ($id > 0) {
                $invoice = $this->emissionRepo->findById($id);
            } elseif (!empty($invoiceId)) {
                // Try to find by invoice_id in nfe_emissions table first
                $invoice = $this->emissionRepo->findByInvoiceId($invoiceId);

                // If not found in nfe_emissions, try looking up via WooCommerce order meta
                // (This handles the legacy ServicesTable which stores invoice_id in order meta)
                if (!$invoice) {
                    $orders = wc_get_orders([
                        'limit' => 1,
                        'meta_key' => '_cloudxm_nfe_invoice_id',
                        'meta_value' => $invoiceId,
                    ]);

                    if (!empty($orders)) {
                        $order = $orders[0];
                        // Build invoice array from order meta
                        $invoice = [
                            'id' => 0,
                            'order_id' => $order->get_id(),
                            'invoice_id' => $invoiceId,
                            'access_key' => $order->get_meta('_cloudxm_nfe_access_key'),
                            'emission_date' => $order->get_meta('_cloudxm_nfe_issuance_date'),
                            'xml_file_path' => '',
                            'pdf_file_path' => '',
                        ];
                    }
                }
            }

            if (!$invoice) {
                wp_die(__('Invoice not found', 'woocommerce-cloudxm-nfe'));
            }

            $orderId = (int) $invoice['order_id'];
            $accessKey = $invoice['access_key'] ?? '';
            $emissionDate = !empty($invoice['emission_date']) ? new \DateTime($invoice['emission_date']) : new \DateTime();

            if ($type === 'xml') {
                // For cancelled invoices, the cancellation flow already invalidated the cache
                // and stored the updated ZIP. Just serve from cache if available.
                $relativePath = $this->fileStorage->getFilePathFromAccessKey($accessKey, 'xml', $emissionDate);

                if ($this->fileStorage->fileExists($relativePath)) {
                    $content = $this->fileStorage->getFileContents($relativePath);
                    // Detect ZIP by magic bytes — cached files have no content-type header
                    $isZip = $content && str_starts_with($content, "PK\x03\x04");
                } else {
                    // Download from API using v2 method that returns content-type
                    $result = $this->apiClient->downloadXmlV2WithMeta($invoice['invoice_id'] ?? '');
                    $content = $result['content'] ?? '';
                    $isZip = ($result['content_type'] ?? '') === 'application/zip'
                        || ($result['content_type'] ?? '') === 'application/octet-stream'
                        || ($content && str_starts_with($content, "PK\x03\x04"));
                    if ($content) {
                        $this->fileStorage->storeXml($invoice['invoice_id'] ?? '', $content, $accessKey, $emissionDate);
                    }
                }

                if ($isZip) {
                    $filename = sprintf('nfe-%s-%d.zip', $accessKey, $orderId);
                    $this->sendFileDownload($content ?? '', $filename, 'application/zip');
                } else {
                    $filename = sprintf('nfe-%s-%d.xml', $accessKey, $orderId);
                    $this->sendFileDownload($content ?? '', $filename, 'application/xml');
                }
            } else {
                // Check if file exists locally (using access key for path generation)
                $relativePath = $this->fileStorage->getFilePathFromAccessKey($accessKey, 'pdf', $emissionDate);
                if ($this->fileStorage->fileExists($relativePath)) {
                    $content = $this->fileStorage->getFileContents($relativePath);
                } else {
                    // Download from API
                    $content = $this->apiClient->downloadInvoiceFile($invoiceId, 'pdf');
                    if ($content) {
                        $this->fileStorage->storePdf($invoiceId, $content, $accessKey, $emissionDate);
                    }
                }
                $filename = sprintf('danfe-%s-%d.pdf', $accessKey, $orderId);
                $this->sendFileDownload($content, $filename, 'application/pdf');
            }

        } catch (\Exception $e) {
            $this->log()->error('nfe.ajax-download-file-failed', [
                'error' => $e->getMessage(),
                'id' => $_POST['id'] ?? null,
                'invoice_id' => $_POST['invoice_id'] ?? null,
                'type' => $_POST['type'] ?? null
            ]);

            wp_die(__('Failed to download file.', 'woocommerce-cloudxm-nfe'));
        }
    }

    /**
     * Handle bulk download AJAX
     */
    public function handleBulkDownload(): void
    {
        try {
            check_ajax_referer('nfe_invoices', 'nonce');

            if (!current_user_can('manage_options')) {
                wp_send_json_error(['message' => __('Insufficient permissions', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $action = sanitize_text_field($_POST['bulk_action'] ?? '');
            $ids_string = sanitize_text_field($_POST['ids'] ?? '');
            $ids = array_map('intval', array_filter(explode(',', $ids_string)));

            if (!in_array($action, ['download_xml', 'download_pdf', 'download_csv'])) {
                wp_send_json_error(['message' => __('Invalid bulk action', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            // If no IDs selected, get all IDs with applied filters
            if (empty($ids)) {
                $conditions = ['status' => 'success'];

                // Year filter
                if (!empty($_POST['year'])) {
                    $year = intval($_POST['year']);
                    $conditions['emission_date >='] = "{$year}-01-01 00:00:00";
                    $conditions['emission_date <='] = "{$year}-12-31 23:59:59";
                }

                // Date range filter
                if (!empty($_POST['start_date'])) {
                    $conditions['emission_date >='] = sanitize_text_field($_POST['start_date']) . ' 00:00:00';
                }
                if (!empty($_POST['end_date'])) {
                    $conditions['emission_date <='] = sanitize_text_field($_POST['end_date']) . ' 23:59:59';
                }

                // Get all invoices (no pagination)
                $invoices = $this->emissionRepo->findByConditions($conditions, 0, 0);
                $ids = array_map('intval', array_column($invoices, 'id'));

                if (empty($ids)) {
                    wp_send_json_error(['message' => __('No invoices found matching current filters', 'woocommerce-cloudxm-nfe')]);
                    return;
                }
            }

            // Handle CSV download separately
            if ($action === 'download_csv') {
                $csvContent = $this->createBulkCsvContent($ids);
                
                if (empty($csvContent)) {
                    wp_send_json_error(['message' => __('No valid invoices found for CSV export', 'woocommerce-cloudxm-nfe')]);
                    return;
                }
                
                $csvFilename = 'nfe_invoices_' . date('Y-m-d_H-i-s') . '.csv';
                $this->sendFileDownload($csvContent, $csvFilename, 'text/csv');
                return;
            }

            // Get file type from action
            $fileType = str_replace('download_', '', $action); // xml or pdf

            // Create ZIP in memory
            $zipContent = $this->createBulkZipContent($ids, $fileType);

            if (empty($zipContent)) {
                wp_send_json_error(['message' => __('No valid files found for download', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            // Send ZIP file directly
            $zipFilename = 'nfe_' . $fileType . '_bulk_' . date('Y-m-d_H-i-s') . '.zip';
            $this->sendFileDownload($zipContent, $zipFilename, 'application/zip');

        } catch (\Exception $e) {
            $this->log()->error('nfe.ajax-bulk-download-failed', [
                'error' => $e->getMessage(),
                'action' => $_POST['bulk_action'] ?? null,
                'ids_count' => count($ids ?? [])
            ]);

            wp_send_json_error([
                'message' => __('Bulk download failed', 'woocommerce-cloudxm-nfe')
            ]);
        }
    }

    /**
     * Create bulk ZIP content from multiple files
     * Downloads files on-demand if not available locally
     */
    private function createBulkZipContent(array $ids, string $fileType): ?string
    {
        $zip = new \ZipArchive();

        // Create temporary file for ZIP creation
        $tempDir = sys_get_temp_dir();
        $zipPath = $tempDir . '/nfe_bulk_' . uniqid() . '.zip';

        if ($zip->open($zipPath, \ZipArchive::CREATE) !== true) {
            return null;
        }

        $addedFiles = 0;
        foreach ($ids as $id) {
            $invoice = $this->emissionRepo->findById($id);
            if (!$invoice) continue;

            $filePath = ($fileType === 'xml') ? $invoice['xml_file_path'] : $invoice['pdf_file_path'];
            $invoiceId = $invoice['invoice_id'] ?? '';
            $accessKey = $invoice['access_key'] ?? '';
            $emissionDate = !empty($invoice['emission_date']) ? new \DateTime($invoice['emission_date']) : new \DateTime();

            // Try to get file content from local storage
            $content = null;
            if (!empty($filePath)) {
                $content = $this->fileStorage->getFileContents($filePath);
            }

            // If not available locally, download from API
            if ($content === null && !empty($invoiceId)) {
                try {
                    if ($fileType === 'xml') {
                        $downloadUrl = $this->apiClient->downloadInvoiceFile($invoiceId, 'xml');
                        if ($downloadUrl) {
                            $response = wp_remote_get($downloadUrl, ['timeout' => 30]);
                            if (!is_wp_error($response)) {
                                $content = wp_remote_retrieve_body($response);
                                // Store for future use
                                if (!empty($content) && !empty($accessKey)) {
                                    try {
                                        $storedPath = $this->fileStorage->storeXml($invoiceId, $content, $accessKey, $emissionDate);
                                        $this->emissionRepo->update($id, ['xml_file_path' => $storedPath]);
                                    } catch (\Exception $e) {
                                        $this->log()->error('nfe.bulk_xml_store_failed', [
                                            'emission_id' => $id,
                                            'error' => $e->getMessage()
                                        ]);
                                    }
                                }
                            }
                        }
                    } else {
                        $downloadUrl = $this->apiClient->downloadInvoiceFile($invoiceId, 'pdf');
                        if ($downloadUrl) {
                            $response = wp_remote_get($downloadUrl, ['timeout' => 30]);
                            if (!is_wp_error($response)) {
                                $content = wp_remote_retrieve_body($response);
                                // Store for future use
                                if (!empty($content) && !empty($accessKey)) {
                                    try {
                                        $storedPath = $this->fileStorage->storePdf($invoiceId, $content, $accessKey, $emissionDate);
                                        $this->emissionRepo->update($id, ['pdf_file_path' => $storedPath]);
                                    } catch (\Exception $e) {
                                        $this->log()->error('nfe.bulk_pdf_store_failed', [
                                            'emission_id' => $id,
                                            'error' => $e->getMessage()
                                        ]);
                                    }
                                }
                            }
                        }
                    }
                } catch (\Exception $e) {
                    $this->log()->error('nfe.bulk_download_failed', [
                        'emission_id' => $id,
                        'file_type' => $fileType,
                        'error' => $e->getMessage()
                    ]);
                    continue;
                }
            }

            if ($content === null) continue;

            $filename = $this->getBulkFilename($invoice, $fileType);
            $zip->addFromString($filename, $content);
            $addedFiles++;
        }

        $zip->close();

        if ($addedFiles === 0) {
            unlink($zipPath);
            return null;
        }

        $zipContent = file_get_contents($zipPath);
        unlink($zipPath); // Clean up temp file

        return $zipContent;
    }

    /**
     * Generate CSV content from invoice data
     */
    private function createBulkCsvContent(array $ids): ?string
    {
        $csv = fopen('php://temp', 'r+');
        if ($csv === false) {
            return null;
        }

        // CSV header
        fputcsv($csv, [
            'ID',
            'Order ID',
            'Access Key',
            'Invoice Number',
            'Status',
            'Emission Date',
            'Total Value',
            'Protocol',
            'Environment'
        ]);

        // CSV data
        foreach ($ids as $id) {
            $invoice = $this->emissionRepo->findById($id);
            if (!$invoice) continue;

            fputcsv($csv, [
                $invoice['id'],
                $invoice['order_id'],
                $invoice['access_key'] ?? '',
                $invoice['invoice_number'] ?? '',
                $invoice['status'] ?? '',
                $invoice['emission_date'] ?? '',
                number_format((float) ($invoice['total_value'] ?? 0), 2, ',', '.'),
                $invoice['protocol_number'] ?? '',
                $invoice['environment'] ?? ''
            ]);
        }

        rewind($csv);
        $csvContent = stream_get_contents($csv);
        fclose($csv);

        return $csvContent ?: null;
    }

    /**
     * Get filename for bulk download
     */
    private function getBulkFilename(array $invoice, string $fileType): string
    {
        $accessKey = $invoice['access_key'] ?? 'unknown';
        $orderId = $invoice['order_id'] ?? '0';
        $extension = $fileType;
        
        if ($fileType === 'pdf') {
            return sprintf('danfe-%s-%d.pdf', $accessKey, $orderId);
        } else {
            return sprintf('nfe-%s-%d.xml', $accessKey, $orderId);
        }
    }

    /**
     * Send file download headers and content
     */
    private function sendFileDownload(string $content, string $filename, string $mimeType): void
    {
        header('Content-Type: ' . $mimeType);
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Length: ' . strlen($content));
        header('Cache-Control: private, max-age=0, must-revalidate');
        header('Pragma: public');

        echo $content;
        exit;
    }

    /**
     * Handle get emission details AJAX
     */
    public function handleGetEmissionDetails(): void
    {
        try {
            check_ajax_referer('nfe_invoices', 'nonce');

            if (!current_user_can('manage_options')) {
                wp_send_json_error(['message' => __('Insufficient permissions', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $id = intval($_POST['id'] ?? 0);
            if (!$id) {
                wp_send_json_error(['message' => __('Invalid emission ID', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $emission = $this->emissionRepo->findById($id);
            if (!$emission) {
                wp_send_json_error(['message' => __('Emission not found', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderUrl = admin_url('post.php?post=' . $emission['order_id'] . '&action=edit');
            $details = $this->formatEmissionDetailsForDisplay($emission, $orderUrl);

            wp_send_json_success([
                'details' => $details
            ]);

        } catch (\Exception $e) {
            $this->log()->error('nfe.ajax-get-emission-details-failed', [
                'error' => $e->getMessage(),
                'id' => $_POST['id'] ?? null
            ]);

            wp_send_json_error([
                'message' => __('Failed to load emission details.', 'woocommerce-cloudxm-nfe')
            ]);
        }
    }

    /**
     * Handle get bulk IDs AJAX
     */
    public function handleGetBulkIds(): void
    {
        try {
            check_ajax_referer('nfe_invoices', 'nonce');

            if (!current_user_can('manage_options')) {
                wp_send_json_error(['message' => __('Insufficient permissions', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $conditions = ['status' => 'success'];

            // Year filter
            if (!empty($_POST['year'])) {
                $year = intval($_POST['year']);
                $conditions['emission_date >='] = "{$year}-01-01 00:00:00";
                $conditions['emission_date <='] = "{$year}-12-31 23:59:59";
            }

            // Date range filter
            if (!empty($_POST['start_date'])) {
                $conditions['emission_date >='] = sanitize_text_field($_POST['start_date']) . ' 00:00:00';
            }
            if (!empty($_POST['end_date'])) {
                $conditions['emission_date <='] = sanitize_text_field($_POST['end_date']) . ' 23:59:59';
            }

            // Get all invoices (no pagination)
            $invoices = $this->emissionRepo->findByConditions($conditions, 0, 0);
            $ids = array_map('intval', array_column($invoices, 'id'));

            wp_send_json_success([
                'ids' => $ids,
                'count' => count($ids)
            ]);

        } catch (\Exception $e) {
            $this->log()->error('nfe.ajax-get-bulk-ids-failed', [
                'error' => $e->getMessage(),
                'post_data' => $_POST
            ]);

            wp_send_json_error([
                'message' => __('Failed to get invoice IDs.', 'woocommerce-cloudxm-nfe')
            ]);
        }
    }

    /**
     * Handle issue scheduled invoice AJAX
     */
    public function handleIssueScheduled(): void
    {
        try {
            check_ajax_referer('nfe_invoices', 'nonce');

            if (!current_user_can('manage_options')) {
                wp_send_json_error(['message' => __('Insufficient permissions', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $invoiceId = intval($_POST['invoice_id'] ?? 0);

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

            // Get the invoice from database to find the server invoice_id and order_id
            $emission = $this->emissionRepo->findById($invoiceId);

            if (!$emission || empty($emission['invoice_id'])) {
                wp_send_json_error(['message' => __('Invoice not found', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = (int) $emission['order_id'];
            $serverInvoiceId = $emission['invoice_id'];
            $result = $this->apiClient->issueScheduledInvoice($serverInvoiceId);

            $error = $result['body']['error'] ?? $result['error'] ?? '';
            if (!empty($error)) {
                $this->log()->error('nfe.ajax-issue-scheduled-failed', [
                    'emission_id' => $invoiceId,
                    'order_id' => $orderId,
                    'server_invoice_id' => $serverInvoiceId,
                    'error' => $error
                ]);
                wp_send_json_error(['message' => $error ?: __('Failed to issue invoice', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            // CRITICAL: Sync data back to order meta via lifecycle service
            // This ensures consistency between emission records and order meta
            $this->lifecycleService->syncInvoiceToOrderMeta($orderId, $serverInvoiceId);

            // Update local database emission status
            $this->emissionRepo->update($invoiceId, ['status' => 'issued']);

            wp_send_json_success(['message' => __('Invoice issued successfully', 'woocommerce-cloudxm-nfe')]);
        } catch (\Exception $e) {
            $this->log()->error('nfe.ajax-issue-scheduled-exception', ['error' => $e->getMessage()]);
            wp_send_json_error(['message' => __('Failed to issue invoice', 'woocommerce-cloudxm-nfe')]);
        }
    }

    /**
     * Handle reschedule invoice AJAX
     */
    public function handleRescheduleInvoice(): void
    {
        try {
            check_ajax_referer('nfe_invoices', 'nonce');

            if (!current_user_can('manage_options')) {
                wp_send_json_error(['message' => __('Insufficient permissions', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $invoiceId = intval($_POST['invoice_id'] ?? 0);
            $scheduledAt = sanitize_text_field($_POST['scheduled_at'] ?? '');
            $timezone = sanitize_text_field($_POST['timezone'] ?? 'America/Sao_Paulo');
            $reason = sanitize_textarea_field($_POST['scheduling_reason'] ?? '');

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

            if (empty($scheduledAt)) {
                wp_send_json_error(['message' => __('Scheduled date is required', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            // Get the invoice from database to find the server invoice_id and order_id
            $emission = $this->emissionRepo->findById($invoiceId);

            if (!$emission || empty($emission['invoice_id'])) {
                wp_send_json_error(['message' => __('Invoice not found', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = (int) $emission['order_id'];
            $serverInvoiceId = $emission['invoice_id'];
            $result = $this->apiClient->rescheduleInvoice($serverInvoiceId, $scheduledAt, $timezone, $reason);

            $error = $result['body']['error'] ?? $result['error'] ?? '';
            if (!empty($error)) {
                $this->log()->error('nfe.ajax-reschedule-failed', [
                    'emission_id' => $invoiceId,
                    'order_id' => $orderId,
                    'server_invoice_id' => $serverInvoiceId,
                    'error' => $error
                ]);
                wp_send_json_error(['message' => $error ?: __('Failed to reschedule invoice', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            // CRITICAL: Update order meta with new scheduled date
            // This ensures consistency between emission records and order meta
            $order = wc_get_order($orderId);
            if ($order) {
                $order->update_meta_data('_cloudxm_nfe_scheduled_at', $scheduledAt);
                $order->update_meta_data('_cloudxm_nfe_status', 'scheduled');
                $order->update_meta_data('_cloudxm_nfe_emission_status', 'scheduled');
                $order->save();
            }

            // Update local database with new scheduled time
            $this->emissionRepo->update($invoiceId, [
                'scheduled_for' => $scheduledAt,
                'scheduled_for_local' => $scheduledAt,
                'scheduled_timezone' => $timezone,
            ]);

            wp_send_json_success(['message' => __('Invoice rescheduled successfully', 'woocommerce-cloudxm-nfe')]);
        } catch (\Exception $e) {
            $this->log()->error('nfe.ajax-reschedule-exception', ['error' => $e->getMessage()]);
            wp_send_json_error(['message' => __('Failed to reschedule invoice', 'woocommerce-cloudxm-nfe')]);
        }
    }

    /**
     * Handle cancel invoice AJAX
     */
    public function handleCancelInvoice(): void
    {
        try {
            check_ajax_referer('nfe_invoices', 'nonce');

            if (!current_user_can('manage_options')) {
                wp_send_json_error(['message' => __('Insufficient permissions', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $invoiceId = intval($_POST['invoice_id'] ?? 0);
            $reason = sanitize_textarea_field($_POST['reason'] ?? '');

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

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

            // Get the invoice from database to find the server invoice_id and order_id
            $emission = $this->emissionRepo->findById($invoiceId);

            if (!$emission || empty($emission['invoice_id'])) {
                wp_send_json_error(['message' => __('Invoice not found', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            $orderId = (int) $emission['order_id'];
            $serverInvoiceId = $emission['invoice_id'];

            // Check if this is a scheduled invoice or issued invoice
            $isScheduledInvoice = in_array($emission['status'] ?? '', ['scheduled', 'async_pending'], true);

            if ($isScheduledInvoice) {
                // Use cancelScheduledInvoice lifecycle method for scheduled invoices
                $result = $this->lifecycleService->cancelScheduledInvoice($orderId, $reason);
            } else {
                // Use cancelInvoice lifecycle method for issued invoices
                $result = $this->lifecycleService->cancelInvoice($orderId, $reason);
            }

            if (!$result['success']) {
                wp_send_json_error(['message' => $result['message'] ?? __('Failed to cancel invoice', 'woocommerce-cloudxm-nfe')]);
                return;
            }

            wp_send_json_success(['message' => __('Invoice cancelled successfully', 'woocommerce-cloudxm-nfe')]);
        } catch (\Exception $e) {
            $this->log()->error('nfe.ajax-cancel-exception', ['error' => $e->getMessage()]);
            wp_send_json_error(['message' => __('Failed to cancel invoice', 'woocommerce-cloudxm-nfe')]);
        }
    }

    /**
     * Format invoice for display
     */
    private function formatInvoiceForDisplay(array $invoice): array
    {
        $status = strtolower($invoice['status'] ?? '');
        $hasIssuedDocument = !empty($invoice['invoice_number']) || !empty($invoice['access_key']);
        $isCancelledScheduled = $status === 'cancelled' && !$hasIssuedDocument;
        $canDownloadRemote = !empty($invoice['invoice_id']) && (
            in_array($status, ['issued', 'authorized'], true) ||
            ($status === 'cancelled' && $hasIssuedDocument)
        );

        $xmlExists = $canDownloadRemote || (!empty($invoice['xml_file_path']) && $this->fileStorage->fileExists($invoice['xml_file_path']));
        $pdfExists = $canDownloadRemote || (!empty($invoice['pdf_file_path']) && $this->fileStorage->fileExists($invoice['pdf_file_path']));

        $isScheduled = in_array($status, ['scheduled', 'async_pending'], true);
        $allowedActions = $this->parseAllowedActions($invoice['allowed_actions'] ?? null);
        if ($isCancelledScheduled || $status === 'cancelled' || $status === 'failed') {
            $allowedActions = [];
        }
        if ($isCancelledScheduled) {
            $xmlExists = false;
            $pdfExists = false;
        }

        $dateValue = $invoice['emission_date'] ?? '';
        $dateFormatted = '-';
        $dateTypeLabel = __('Emission Date', 'woocommerce-cloudxm-nfe');

        if ($isScheduled) {
            // For scheduled invoices, use scheduled_for_local as the display date
            $dateValue = $invoice['scheduled_for_local'] ?? '';
            if (empty($dateValue)) {
                // Fallback to created_at
                $dateValue = $invoice['created_at'] ?? '';
            }
            $dateTypeLabel = __('Scheduled Date', 'woocommerce-cloudxm-nfe');
            if ($dateValue) {
                $dateFormatted = wp_date(get_option('date_format') . ' ' . get_option('time_format'), strtotime($dateValue));
            }
        } elseif ($dateValue) {
            $dateFormatted = wp_date(get_option('date_format'), strtotime($dateValue));
        }

        // Get order URL
        $orderUrl = admin_url('post.php?post=' . $invoice['order_id'] . '&action=edit');

        // Extract value from dedicated database field
        $value = $invoice['total_value'] ?? '-';
        if (is_numeric($value)) {
            $value = 'R$ ' . number_format((float) $value, 2, ',', '.');
        }

        $displayNumber = $invoice['invoice_number'] ?? '';
        if ($displayNumber === '') {
            $displayNumber = $isScheduled || $isCancelledScheduled
                ? __('Not issued yet', 'woocommerce-cloudxm-nfe')
                : '-';
        }

        return [
            'id' => $invoice['id'],
            'access_key' => $invoice['access_key'],
            'invoice_number' => $invoice['invoice_number'],
            'display_number' => $displayNumber,
            'order_id' => $invoice['order_id'],
            'order_url' => $orderUrl,
            'emission_date' => $dateValue,
            'emission_date_formatted' => $dateFormatted,
            'date_type_label' => $dateTypeLabel,
            'value' => $value,
            'status' => $status,
            'status_label' => $isCancelledScheduled
                ? __('Cancelled', 'woocommerce-cloudxm-nfe')
                : $this->getStatusLabel($status),
            'environment' => $invoice['environment'] ?? '',
            'environment_label' => \CloudXM\NFe\Config\Configuration::getEnvironmentLabel($invoice['environment'] ?? ''),
            'xml_exists' => $xmlExists,
            'pdf_exists' => $pdfExists,
            'xml_file_path' => $invoice['xml_file_path'] ?? null,
            'pdf_file_path' => $invoice['pdf_file_path'] ?? null,
            'is_cancelled_scheduled' => $isCancelledScheduled,
            // Scheduled invoice fields
            'scheduled_for' => $invoice['scheduled_for'] ?? null,
            'scheduled_for_local' => $invoice['scheduled_for_local'] ?? null,
            'scheduled_timezone' => $invoice['scheduled_timezone'] ?? 'America/Sao_Paulo',
            'is_scheduled' => $isScheduled,
            // Allowed actions for scheduled/issuable invoices
            'allowed_actions' => $allowedActions,
        ];
    }

    private function getStatusLabel(string $status): string
    {
        return match ($status) {
            'issued'     => __('Issued', 'woocommerce-cloudxm-nfe'),
            'authorized' => __('Authorized', 'woocommerce-cloudxm-nfe'),
            'processing' => __('Processing', 'woocommerce-cloudxm-nfe'),
            'cancelled'  => __('Cancelled', 'woocommerce-cloudxm-nfe'),
            'failed'     => __('Failed', 'woocommerce-cloudxm-nfe'),
            'pending'    => __('Pending', 'woocommerce-cloudxm-nfe'),
            'draft'      => __('Draft', 'woocommerce-cloudxm-nfe'),
            'scheduled'  => __('Scheduled', 'woocommerce-cloudxm-nfe'),
            default      => ucfirst($status),
        };
    }

    /**
     * Parse allowed actions from database
     *
     * @param string|array|null $allowedActions Allowed actions from database (JSON string or array)
     * @return array
     */
    private function parseAllowedActions($allowedActions): array
    {
        if (is_array($allowedActions)) {
            return $allowedActions;
        }

        if (is_string($allowedActions)) {
            $decoded = json_decode($allowedActions, true);
            if (is_array($decoded)) {
                return $decoded;
            }
        }

        return [];
    }

    /**
     * Format emission details for modal display
     */
    private function formatEmissionDetailsForDisplay(array $emission, string $orderUrl): array
    {
        $status = strtolower($emission['status'] ?? '');
        $isScheduled = in_array($status, ['scheduled', 'async_pending'], true);
        $hasIssuedDocument = !empty($emission['invoice_number']) || !empty($emission['access_key']) || !empty($emission['protocol_number']);
        $isCancelledScheduled = $status === 'cancelled' && !$hasIssuedDocument;
        $isPreIssueFailure = $status === 'failed' && !$hasIssuedDocument;

        // Format dates
        $emissionDateFormatted = $emission['emission_date']
            ? wp_date(get_option('date_format') . ' ' . get_option('time_format'), strtotime($emission['emission_date']))
            : '-';

        $createdDateFormatted = $emission['created_at']
            ? wp_date(get_option('date_format') . ' ' . get_option('time_format'), strtotime($emission['created_at']))
            : '-';

        $updatedDateFormatted = $emission['updated_at']
            ? wp_date(get_option('date_format') . ' ' . get_option('time_format'), strtotime($emission['updated_at']))
            : '-';

        $cancellationDateFormatted = $emission['cancellation_date']
            ? wp_date(get_option('date_format') . ' ' . get_option('time_format'), strtotime($emission['cancellation_date']))
            : '-';

        // Use a lifecycle-aware primary date label/value.
        $displayDateFormatted = $emissionDateFormatted;
        $dateLabel = __('Emission Date', 'woocommerce-cloudxm-nfe');
        $scheduledDateFormatted = '-';

        if (($isScheduled || $isCancelledScheduled) && !empty($emission['scheduled_for_local'])) {
            $scheduledDate = new \DateTime($emission['scheduled_for_local']);
            $scheduledDateFormatted = wp_date(get_option('date_format') . ' ' . get_option('time_format'), $scheduledDate->getTimestamp());
            $displayDateFormatted = $scheduledDateFormatted;
            $dateLabel = 'Data de Agendamento';
        } elseif (($isCancelledScheduled || $isPreIssueFailure) && $createdDateFormatted !== '-') {
            $displayDateFormatted = $createdDateFormatted;
            $dateLabel = __('Request Date', 'woocommerce-cloudxm-nfe');
        }

        return [
            'id' => $emission['id'],
            'order_id' => $emission['order_id'],
            'order_url' => $orderUrl,

            // Lifecycle flags
            'has_issued_document' => $hasIssuedDocument,
            'is_cancelled_scheduled' => $isCancelledScheduled,
            'is_pre_issue_failure' => $isPreIssueFailure,

            // NFe identifiers
            'invoice_number' => $emission['invoice_number'] ?? null,
            'access_key' => $emission['access_key'],
            'protocol' => $emission['protocol_number'] ?? null,

            // Status and environment
            'status' => $emission['status'],
            'status_label' => $isCancelledScheduled
                ? __('Cancelled', 'woocommerce-cloudxm-nfe')
                : $this->getStatusLabel($status),
            'environment' => $emission['environment'] ?? null,
            'is_scheduled' => $isScheduled,

            // Financial information
            'total_value' => $emission['total_value'],
            'icms_value' => $emission['icms_value'] ?? null,
            'icms_rate' => $emission['icms_rate'] ?? null,
            'ipi_value' => $emission['ipi_value'] ?? null,
            'ipi_rate' => $emission['ipi_rate'] ?? null,
            'discount_value' => $emission['discount_value'] ?? null,
            'other_taxes' => $emission['other_taxes'] ?? null,

            // Dates
            'emission_date' => $displayDateFormatted,
            'date_label' => $dateLabel,
            'scheduled_for' => $scheduledDateFormatted,
            'scheduled_timezone' => $emission['scheduled_timezone'] ?? 'America/Sao_Paulo',
            'created_at' => $createdDateFormatted,
            'updated_at' => $updatedDateFormatted,
            'cancellation_date' => $cancellationDateFormatted,

            // Cancellation info
            'cancellation_reason' => $emission['cancellation_reason'] ?? null,
            'cancellation_protocol' => $emission['cancellation_protocol'] ?? null,
            'error_message' => $emission['error_message'] ?? null,

            // File paths
            'xml_file_path' => $emission['xml_file_path'],
            'pdf_file_path' => $emission['pdf_file_path']
        ];
    }
}
