<?php

/**
 * Affiliate Lifecycle
 *
 * Handles order status changes (refunds, cancellations) and auto-approvals.
 *
 * @package WooNooW\Modules\Affiliate
 */

namespace WooNooW\Modules\Affiliate;

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

class AffiliateLifecycle
{
    /**
     * Initialize lifecycle hooks
     */
    public static function init()
    {
        // Cancel/Revert on order refund or cancellation
        add_action('woocommerce_order_status_refunded', [__CLASS__, 'handle_order_cancelled']);
        add_action('woocommerce_order_status_cancelled', [__CLASS__, 'handle_order_cancelled']);
        add_action('woocommerce_order_status_failed', [__CLASS__, 'handle_order_cancelled']);

        // Handle order completion - immediate approval
        add_action('woocommerce_order_status_completed', [__CLASS__, 'handle_order_completed']);

        // HPOS compatible hooks
        add_action('woocommerce_order_status_changed', [__CLASS__, 'handle_hpos_status_changed'], 10, 4);
        add_action('woocommerce_update_order', [__CLASS__, 'handle_order_updated'], 10, 2);

        // Handle order deletion (trash + permanent delete)
        add_action('before_delete_post', [__CLASS__, 'handle_order_deleted'], 10, 1);
        add_action('woocommerce_delete_order', [__CLASS__, 'handle_order_deleted'], 10, 1);

        // Action Scheduler Hook for auto-approval
        add_action('woonoow_approve_referral', [__CLASS__, 'auto_approve_referral']);
    }

    /**
     * Handle cancelled, refunded, or failed orders
     */
    public static function handle_order_cancelled($order_id)
    {
        global $wpdb;
        $referrals_table = $wpdb->prefix . 'woonoow_referrals';

        // Get the order to determine the reason
        $order = wc_get_order($order_id);
        $reason = 'order_cancelled';
        if ($order) {
            $status = $order->get_status();
            $reason = 'order_' . $status;
        }

        // Find pending or approved referral
        $referral = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $referrals_table WHERE order_id = %d AND status IN ('pending', 'approved')",
            $order_id
        ));

        if ($referral) {
            // If was already approved, this is a clawback - decrease affiliate earnings
            if ($referral->status === 'approved') {
                $affiliates_table = $wpdb->prefix . 'woonoow_affiliates';
                $wpdb->query($wpdb->prepare(
                    "UPDATE $affiliates_table SET total_earnings = total_earnings - %f WHERE id = %d",
                    $referral->commission_amount,
                    $referral->affiliate_id
                ));
            }

            // Update status to rejected with reason
            $wpdb->update(
                $referrals_table,
                [
                    'status' => 'rejected',
                    'cancelled_reason' => $reason,
                    'cancelled_at' => current_time('mysql')
                ],
                ['id' => $referral->id]
            );

            // Unschedule action if action scheduler exists
            if (function_exists('as_unschedule_all_actions')) {
                as_unschedule_all_actions('woonoow_approve_referral', ['referral_id' => $referral->id], 'woonoow_affiliate');
            }
        }
    }

    /**
     * Handle order completion - check if referral should be approved
     */
    public static function handle_order_completed($order_id)
    {
        global $wpdb;
        $referrals_table = $wpdb->prefix . 'woonoow_referrals';

        // Find pending referral for this order
        $referral = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $referrals_table WHERE order_id = %d AND status = 'pending'",
            $order_id
        ));

        if (!$referral) return;

        // Check if holding period is 0 (immediate approval on completion)
        $holding_period = (int) get_option('woonoow_affiliate_holding_period', 14);

        if ($holding_period === 0) {
            // Immediate approval
            self::auto_approve_referral($referral->id);
        } else {
            // If order was completed BEFORE the scheduled action time, approve now
            // Otherwise, the scheduled action will approve later
            // Check if the scheduled action time has already passed
            $approval_time = strtotime($referral->created_at) + ($holding_period * DAY_IN_SECONDS);

            if (time() >= $approval_time) {
                self::auto_approve_referral($referral->id);
            }
            // If not, the scheduled Action Scheduler job will handle it
        }

        // Cancel the scheduled auto-approval since we're handling it now
        if (function_exists('as_unschedule_all_actions')) {
            as_unschedule_all_actions('woonoow_approve_referral', ['referral_id' => $referral->id], 'woonoow_affiliate');
        }
    }

    /**
     * Handle HPOS order status change
     */
    public static function handle_hpos_status_changed($order_id, $from_status, $to_status, $order)
    {
        if ($to_status === 'completed') {
            self::handle_order_completed($order_id);
        }
    }

    /**
     * Handle order update (HPOS compatible)
     */
    public static function handle_order_updated($order_id, $order)
    {
        if (!$order) return;

        // Check if order was just completed
        $status = $order->get_status();
        if ($status === 'completed') {
            self::handle_order_completed($order_id);
        }
    }

    /**
     * Handle order deletion (permanent delete or trash)
     */
    public static function handle_order_deleted($order_id)
    {
        // Check if this is a WooCommerce order
        $order = wc_get_order($order_id);
        if (!$order) return;

        // Only process shop orders
        $post_type = get_post_type($order_id);
        if ($post_type !== 'shop_order') return;

        global $wpdb;
        $referrals_table = $wpdb->prefix . 'woonoow_referrals';

        // Find any referral for this order
        $referral = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $referrals_table WHERE order_id = %d",
            $order_id
        ));

        if ($referral) {
            // If was already approved, this is a clawback - decrease affiliate earnings
            if ($referral->status === 'approved') {
                $affiliates_table = $wpdb->prefix . 'woonoow_affiliates';
                $wpdb->query($wpdb->prepare(
                    "UPDATE $affiliates_table SET total_earnings = total_earnings - %f WHERE id = %d",
                    $referral->commission_amount,
                    $referral->affiliate_id
                ));
            }

            // Mark as rejected with "order_deleted" reason
            $wpdb->update(
                $referrals_table,
                [
                    'status' => 'rejected',
                    'cancelled_reason' => 'order_deleted',
                    'cancelled_at' => current_time('mysql')
                ],
                ['id' => $referral->id]
            );

            // Unschedule any pending approval action
            if (function_exists('as_unschedule_all_actions')) {
                as_unschedule_all_actions('woonoow_approve_referral', ['referral_id' => $referral->id], 'woonoow_affiliate');
            }
        }
    }

    /**
     * Action Scheduler callback for auto-approving a referral after the holding period
     */
    public static function auto_approve_referral($referral_id)
    {
        global $wpdb;
        $referrals_table = $wpdb->prefix . 'woonoow_referrals';
        $affiliates_table = $wpdb->prefix . 'woonoow_affiliates';

        // Find pending referral
        $referral = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM $referrals_table WHERE id = %d AND status = 'pending'",
            $referral_id
        ));

        if (!$referral) return; // Already processed or deleted

        // Double check order status
        $order = wc_get_order($referral->order_id);
        if (!$order || in_array($order->get_status(), ['refunded', 'cancelled', 'failed'])) {
            self::handle_order_cancelled($referral->order_id);
            return;
        }

        // Approve referral
        $wpdb->update(
            $referrals_table,
            [
                'status' => 'approved',
                'approved_at' => current_time('mysql')
            ],
            ['id' => $referral_id]
        );

        // Update Affiliate totals
        $wpdb->query($wpdb->prepare(
            "UPDATE $affiliates_table SET 
            total_referrals = total_referrals + 1,
            total_earnings = total_earnings + %f
            WHERE id = %d",
            $referral->commission_amount,
            $referral->affiliate_id
        ));
    }
}
