<?php
/**
 * Eligibility — 9-step gate for whether an order can be returned.
 *
 * @package WPNest_Returns_For_WooCommerce
 */

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

class WPNest_RFW_Eligibility {

    private static $cache = array();

    /**
     * @param int $order_id
     * @return bool
     */
    public static function is_eligible( $order_id ) {
        $result = self::evaluate( (int) $order_id );
        return ! empty( $result['eligible'] );
    }

    /**
     * @param int $order_id
     * @return string  Empty if eligible, otherwise a translatable reason.
     */
    public static function get_ineligibility_reason( $order_id ) {
        $result = self::evaluate( (int) $order_id );
        return ! empty( $result['eligible'] ) ? '' : (string) $result['reason'];
    }

    /**
     * Returns ['eligible' => bool, 'reason' => string].
     */
    public static function evaluate( $order_id ) {
        $order_id = (int) $order_id;
        if ( isset( self::$cache[ $order_id ] ) ) {
            return self::$cache[ $order_id ];
        }

        $result = self::run_checks( $order_id );

        $filtered = apply_filters( 'wpnest_rfw_is_eligible', $result['eligible'], wc_get_order( $order_id ) );
        if ( false === $filtered && true === $result['eligible'] ) {
            $result = array( 'eligible' => false, 'reason' => __( 'Returns are not allowed for this order.', 'wpnest-returns-for-woocommerce' ) );
        } elseif ( true === $filtered ) {
            $result = array( 'eligible' => true, 'reason' => '' );
        }

        self::$cache[ $order_id ] = $result;
        return $result;
    }

    private static function run_checks( $order_id ) {
        if ( $order_id <= 0 ) {
            return self::fail( __( 'Invalid order.', 'wpnest-returns-for-woocommerce' ) );
        }

        $order = wc_get_order( $order_id );
        if ( ! $order instanceof WC_Order ) {
            return self::fail( __( 'Order not found.', 'wpnest-returns-for-woocommerce' ) );
        }

        // 2. Within withdrawal window.
        $window_days = max( 1, (int) get_option( 'wpnest_rfw_withdrawal_window_days', 14 ) );
        $order_date  = $order->get_date_created();
        if ( ! $order_date ) {
            return self::fail( __( 'Order has no creation date.', 'wpnest-returns-for-woocommerce' ) );
        }
        $deadline_ts = $order_date->getTimestamp() + ( $window_days * DAY_IN_SECONDS );
        if ( time() > $deadline_ts ) {
            return self::fail(
                sprintf(
                    /* translators: %d: number of days */
                    _n( 'The %d-day return window has expired for this order.', 'The %d-day return window has expired for this order.', $window_days, 'wpnest-returns-for-woocommerce' ),
                    $window_days
                )
            );
        }

        // 3. No existing non-rejected request.
        $existing = WPNest_RFW_Request_Model::get_by_order( $order_id );
        if ( $existing && WPNest_RFW_Request_Model::STATUS_REJECTED !== $existing->status ) {
            return self::fail( __( 'A return request for this order already exists.', 'wpnest-returns-for-woocommerce' ) );
        }

        // 4. Excluded statuses.
        $excluded_statuses = (array) get_option( 'wpnest_rfw_excluded_statuses', array( 'cancelled', 'failed', 'refunded', 'trash' ) );
        if ( in_array( $order->get_status(), $excluded_statuses, true ) ) {
            return self::fail( __( 'This order is in a status that does not allow returns.', 'wpnest-returns-for-woocommerce' ) );
        }

        // 5. Subscriptions.
        if ( get_option( 'wpnest_rfw_exclude_subscriptions', 1 )
            && class_exists( 'WC_Subscriptions_Order' )
            && method_exists( 'WC_Subscriptions_Order', 'order_contains_subscription' )
            && WC_Subscriptions_Order::order_contains_subscription( $order ) ) {
            return self::fail( __( 'Subscription orders cannot be returned through this form.', 'wpnest-returns-for-woocommerce' ) );
        }

        $items     = $order->get_items();
        $all_items_digital = false;
        if ( ! empty( $items ) ) {
            $all_items_digital = true;
            foreach ( $items as $item ) {
                $product = $item instanceof WC_Order_Item_Product ? $item->get_product() : null;
                if ( ! $product || ( ! $product->is_downloadable() && ! $product->is_virtual() ) ) {
                    $all_items_digital = false;
                    break;
                }
            }
        }

        // 6. Digital-with-waiver.
        if ( get_option( 'wpnest_rfw_exclude_digital_with_waiver', 1 ) && $all_items_digital ) {
            $waiver = $order->get_meta( '_wpnest_rfw_digital_waiver', true );
            if ( '1' === (string) $waiver || 1 === (int) $waiver ) {
                return self::fail( __( 'You agreed to the immediate delivery of digital content and waived the right to return.', 'wpnest-returns-for-woocommerce' ) );
            }
        }

        // 7. Customized products + 8. Excluded product IDs.
        $exclude_customized = (bool) get_option( 'wpnest_rfw_exclude_customized', 0 );
        $excluded_ids       = array_map( 'intval', (array) get_option( 'wpnest_rfw_excluded_product_ids', array() ) );

        foreach ( $items as $item ) {
            $product = $item instanceof WC_Order_Item_Product ? $item->get_product() : null;
            if ( ! $product ) {
                continue;
            }

            if ( $exclude_customized ) {
                $is_customized = (string) $product->get_meta( '_wpnest_rfw_exclude', true );
                if ( '1' === $is_customized ) {
                    return self::fail( __( 'This order contains a customized product that cannot be returned.', 'wpnest-returns-for-woocommerce' ) );
                }
            }

            if ( ! empty( $excluded_ids ) ) {
                $product_id = (int) $product->get_id();
                $parent_id  = (int) ( method_exists( $product, 'get_parent_id' ) ? $product->get_parent_id() : 0 );
                if ( in_array( $product_id, $excluded_ids, true ) || ( $parent_id > 0 && in_array( $parent_id, $excluded_ids, true ) ) ) {
                    return self::fail( __( 'This order contains an item that is excluded from returns.', 'wpnest-returns-for-woocommerce' ) );
                }
            }
        }

        return array( 'eligible' => true, 'reason' => '' );
    }

    /**
     * Returns true when the order's items are entirely digital/virtual.
     *
     * @param WC_Order $order
     * @return bool
     */
    public static function is_digital_order( $order ) {
        if ( ! $order instanceof WC_Order ) {
            return false;
        }
        $items = $order->get_items();
        if ( empty( $items ) ) {
            return false;
        }
        foreach ( $items as $item ) {
            $product = $item instanceof WC_Order_Item_Product ? $item->get_product() : null;
            if ( ! $product || ( ! $product->is_downloadable() && ! $product->is_virtual() ) ) {
                return false;
            }
        }
        return true;
    }

    private static function fail( $reason ) {
        return array( 'eligible' => false, 'reason' => $reason );
    }
}
