<?php

/**
 * Subscription Scheduler
 * 
 * Handles cron jobs for subscription renewals and expirations
 *
 * @package WooNooW\Modules\Subscription
 */

namespace WooNooW\Modules\Subscription;

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

use WooNooW\Core\ModuleRegistry;

class SubscriptionScheduler
{

    /**
     * Cron hook for processing renewals
     */
    const RENEWAL_HOOK = 'woonoow_process_subscription_renewals';

    /**
     * Cron hook for checking expired subscriptions
     */
    const EXPIRY_HOOK = 'woonoow_check_expired_subscriptions';

    /**
     * Cron hook for sending renewal reminders
     */
    const REMINDER_HOOK = 'woonoow_send_renewal_reminders';

    /**
     * Initialize the scheduler
     */
    public static function init()
    {
        // Register cron handlers
        add_action(self::RENEWAL_HOOK, [__CLASS__, 'process_renewals']);
        add_action(self::EXPIRY_HOOK, [__CLASS__, 'check_expirations']);
        add_action(self::REMINDER_HOOK, [__CLASS__, 'send_reminders']);

        // Schedule cron events if not already scheduled
        self::schedule_events();

        // Cleanup on plugin deactivation
        register_deactivation_hook(WOONOOW_PLUGIN_FILE, [__CLASS__, 'unschedule_events']);
    }

    /**
     * Schedule cron events
     */
    public static function schedule_events()
    {
        if (!wp_next_scheduled(self::RENEWAL_HOOK)) {
            wp_schedule_event(time(), 'hourly', self::RENEWAL_HOOK);
        }

        if (!wp_next_scheduled(self::EXPIRY_HOOK)) {
            wp_schedule_event(time(), 'daily', self::EXPIRY_HOOK);
        }

        if (!wp_next_scheduled(self::REMINDER_HOOK)) {
            wp_schedule_event(time(), 'daily', self::REMINDER_HOOK);
        }
    }

    /**
     * Unschedule cron events
     */
    public static function unschedule_events()
    {
        wp_clear_scheduled_hook(self::RENEWAL_HOOK);
        wp_clear_scheduled_hook(self::EXPIRY_HOOK);
        wp_clear_scheduled_hook(self::REMINDER_HOOK);
    }

    /**
     * Process due subscription renewals
     */
    public static function process_renewals()
    {
        if (!ModuleRegistry::is_enabled('subscription')) {
            return;
        }

        $due_subscriptions = SubscriptionManager::get_due_renewals();

        foreach ($due_subscriptions as $subscription) {
            // Log renewal attempt
            do_action('woonoow/subscription/renewal_processing', $subscription->id);

            try {
                $success = SubscriptionManager::renew($subscription->id);

                if ($success) {
                    do_action('woonoow/subscription/renewal_completed', $subscription->id);
                } else {
                    // Auto-debit failed (returns false), so schedule retry
                    // Note: 'manual' falls into a separate bucket in SubscriptionManager and returns true (handled)
                    self::schedule_retry($subscription->id);
                }
            } catch (\Exception $e) {
                // Log error
                error_log('[WooNooW Subscription] Renewal failed for subscription #' . $subscription->id . ': ' . $e->getMessage());
                do_action('woonoow/subscription/renewal_error', $subscription->id, $e);

                // Also schedule retry on exception
                self::schedule_retry($subscription->id);
            }
        }
    }

    /**
     * Check for expired subscriptions
     */
    public static function check_expirations()
    {
        global $wpdb;

        if (!ModuleRegistry::is_enabled('subscription')) {
            return;
        }

        $table = $wpdb->prefix . 'woonoow_subscriptions';
        $now = current_time('mysql');

        // Find subscriptions that have passed their end date
        $expired = $wpdb->get_results($wpdb->prepare(
            "SELECT id FROM $table 
             WHERE status = 'active' 
             AND end_date IS NOT NULL 
             AND end_date <= %s",
            $now
        ));

        foreach ($expired as $subscription) {
            SubscriptionManager::update_status($subscription->id, 'expired');
            do_action('woonoow/subscription/expired', $subscription->id, 'end_date_reached');
        }

        // Also check pending-cancel subscriptions that need to be finalized
        $pending_cancel = $wpdb->get_results($wpdb->prepare(
            "SELECT id FROM $table 
             WHERE status = 'pending-cancel' 
             AND next_payment_date IS NOT NULL 
             AND next_payment_date <= %s",
            $now
        ));

        foreach ($pending_cancel as $subscription) {
            SubscriptionManager::update_status($subscription->id, 'cancelled');
            do_action('woonoow/subscription/cancelled', $subscription->id, 'pending_cancel_completed');
        }
    }

    /**
     * Send renewal reminder emails
     */
    public static function send_reminders()
    {
        global $wpdb;

        if (!ModuleRegistry::is_enabled('subscription')) {
            return;
        }

        // Check if reminders are enabled
        $settings = ModuleRegistry::get_settings('subscription');
        if (empty($settings['send_renewal_reminder'])) {
            return;
        }

        $days_before = $settings['reminder_days_before'] ?? 3;
        $reminder_date = date('Y-m-d H:i:s', strtotime("+$days_before days"));
        $tomorrow = date('Y-m-d H:i:s', strtotime('+' . ($days_before + 1) . ' days'));

        $table = $wpdb->prefix . 'woonoow_subscriptions';

        // Find subscriptions due for reminder (that haven't had reminder sent for this billing cycle)
        $due_reminders = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM $table 
             WHERE status = 'active' 
             AND next_payment_date IS NOT NULL 
             AND next_payment_date >= %s 
             AND next_payment_date < %s
             AND (reminder_sent_at IS NULL OR reminder_sent_at < last_payment_date OR (last_payment_date IS NULL AND reminder_sent_at < start_date))",
            $reminder_date,
            $tomorrow
        ));

        foreach ($due_reminders as $subscription) {
            // Trigger reminder email
            do_action('woonoow/subscription/renewal_reminder', $subscription);

            // Mark reminder as sent in database
            $wpdb->update(
                $table,
                ['reminder_sent_at' => current_time('mysql')],
                ['id' => $subscription->id],
                ['%s'],
                ['%d']
            );
        }
    }

    /**
     * Get retry schedule for failed payments
     * 
     * @param int $subscription_id
     * @return string|null Next retry datetime or null if no more retries
     */
    public static function get_next_retry_date($subscription_id)
    {
        $subscription = SubscriptionManager::get($subscription_id);
        if (!$subscription) {
            return null;
        }

        $settings = ModuleRegistry::get_settings('subscription');

        if (empty($settings['renewal_retry_enabled'])) {
            return null;
        }

        $retry_days_str = $settings['renewal_retry_days'] ?? '1,3,5';
        $retry_days = array_map('intval', array_filter(explode(',', $retry_days_str)));

        $failed_count = $subscription->failed_payment_count;

        if ($failed_count >= count($retry_days)) {
            return null; // No more retries
        }

        $days_to_add = $retry_days[$failed_count] ?? 1;
        return date('Y-m-d H:i:s', strtotime("+$days_to_add days"));
    }

    /**
     * Schedule a retry for failed payment
     * 
     * @param int $subscription_id
     */
    public static function schedule_retry($subscription_id)
    {
        global $wpdb;

        $next_retry = self::get_next_retry_date($subscription_id);

        if ($next_retry) {
            $table = $wpdb->prefix . 'woonoow_subscriptions';
            $wpdb->update(
                $table,
                ['next_payment_date' => $next_retry],
                ['id' => $subscription_id],
                ['%s'],
                ['%d']
            );
        }
    }
}
