<?php

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

/**
 * Order Auto-Complete Scheduler
 * 
 * Automatically completes orders after a specified time period
 * Uses Action Scheduler if available, falls back to WP-Cron
 */

class Upgram_Order_Scheduler
{
    private static $instance = null;
    private $hook_name = 'upgram_auto_complete_order';

    public static function get_instance()
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct()
    {
        // Hook quando pedido muda para processando
        add_action('woocommerce_order_status_processing', array($this, 'schedule_order_completion'), 10, 1);
        
        // Hook quando status do pedido muda (para cancelar agendamento)
        add_action('woocommerce_order_status_changed', array($this, 'cancel_scheduled_completion'), 10, 4);
        
        // Registrar hook para completar pedido
        add_action($this->hook_name, array($this, 'complete_order'), 10, 1);
        
        // Hook para limpar agendamentos quando configuração for desativada
        add_action('update_option_upgram_enable_auto_complete', array($this, 'handle_setting_change'), 10, 2);
    }

    /**
     * Verifica se o Action Scheduler está disponível
     */
    private function is_action_scheduler_available()
    {
        return function_exists('as_schedule_single_action') && class_exists('ActionScheduler');
    }

    /**
     * Agenda a conclusão automática de um pedido
     */
    public function schedule_order_completion($order_id)
    {
        // Verificar se a funcionalidade está ativada
        if (!get_option('upgram_enable_auto_complete', false)) {
            return;
        }

        // Obter configuração de horas
        $hours = absint(get_option('upgram_auto_complete_hours', 24));
        if ($hours < 1) {
            $hours = 24;
        }

        $order = wc_get_order($order_id);
        if (!$order) {
            return;
        }

        // Calcular timestamp para conclusão
        $complete_timestamp = time() + ($hours * HOUR_IN_SECONDS);

        // Salvar timestamp no pedido para referência
        $order->update_meta_data('_upgram_scheduled_complete_time', $complete_timestamp);
        $order->update_meta_data('_upgram_scheduled_complete_hours', $hours);
        $order->save();

        // Agendar usando Action Scheduler ou WP-Cron
        if ($this->is_action_scheduler_available()) {
            // Cancelar agendamento anterior se existir
            as_unschedule_all_actions($this->hook_name, array('order_id' => $order_id));
            
            // Agendar nova ação
            as_schedule_single_action($complete_timestamp, $this->hook_name, array('order_id' => $order_id));
            
            $order->add_order_note(
                sprintf(
                    'Agendamento automático criado: pedido será concluído em %d horas (às %s) usando Action Scheduler.',
                    $hours,
                    date_i18n('d/m/Y H:i', $complete_timestamp)
                )
            );
        } else {
            // Usar WP-Cron como fallback
            // Cancelar agendamento anterior se existir
            wp_clear_scheduled_hook($this->hook_name, array($order_id));
            
            // Agendar nova ação
            wp_schedule_single_event($complete_timestamp, $this->hook_name, array($order_id));
            
            $order->add_order_note(
                sprintf(
                    'Agendamento automático criado: pedido será concluído em %d horas (às %s) usando WP-Cron.',
                    $hours,
                    date_i18n('d/m/Y H:i', $complete_timestamp)
                )
            );
        }

        error_log(sprintf('Order #%d scheduled for auto-completion at %s', $order_id, date('Y-m-d H:i:s', $complete_timestamp)));
    }

