<?php

declare(strict_types=1);

namespace CloudXM\NFe\Services;

use CloudXM\NFe\Bootstrap\Container;
use CloudXM\NFe\Services\NFeQueueService;
use CloudXM\NFe\Services\OrderInvoiceLifecycleService;
use CloudXM\SDK\Support\HasLogger;
use function as_schedule_single_action;
use function as_schedule_recurring_action;
use function as_next_scheduled_action;
use function add_action;

/**
 * NFe Queue Scheduler
 *
 * Handles Action Scheduler integration for background NFe processing
 */
class NFeQueueScheduler
{
    use HasLogger;

    private Container $container;

    public function __construct(Container $container)
    {
        $this->container = $container;
    }

    /**
     * Register Action Scheduler hooks
     */
    public function registerHooks(): void
    {
        // Register WordPress cron task handlers
        add_action('cloudxm_nfe_issue_order', [$this, 'processIssue']);
        add_action('cloudxm_nfe_cancel_order', [$this, 'processCancel']);
        add_action('cloudxm_nfe_reissue_order', [$this, 'processReissue']);

        // Register Action Scheduler task handlers (for backward compatibility)
        add_action('cloudxm_nfe_queue_issue_invoice', [$this, 'processIssue']);
        add_action('cloudxm_nfe_queue_cancel_invoice', [$this, 'processCancel']);
        add_action('cloudxm_nfe_queue_reissue_invoice', [$this, 'processReissue']);

        // Register cleanup task
        add_action('cloudxm_nfe_queue_cleanup', [$this, 'processCleanup']);

        // Schedule daily cleanup if not already scheduled
        if (function_exists('as_next_scheduled_action') && function_exists('as_schedule_recurring_action')) {
            if (!as_next_scheduled_action('cloudxm_nfe_queue_cleanup')) {
                as_schedule_recurring_action(time(), 'daily', 'cloudxm_nfe_queue_cleanup');
            }
        }
    }

    /**
     * Process issue invoice task
     *
     * @param int $orderId Order ID
     */
    public function processIssue(int $orderId): void
    {
        try {
            $this->log()->info('nfe.scheduler.processing_issue', ['order_id' => $orderId]);

            $lifecycleService = $this->container->get(OrderInvoiceLifecycleService::class);
            $result = $lifecycleService->issueInvoice($orderId);

            $this->log()->info('nfe.scheduler.issue_completed', [
                'order_id' => $orderId,
                'success' => $result['success'] ?? false,
            ]);

        } catch (\Throwable $e) {
            $this->log()->error('nfe.scheduler.issue_failed', [
                'order_id' => $orderId,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            // Could schedule retry here if needed
            // as_schedule_single_action(time() + 300, 'cloudxm_nfe_queue_issue_invoice', [$orderId]);
        }
    }

    /**
     * Process cancel invoice task
     *
     * @param int $orderId Order ID
     * @param array $payload Task payload containing cancellation reason
     */
    public function processCancel(int $orderId, array $payload = []): void
    {
        try {
            $reason = $payload['reason'] ?? '';

            $this->log()->info('nfe.scheduler.processing_cancel', [
                'order_id' => $orderId,
                'reason' => $reason,
            ]);

            $lifecycleService = $this->container->get(OrderInvoiceLifecycleService::class);
            $result = $lifecycleService->cancelInvoice($orderId, $reason);

            $this->log()->info('nfe.scheduler.cancel_completed', [
                'order_id' => $orderId,
                'success' => $result['success'] ?? false,
            ]);

        } catch (\Throwable $e) {
            $this->log()->error('nfe.scheduler.cancel_failed', [
                'order_id' => $orderId,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            // Could schedule retry here if needed
            // as_schedule_single_action(time() + 300, 'cloudxm_nfe_queue_cancel_invoice', [$orderId, $payload]);
        }
    }

    /**
     * Process reissue invoice task
     *
     * @param int $orderId Order ID
     */
    public function processReissue(int $orderId): void
    {
        try {
            $this->log()->info('nfe.scheduler.processing_reissue', ['order_id' => $orderId]);

            $lifecycleService = $this->container->get(OrderInvoiceLifecycleService::class);
            $result = $lifecycleService->issueInvoice($orderId);

            $this->log()->info('nfe.scheduler.reissue_completed', [
                'order_id' => $orderId,
                'success' => $result['success'] ?? false,
            ]);

        } catch (\Throwable $e) {
            $this->log()->error('nfe.scheduler.reissue_failed', [
                'order_id' => $orderId,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            // Could schedule retry here if needed
            // as_schedule_single_action(time() + 300, 'cloudxm_nfe_queue_reissue_invoice', [$orderId]);
        }
    }

    /**
     * Process cleanup task
     *
     * Cleans up old completed/failed queue tasks
     */
    public function processCleanup(): void
    {
        try {
            $this->log()->info('nfe.scheduler.processing_cleanup');

            $queueService = $this->container->get(NFeQueueService::class);
            $deleted = $queueService->cleanupOldTasks(7);

            $this->log()->info('nfe.scheduler.cleanup_completed', [
                'deleted_count' => $deleted,
            ]);

        } catch (\Throwable $e) {
            $this->log()->error('nfe.scheduler.cleanup_failed', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);
        }
    }
}
