<?php

/**
 * Refund Helper Functions
 *
 * Global helper functions for subscription refund operations.
 *
 * @package ArraySubs
 * @since 1.0.0
 */

defined('ABSPATH') || exit;

use ArraySubs\Features\PlanSwitching\Services\ProrationCalculator;
use ArraySubs\Features\Refunds\Services\RefundProcessor;

/**
 * Calculate prorated refund amount for a subscription
 *
 * Calculates refund based on unused days remaining in the current billing cycle.
 *
 * @param int         $subscription_id Subscription ID
 * @param string|null $cancel_date     Optional cancel date (defaults to now)
 * @return float Prorated refund amount
 */
function arraysubs_calculate_prorated_refund(int $subscription_id, ?string $cancel_date = null): float
{
    $proration = ProrationCalculator::calculateProrationRefund($subscription_id, $cancel_date);

    if (!$proration['success']) {
        return 0.0;
    }

    return floatval($proration['refund_amount']);
}

/**
 * Get detailed prorated refund calculation
 *
 * Returns full calculation details including days used/unused.
 *
 * @param int         $subscription_id Subscription ID
 * @param string|null $cancel_date     Optional cancel date
 * @return array Calculation details with keys: success, refund_amount, days_used, days_unused, etc.
 */
function arraysubs_get_prorated_refund_details(int $subscription_id, ?string $cancel_date = null): array
{
    return ProrationCalculator::calculateProrationRefund($subscription_id, $cancel_date);
}

/**
 * Check if a subscription can be refunded
 *
 * @param int $subscription_id Subscription ID
 * @return bool
 */
function arraysubs_can_refund_subscription(int $subscription_id): bool
{
    $result = RefundProcessor::canRefund($subscription_id);
    return $result['can_refund'] ?? false;
}

/**
 * Get maximum refundable amount for a subscription
 *
 * @param int $subscription_id Subscription ID
 * @return float Maximum refundable amount
 */
function arraysubs_get_max_refundable_amount(int $subscription_id): float
{
    $result = RefundProcessor::canRefund($subscription_id);
    return floatval($result['max_amount'] ?? 0);
}

/**
 * Get total amount refunded for a subscription
 *
 * @param int $subscription_id Subscription ID
 * @return float Total refunded
 */
function arraysubs_get_total_refunded(int $subscription_id): float
{
    return RefundProcessor::getTotalRefunded($subscription_id);
}

/**
 * Get refund history for a subscription
 *
 * @param int $subscription_id Subscription ID
 * @return array Array of refund history entries
 */
function arraysubs_get_refund_history(int $subscription_id): array
{
    return RefundProcessor::getRefundHistory($subscription_id);
}

/**
 * Process a prorated refund for a subscription
 *
 * @param int    $subscription_id Subscription ID
 * @param string $reason          Refund reason
 * @param bool   $cancel_after    Whether to cancel after refund
 * @return array Result with 'success', 'refund_id', 'amount', etc.
 */
function arraysubs_process_prorated_refund(int $subscription_id, string $reason = '', bool $cancel_after = true): array
{
    return RefundProcessor::processProratedRefund($subscription_id, $reason, $cancel_after);
}

/**
 * Process a full refund for an order
 *
 * @param int    $order_id Order ID
 * @param string $reason   Refund reason
 * @return array Result with 'success', 'refund_id', etc.
 */
function arraysubs_process_full_order_refund(int $order_id, string $reason = ''): array
{
    return RefundProcessor::processFullRefund($order_id, $reason);
}

/**
 * Process a partial refund for an order
 *
 * @param int    $order_id Order ID
 * @param float  $amount   Refund amount
 * @param string $reason   Refund reason
 * @return array Result with 'success', 'refund_id', etc.
 */
function arraysubs_process_partial_order_refund(int $order_id, float $amount, string $reason = ''): array
{
    return RefundProcessor::processPartialRefund($order_id, $amount, $reason);
}

/**
 * Check if an order is fully refunded
 *
 * @param int|\WC_Order $order Order ID or object
 * @return bool
 */
