<?php
/**
 * Cron Handler Class
 *
 * @package WahraRentalsBookings
 */

defined('ABSPATH') || exit;

/**
 * Handles scheduled events
 */
class WAHRB_Cron {

    /**
     * Instance
     *
     * @var WAHRB_Cron|null
     */
    protected static $instance = null;

    /**
     * Get instance
     *
     * @return WAHRB_Cron
     */
    public static function instance() {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Constructor
     */
    public function __construct() {
        add_filter('cron_schedules', [$this, 'add_cron_intervals']);
        add_action('wahrb_daily_cron_event', [$this, 'process_reminders']);
        add_action('wahrb_daily_cron_event', [$this, 'auto_start_bookings']);
        add_action('wahrb_daily_cron_event', [$this, 'auto_complete_bookings']);
        add_action('wahrb_daily_cron_event', [$this, 'auto_cancel_pending_bookings']);
        add_action('wahrb_daily_cron_event', [$this, 'cleanup_expired_holds']);
        add_action('wahrb_daily_cron_event', [$this, 'cleanup_old_logs']);
        add_action('wahrb_daily_cron_event', [$this, 'cleanup_stale_drafts']);
        add_action('wahrb_daily_cron_event', [$this, 'cleanup_soft_deleted_bookings']);
        
        if (!wp_next_scheduled('wahrb_daily_cron_event')) {
            wp_schedule_event(time(), 'daily', 'wahrb_daily_cron_event');
        }
    }

    /**
     * Add cron intervals if needed
     *
     * @param array $schedules
     * @return array
     */
    public function add_cron_intervals($schedules) {
        $schedules['daily'] = array(
            'interval' => 86400,
            'display'  => __('Daily', 'wahra-rentals-bookings')
        );
        return $schedules;
    }

    /**
     * Process reminders
     */
    public function process_reminders() {
        // Get settings
        $settings = get_option('wahrb_settings_notifications', []);
        $days = intval($settings['balance_reminder_days'] ?? 3);
        if ($days <= 0) return; // Disabled

        $target_date = gmdate('Y-m-d', strtotime("+{$days} days"));
        
        global $wpdb;
        $db = WAHRB_Database::instance();
        $batch_size = 100;
        $total_processed = 0;
        $max_batches = 10; // Process max 1,000 bookings per cron run
        
        $emailer = WAHRB_Emailer::instance();
        
        for ($i = 0; $i < $max_batches; $i++) {
            // Find bookings starting on target date that are confirmed and haven't received reminder
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $results = $wpdb->get_results($wpdb->prepare("
                SELECT booking_id FROM {$db->table('bookings')}
                WHERE status = 'confirmed' 
                AND DATE(start_dt) = %s 
                AND (meta_data IS NULL OR meta_data NOT LIKE %s)
                LIMIT %d
            ", $target_date, '%"_wahrb_reminder_sent":true%', $batch_size));
            
            if (empty($results)) {
                break;
            }
            
            foreach ($results as $row) {
                try {
                    $booking = new WAHRB_Booking($row->booking_id);
                    $emailer->send_booking_reminder($booking);
                    
                    // Mark as sent to avoid loop
                    $meta = $booking->get_meta_data();
                    $meta['_wahrb_reminder_sent'] = true;
                    $booking->update(['meta_data' => wp_json_encode($meta)]);
                    
                    $total_processed++;
                } catch (Exception $e) {
                    // Log error but continue
                }
            }
            
            if (count($results) < $batch_size) {
                break; // Last batch
            }
        }
        
        if ($total_processed > 0) {
            // error_log("WAHRB Cron: $total_processed rappels envoyés.");
        }
    }

    /**
     * Auto-start confirmed bookings when start date is reached
     *
     * Transitions confirmed → checked_in when start_dt <= now
     */
    public function auto_start_bookings() {
        global $wpdb;
        $db = WAHRB_Database::instance();
        $now = current_time('mysql');
        $batch_size = 100;
        $total_processed = 0;
        $max_batches = 10;

        for ($i = 0; $i < $max_batches; $i++) {
            // Find confirmed bookings whose start date/time has passed
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $results = $wpdb->get_results($wpdb->prepare("
                SELECT booking_id FROM {$db->table('bookings')}
                WHERE status = 'confirmed' 
                AND start_dt <= %s
                LIMIT %d
            ", $now, $batch_size));

            if (empty($results)) {
                break;
            }

            foreach ($results as $row) {
                try {
                    $booking = new WAHRB_Booking($row->booking_id);
                    if ($booking->exists()) {
                        $booking->check_in(__('Automatically started at scheduled time.', 'wahra-rentals-bookings'), true);
                        $total_processed++;
                    }
                } catch (Exception $e) {
                    // Log error but continue
                }
            }

            if (count($results) < $batch_size) {
                break;
            }
        }
    }

    /**
     * Auto-stop in-progress bookings after end date (checked_in → checked_out)
     *
     * The vendor must then validate restitution (damage, payment, notes) before completing.
     */
    public function auto_complete_bookings() {
        global $wpdb;
        $db = WAHRB_Database::instance();
        $now = current_time('mysql');
        $batch_size = 100;
        $total_processed = 0;
        $max_batches = 10;
        
        for ($i = 0; $i < $max_batches; $i++) {
            // Find checked_in bookings whose end date/time has passed
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $results = $wpdb->get_results($wpdb->prepare("
                SELECT booking_id FROM {$db->table('bookings')}
                WHERE status = 'checked_in' 
                AND end_dt <= %s
                LIMIT %d
            ", $now, $batch_size));
            
            if (empty($results)) {
                break;
            }
            
            foreach ($results as $row) {
                try {
                    $booking = new WAHRB_Booking($row->booking_id);
                    if ($booking->exists()) {
                        $booking->check_out(__('Automatically ended at scheduled time. Awaiting vendor validation.', 'wahra-rentals-bookings'));
                        $total_processed++;
                    }
                } catch (Exception $e) {
                    // Log error but continue
                }
            }
            
            if (count($results) < $batch_size) {
                break;
            }
        }
    }

    /**
     * Auto-cancel pending bookings after start date
     */
    public function auto_cancel_pending_bookings() {
        global $wpdb;
        $db = WAHRB_Database::instance();
        $today = current_time('Y-m-d');
        $batch_size = 100;
        $total_processed = 0;
        $max_batches = 10; // Process max 1,000 bookings per cron run
        
        for ($i = 0; $i < $max_batches; $i++) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $results = $wpdb->get_results($wpdb->prepare("
                SELECT booking_id FROM {$db->table('bookings')}
                WHERE status = 'pending' 
                AND DATE(start_dt) < %s
                LIMIT %d
            ", $today, $batch_size));
            
            if (empty($results)) {
                break;
            }
            
            foreach ($results as $row) {
                try {
                    $booking = new WAHRB_Booking($row->booking_id);
                    if ($booking->exists()) {
                        $booking->update_status('cancelled', __('Booking automatically cancelled - start date passed without confirmation.', 'wahra-rentals-bookings'));
                        $total_processed++;
                    }
                } catch (Exception $e) {
                    // Log error but continue
                }
            }
            
            if (count($results) < $batch_size) {
                break; // Last batch
            }
        }
        
        if ($total_processed > 0) {
            // error_log("WAHRB Cron: $total_processed réservations pending annulées.");
        }
    }

    /**
     * Cleanup expired holds to prevent database bloat
     */
    public function cleanup_expired_holds() {
        global $wpdb;
        $db = WAHRB_Database::instance();
        
        $cutoff_time = gmdate('Y-m-d H:i:s');
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $deleted = $wpdb->query($wpdb->prepare("
            DELETE FROM {$db->table('holds')}
            WHERE expires_at < %s
            AND converted_to_booking = 0
            LIMIT 10000
        ", $cutoff_time));
        
        return $deleted;
    }

    /**
     * Cleanup old log entries (keep last 90 days)
     */
    public function cleanup_old_logs() {
        global $wpdb;
        $db = WAHRB_Database::instance();
        
        // Keep logs for 30 days
        $cutoff_date = gmdate('Y-m-d H:i:s', strtotime('-30 days'));
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $deleted = $wpdb->query($wpdb->prepare("
            DELETE FROM {$db->table('logs')}
            WHERE created_at < %s
            LIMIT 50000
        ", $cutoff_date));
        
        return $deleted;
    }

    /**
     * Cleanup expired wizard drafts (30+ days old)
     */
    public function cleanup_stale_drafts() {
        global $wpdb;
        $db = WAHRB_Database::instance();
        
        // Cleanup drafts older than 7 days if abandoned, or 30 days if complete/expired
        $cutoff_date = gmdate('Y-m-d H:i:s', strtotime('-30 days'));
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $deleted = $wpdb->query($wpdb->prepare("
            DELETE FROM {$db->table('wizard_drafts')}
            WHERE (
                (draft_expires_at IS NOT NULL AND draft_expires_at < %s)
                OR (status = 'abandoned' AND updated_at < %s)
                OR (is_complete = 0 AND updated_at < %s)
            )
            LIMIT 10000
        ", $cutoff_date, $cutoff_date, $cutoff_date));
        
        return $deleted;
    }

    /**
     * Purge soft-deleted bookings (365+ days old)
     */
    public function cleanup_soft_deleted_bookings() {
        global $wpdb;
        $db = WAHRB_Database::instance();
        
        // Permanently delete soft-deleted bookings after 90 days
        $cutoff_date = gmdate('Y-m-d H:i:s', strtotime('-90 days'));
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $deleted = $wpdb->query($wpdb->prepare("
            DELETE FROM {$db->table('bookings')}
            WHERE deleted_at IS NOT NULL
            AND deleted_at < %s
            LIMIT 5000
        ", $cutoff_date));
        
        return $deleted;
    }
}