    /**
     * Cancela o agendamento se o status do pedido for alterado manualmente
     */
    public function cancel_scheduled_completion($order_id, $old_status, $new_status, $order)
    {
        // Se o pedido não está mais em processando e tinha agendamento, cancelar
        if ($old_status === 'processing' && $new_status !== 'processing') {
            $scheduled_time = $order->get_meta('_upgram_scheduled_complete_time');
            
            if (!empty($scheduled_time)) {
                // Cancelar agendamento
                if ($this->is_action_scheduler_available()) {
                    as_unschedule_all_actions($this->hook_name, array('order_id' => $order_id));
                } else {
                    wp_clear_scheduled_hook($this->hook_name, array($order_id));
                }
                
                // Limpar meta
                $order->delete_meta_data('_upgram_scheduled_complete_time');
                $order->delete_meta_data('_upgram_scheduled_complete_hours');
                $order->save();
                
                $order->add_order_note('Agendamento automático cancelado: status alterado manualmente.');
                
                error_log(sprintf('Order #%d auto-completion cancelled: status changed from %s to %s', $order_id, $old_status, $new_status));
            }
        }
        
        // Se o novo status é processando, agendar novamente
        if ($new_status === 'processing' && $old_status !== 'processing') {
            $this->schedule_order_completion($order_id);
        }
    }

    /**
     * Completa o pedido automaticamente
     */
    public function complete_order($order_id)
    {
        $order = wc_get_order($order_id);
        
        if (!$order) {
            error_log(sprintf('Order #%d not found for auto-completion', $order_id));
            return;
        }

        // Verificar se o pedido ainda está em processando
        if ($order->get_status() !== 'processing') {
            error_log(sprintf('Order #%d is no longer processing, skipping auto-completion', $order_id));
            return;
        }

        // Obter horas configuradas
        $hours = $order->get_meta('_upgram_scheduled_complete_hours');
        if (empty($hours)) {
            $hours = get_option('upgram_auto_complete_hours', 24);
        }

        // Atualizar status para concluído
        $order->update_status('completed', sprintf(
            'Pedido concluído automaticamente após %d horas em processamento.',
            $hours
        ));

        // Limpar meta
        $order->delete_meta_data('_upgram_scheduled_complete_time');
        $order->delete_meta_data('_upgram_scheduled_complete_hours');
        $order->save();

        error_log(sprintf('Order #%d auto-completed successfully after %d hours', $order_id, $hours));
    }

    /**
     * Manipula mudanças na configuração
     */
    public function handle_setting_change($old_value, $new_value)
    {
        // Se a funcionalidade foi desativada, cancelar todos os agendamentos pendentes
        if ($new_value == false && $old_value == true) {
            $this->cancel_all_scheduled_completions();
        }
    }

    /**
     * Cancela todos os agendamentos pendentes
     */
    public function cancel_all_scheduled_completions()
    {
        if ($this->is_action_scheduler_available()) {
            as_unschedule_all_actions($this->hook_name);
        } else {
            // Para WP-Cron, precisamos buscar pedidos com agendamento
            $args = array(
                'status' => 'processing',
                'meta_key' => '_upgram_scheduled_complete_time',
                'limit' => -1,
                'return' => 'ids'
            );
            
            $order_ids = wc_get_orders($args);
            
            foreach ($order_ids as $order_id) {
                wp_clear_scheduled_hook($this->hook_name, array($order_id));
                
                $order = wc_get_order($order_id);
                if ($order) {
                    $order->delete_meta_data('_upgram_scheduled_complete_time');
                    $order->delete_meta_data('_upgram_scheduled_complete_hours');
                    $order->add_order_note('Agendamento automático cancelado: funcionalidade desativada nas configurações.');
                    $order->save();
                }
            }
        }
        
        error_log('All order auto-completion schedules cancelled');
    }

    /**
     * Obtém pedidos agendados para conclusão
     * (útil para debugging e listagem)
     */
    public function get_scheduled_orders()
    {
        $args = array(
            'status' => 'processing',
            'meta_key' => '_upgram_scheduled_complete_time',
            'limit' => -1,
        );
        
        return wc_get_orders($args);
    }
}

// Inicializar o scheduler
function upgram_init_order_scheduler()
{
    return Upgram_Order_Scheduler::get_instance();
}
add_action('plugins_loaded', 'upgram_init_order_scheduler');