function arraysubs_is_order_fully_refunded($order): bool
{
    if (is_int($order)) {
        $order = wc_get_order($order);
    }

    if (!$order instanceof \WC_Order) {
        return false;
    }

    $total = floatval($order->get_total());
    $refunded = floatval($order->get_total_refunded());

    // Use small tolerance for floating point comparison
    return ($total - $refunded) < 0.01;
}

/**
 * Get refundable amount for an order
 *
 * @param int|\WC_Order $order Order ID or object
 * @return float Refundable amount
 */
function arraysubs_get_order_refundable_amount($order): float
{
    if (is_int($order)) {
        $order = wc_get_order($order);
    }

    if (!$order instanceof \WC_Order) {
        return 0.0;
    }

    return max(0, floatval($order->get_total()) - floatval($order->get_total_refunded()));
}

/**
 * Check if order is the most recent renewal for a subscription
 *
 * @param int $order_id        Order ID
 * @param int $subscription_id Subscription ID
 * @return bool
 */
function arraysubs_is_most_recent_renewal_order(int $order_id, int $subscription_id): bool
{
    // Check pending renewal order
    $pending_order_id = get_post_meta($subscription_id, '_pending_renewal_order_id', true);
    if ($order_id === absint($pending_order_id)) {
        return true;
    }

    // Check original order (if no renewals yet)
    $original_order_id = get_post_meta($subscription_id, '_original_order_id', true);
    if ($order_id === absint($original_order_id)) {
        // Only return true if this is the only paid order
        $renewal_count = arraysubs_get_subscription_completed_payments($subscription_id);
        return $renewal_count <= 1;
    }

    // Query for the most recent completed renewal order
    $renewal_orders = wc_get_orders([
        'meta_key' => '_arraysubs_subscription_id',
        'meta_value' => $subscription_id,
        'status' => ['completed', 'processing'],
        'orderby' => 'date',
        'order' => 'DESC',
        'limit' => 1,
    ]);

    if (!empty($renewal_orders)) {
        return $renewal_orders[0]->get_id() === $order_id;
    }

    return false;
}

/**
 * Get subscription completed payment count
 *
 * @param int $subscription_id Subscription ID
 * @return int Number of completed payments
 */
function arraysubs_get_subscription_completed_payments(int $subscription_id): int
{
    $completed_payments = get_post_meta($subscription_id, '_completed_payments', true);
    return absint($completed_payments);
}

/**
 * Check if automatic gateway refund is enabled
 *
 * @return bool
 */
function arraysubs_is_auto_gateway_refund_enabled(): bool
{
    return (bool) arraysubs_get_setting('refunds.auto_gateway_refund', true);
}

/**
 * Get refund cancellation behavior setting
 *
 * @return string 'immediate', 'end_of_period', or 'none'
 */
function arraysubs_get_refund_cancellation_behavior(): string
{
    return arraysubs_get_setting('refunds.cancellation_behavior', 'immediate');
}

/**
 * Get minimum refund amount setting
 *
 * @return float Minimum amount
 */
function arraysubs_get_minimum_refund_amount(): float
{
    return floatval(arraysubs_get_setting('refunds.minimum_amount', 0));
}

/**
 * Check if refund amount meets minimum threshold
 *
 * @param float $amount Refund amount to check
 * @return bool
 */
function arraysubs_meets_minimum_refund_amount(float $amount): bool
{
    $minimum = arraysubs_get_minimum_refund_amount();
    return $amount >= $minimum;
}

/**
 * Get all refunds for an order
 *
 * @param int $order_id Order ID
 * @return array Array of WC_Order_Refund objects
 */
function arraysubs_get_order_refunds(int $order_id): array
{
    $order = wc_get_order($order_id);
    if (!$order) {
        return [];
    }

    return $order->get_refunds();
}

/**
 * Format refund amount with currency
 *
 * @param float       $amount        Refund amount
 * @param string|null $currency      Currency code (defaults to store currency)
 * @return string Formatted price
 */
function arraysubs_format_refund_amount(float $amount, ?string $currency = null): string
{
    $args = [];
    if ($currency) {
        $args['currency'] = $currency;
    }

    return wc_price($amount, $args);
}
