<?php

/**
 * The WC Vendors Pro commission controller.
 *
 * Defines the plugin name, version, and two examples hooks for how to
 * enqueue the dashboard-specific stylesheet and JavaScript.
 *
 * @package    WCVendors_Pro
 * @subpackage WCVendors_Pro/admin
 * @author     Jamie Madden <support@wcvendors.com>
 */
class WCVendors_Pro_Commission_Controller {
    /**
     * The ID of this plugin.
     *
     * @since  1.0.0
     * @access private
     * @var    string $wcvendors_pro The ID of this plugin.
     */
    private $wcvendors_pro;

    /**
     * The version of this plugin.
     *
     * @since  1.0.0
     * @access private
     * @var    string $version The current version of this plugin.
     */
    private $version;

    /**
     * Is the plugin in debug mode
     *
     * @since  1.0.0
     * @access private
     * @var    bool $debug plugin is in debug mode
     */
    private $debug;

    /**
     * Is the plugin base directory
     *
     * @since  1.0.0
     * @access private
     * @var    string $base_dir string path for the plugin directory
     */
    private $base_dir;

    /**
     * Initialize the class and set its properties.
     *
     * @param string  $wcvendors_pro The name of the plugin.
     * @param string  $version       The version of this plugin.
     * @param boolean $debug         Whether to debug or not.
     *
     * @since 1.0.0
     */
    public function __construct( $wcvendors_pro, $version, $debug ) {

        $this->wcvendors_pro = $wcvendors_pro;
        $this->version       = $version;
        $this->debug         = $debug;
        $this->base_dir      = plugin_dir_path( __DIR__ );
    }

    /**
     * Process the new commission structure
     *
     * @since   1.0.0
     * @version 1.7.3
     * @version 1.9.4 Fix the tier commission calculation
     *
     * @param float    $commission The commission amount.
     * @param int      $product_id The product id.
     * @param float    $product_price The product price.
     * @param WC_Order $order The order object.
     * @param int      $qty The product item quantity.
     * @param object   $item The item array.
     * @return float $commission The processed commission structure.
     */
    public function process_commission( $commission, $product_id, $product_price, $order, $qty, object $item = null ) {

        // Check if this is a variation and get the parent id, this ensures that the correct vendor id is retrieved.
        if ( get_post_type( $product_id ) === 'product_variation' ) {
            $product_id = get_post_field( 'post_parent', $product_id );
        }

        // Product Commission.
        $product_commission_type = get_post_meta( $product_id, 'wcv_commission_type', true );
        $single_product_price    = 0;
        if ( $product_price > 0 ) {
            $single_product_price = $product_price / $qty;
        }
        // Store Commission.
        $vendor_id             = get_post_field( 'post_author', $product_id );
        $store_commission_type = get_user_meta( $vendor_id, '_wcv_commission_type', true );

        // Reset product count for vendor.
        wp_cache_delete( 'vendor_' . $vendor_id . '_total_sales', 'counts' );

        // Category commission.
        $product = wc_get_product( $product_id );

        if ( ! $product ) {
            return $commission;
        }

        $categories = $product->get_category_ids();

        if ( 1 === count( $categories ) && 'single_select' === get_option( 'wcvendors_category_display', 'select' ) ) {
            $category_id         = reset( $categories );
            $category_commission = $this->recursive_fallback_commission( $category_id );
        } else {
            $commissions_per_category = array();
            foreach ( $categories as $category_id ) {
                $commissions_per_category[] = $this->category_commission_args( $category_id );
            }

            $commissions_per_category = array_filter( $commissions_per_category );

            $commissions_per_category = array_filter(
                $commissions_per_category,
                function ( $args ) {
                    return isset( $args['type'] ) && '' !== $args['type'];
                }
            );

            $category_commission = reset( $commissions_per_category );
        }

        $commission_args = array();
        $found_tier      = false;
        $product_sales   = $product->get_total_sales();
        $vendor_sales    = WCVendors_Pro_Vendor_Controller::get_vendor_sales_count( $vendor_id );

        if ( ! did_action( 'woocommerce_recorded_sales' ) ) {
            $product_sales += $qty;
            $vendor_sales  += $qty;
        }

        if ( $product_commission_type && ! $found_tier ) {
            if ( 'product_sales' === $product_commission_type ) {
                $tier = wcv_commission_get_tier( $product_sales, 'product', 'product_sales', $product_id );
                if ( ! is_null( $tier ) ) {
                    $found_tier                 = true;
                    $commission_args['type']    = $tier['type'];
                    $commission_args['percent'] = (float) $tier['percent'];
                    $commission_args['amount']  = (float) $tier['amount'];
                    $commission_args['fee']     = (float) $tier['fee'];
                }
            }
        } elseif ( $category_commission && is_array( $category_commission ) && '' !== $category_commission['type'] ) {
            $found_tier      = true;
            $commission_args = $category_commission;
        } elseif ( $store_commission_type && ! $found_tier ) {
            if ( in_array( $store_commission_type, array( 'product_sales', 'vendor_sales', 'product_price' ), true ) ) {
                if ( 'product_sales' === $store_commission_type ) {
                    $tier = wcv_commission_get_tier( $product_sales, 'vendor', 'product_sales', $vendor_id );
                } elseif ( 'vendor_sales' === $store_commission_type ) {
                    $tier = wcv_commission_get_tier( $vendor_sales, 'vendor', 'vendor_sales', $vendor_id );
                } else {
                    $tier = wcv_commission_get_tier( $single_product_price, 'vendor', 'product_price', $vendor_id );
                }

                if ( ! is_null( $tier ) ) {
                    $found_tier                 = true;
                    $commission_args['type']    = $tier['type'];
                    $commission_args['percent'] = (float) $tier['percent'];
                    $commission_args['amount']  = (float) $tier['amount'];
                    $commission_args['fee']     = (float) $tier['fee'];
                }
            }
        } else { // Global Commissions.
            $global_commission_type = get_option( 'wcvendors_commission_type', 'percent' );

            if ( in_array( $global_commission_type, array( 'product_sales', 'vendor_sales', 'product_price' ), true ) ) {
                if ( 'product_sales' === $global_commission_type ) {
                    $tier = wcv_commission_get_tier( $product_sales, 'global', 'product_sales' );
                } elseif ( 'vendor_sales' === $global_commission_type ) {
                    $tier = wcv_commission_get_tier( $vendor_sales, 'global', 'vendor_sales' );
                } else {
                    $tier = wcv_commission_get_tier( $single_product_price, 'global', 'product_price' );
                }

                if ( ! is_null( $tier ) ) {
                    $found_tier                 = true;
                    $commission_args['type']    = $tier['type'];
                    $commission_args['percent'] = (float) $tier['percent'];
                    $commission_args['amount']  = (float) $tier['amount'];
                    $commission_args['fee']     = (float) $tier['fee'];
                }
            }
        }

        if ( ! $found_tier ) {
            $levels = array( 'product', 'vendor', 'global' );
            foreach ( $levels as $level ) {
                $commission_args = $this->get_default_commission_rate( $product_id, $vendor_id, $level );
                $check_args      = array_filter( $commission_args );
                if ( ! empty( $commission_args ) && count( $check_args ) > 1 ) {
                    $found_tier = true;
                    break;
                }
            }
        }

        if ( ! $found_tier ) {
            $commission_args = array(
                'type'    => '',
                'percent' => 0,
                'amount'  => 0,
                'fee'     => 0,
            );
        }

        $commission_args = apply_filters( 'wcvendors_commission_args', $commission_args, $product_id, $product_price, $vendor_id );

        // Assumption that coupon codes are unique, if created by vendors they are.
        $coupons = $order->get_items( 'coupon' );

        $discount_amount = 0;

        if ( ! empty( $coupons ) ) {

            foreach ( $coupons as $coupon ) {

                $coupon_obj    = new WC_Coupon( $coupon->get_name() );
                $coupon_id     = $coupon_obj->get_id();
                $coupon_owner  = WCVendors_Pro_Vendor_Controller::get_vendor_from_object( $coupon_id );
                $product_owner = (int) WCVendors_Pro_Vendor_Controller::get_vendor_from_object( $product_id );

                $coupon_user = get_userdata( $coupon_owner );

                if ( ! $coupon_user ) {
                    continue;
                }

                // Is this coupon valid for this product?
                if ( ! $coupon_obj->is_valid_for_product( $product ) ) {
                    continue;
                }

                // This checks that the coupon is created by the product owner OR the site administrator.
                if ( (int) $coupon_owner === (int) $product_owner || in_array( 'administrator', $coupon_user->roles, true ) ) {
                    // Reset the product price to be the full price for calculations.
                    if ( is_a( $item, 'WC_Order_Item_Product' ) ) {
                        $product_price = $item->get_subtotal();
                    } elseif ( is_array( $item ) && array_key_exists( 'line_total', $item ) ) {
                        $product_price = $item['line_total'];
                    } else {
                        $product_price = $product->get_price();
                    }
                    $is_coupon_applied = true;
                    if ( $product_price === $item->get_subtotal() ) {
                        $is_coupon_applied = false;
                    }
                    if ( ! $is_coupon_applied ) {
                        $discount_amount += $coupon_obj->get_discount_amount( $product_price, $item );
                    }

                    // Apply the coupon after the commission is taken out.
                    if ( wc_string_to_bool( get_option( 'wcvendors_commission_coupon_action', 'no' ) ) ) {
                        $product_price = $product_price - $discount_amount;
                        if ( 0 > $product_price ) {
                            $product_price = 0;
                        }
                    }
                }
            }
        }

        switch ( $commission_args['type'] ) {
            case 'fixed':
                $commission = $commission_args['amount'] * $qty;
                $commission = round( $commission, 2 );
                break;
            case 'fixed_fee':
                $commission = round( ( $commission_args['amount'] - $commission_args['fee'] ) * $qty, 2 );
                break;
            case 'percent':
                if ( $commission_args['percent'] < 100 ) {
                    $commission = $product_price * ( $commission_args['percent'] / 100 );
                } else {
                    $commission = $product_price;
                }
                break;
            case 'percent_fee':
                $commission = $product_price * ( $commission_args['percent'] / 100 );
                $commission = round( $commission - ( $commission_args['fee'] * $qty ), 2 );
                break;
            default:
                $commission = round( $commission_args['amount'], 2 );
                break;
        }

        // If the coupon amount is higher than the commission amount then set it to 0.
        if ( $commission < 0 ) {
            $commission = 0;
        }

        return apply_filters( 'wcv_process_commission', $commission, $product_id, $product_price, $order, $qty, $item );
    }

    /**
     * Get default commission rate
     *
     * @since 1.9.4
     *
     * @param int    $product_id The product id.
     * @param int    $vendor_id The vendor id.
     * @param string $level The commission level.
     */
    public function get_default_commission_rate( $product_id, $vendor_id, $level = 'product' ) {

        $commission_args = array(
            'percent' => 0,
            'amount'  => 0,
            'fee'     => 0,
        );

        switch ( $level ) {
            case 'product':
                $product_commission_type = get_post_meta( $product_id, 'wcv_commission_type', true );
                if ( $product_commission_type ) {
                    $commission_args['type']    = $product_commission_type;
                    $commission_args['percent'] = (float) get_post_meta( $product_id, 'wcv_commission_percent', true );
                    $commission_args['amount']  = (float) get_post_meta( $product_id, 'wcv_commission_amount', true );
                    $commission_args['fee']     = (float) get_post_meta( $product_id, 'wcv_commission_fee', true );
                }
                break;
            case 'vendor':
                $store_commission_type = get_user_meta( $vendor_id, '_wcv_commission_type', true );
                if ( $store_commission_type ) {
                    $commission_args['type']    = $store_commission_type;
                    $commission_args['percent'] = (float) get_user_meta( $vendor_id, '_wcv_commission_percent', true );
                    $commission_args['amount']  = (float) get_user_meta( $vendor_id, '_wcv_commission_amount', true );
                    $commission_args['fee']     = (float) get_user_meta( $vendor_id, '_wcv_commission_fee', true );
                }
                break;
            case 'global':
                $global_commission_type = get_option( 'wcvendors_commission_type', 'percent' );
                if ( $global_commission_type ) {
                    $commission_args['type']    = $global_commission_type;
                    $commission_args['percent'] = (float) get_option( 'wcvendors_vendor_commission_rate', '' );
                    $commission_args['amount']  = (float) get_option( 'wcvendors_commission_amount', '' );
                    $commission_args['fee']     = (float) get_option( 'wcvendors_commission_fee', '' );
                }
                break;
        }

        return $commission_args;
    }

    /**
     * Get a commission tier based on the condition value
     *
     * @param   float   $value The value yo calculate commission from.
     * @param   string  $from  Where to get the tiers from, this is where the data is saved.
     *                         Possible values 'global', 'vendor' and product.
     * @param   string  $key   The key of the tiers to return.
     * @param   integer $id The user_id or post.
     * @return  array
     * @since   1.6.0
     * @version 1.6.0
     * @deprecated 1.8.6
     */
    public function get_tier( $value, $from = 'global', $key = 'vendor_sales', $id = 0 ) {

        _deprecated_function( 'get_tier', '1.8.6', 'wcv_commission_get_tier' );
        return wcv_commission_get_tier( $value, $from, $key, $id );
    }

    /**
     * Search an array using multiple values
     *
     * @param array $data The array to search.
     * @param array $pairs Array of values to look for.
     *
     * @return  array
     * @since   1.6.0
     * @version 1.6.0
     */
    public static function search_array( $data, $pairs ) {
        $found = array();
        foreach ( $data as $array_key => $array_value ) {
            $occurances = 0;
            foreach ( $pairs as $pair_key => $pair_val ) {
                if ( array_key_exists( $pair_key, $array_value ) && $array_value[ $pair_key ] === $pair_val ) {
                    ++$occurances;
                }
            }

            if ( count( $pairs ) === $occurances ) {
                $found[ $array_key ] = $array_value;
            }
        }

        return $found;
    }

    /**
     *  Save the commission detail for the post object (Product | Store)
     *
     * @param int $post_id post_id being saved.
     *
     * @since 1.0.0
     */
    public function save_commission_details( $post_id ) {
        if (
            ! isset( $_POST['save_commissions_nonce'] ) ||
            ! wp_verify_nonce(
                sanitize_text_field( wp_unslash( $_POST['save_commissions_nonce'] ) ),
                'save_commissions'
            ) ) {
            return;
        }

        if ( isset( $_POST['wcv_commission_type'] ) && '' !== $_POST['wcv_commission_type'] && 'product_sales' !== $_POST['wcv_commission_type'] ) {
            update_post_meta( $post_id, 'wcv_commission_type', $_POST['wcv_commission_type'] );

            // wcv_commission_percent.
            if ( isset( $_POST['wcv_commission_percent'] ) && '' !== $_POST['wcv_commission_percent'] ) {
                update_post_meta( $post_id, 'wcv_commission_percent', (float) $_POST['wcv_commission_percent'] );
            } else {
                delete_post_meta( $post_id, 'wcv_commission_percent' );
            }

            // wcv_commission_amount.
            if ( isset( $_POST['wcv_commission_amount'] ) && '' !== $_POST['wcv_commission_amount'] ) {
                update_post_meta( $post_id, 'wcv_commission_amount', (float) $_POST['wcv_commission_amount'] );
            } else {
                delete_post_meta( $post_id, 'wcv_commission_amount' );
            }

            // wcv_commission_fee.
            if ( isset( $_POST['wcv_commission_fee'] ) && '' !== $_POST['wcv_commission_fee'] ) {
                update_post_meta( $post_id, 'wcv_commission_fee', (float) $_POST['wcv_commission_fee'] );
            } else {
                delete_post_meta( $post_id, 'wcv_commission_fee' );
            }
        } else {
            delete_post_meta( $post_id, 'wcv_commission_type' );
            delete_post_meta( $post_id, 'wcv_commission_percent' );
            delete_post_meta( $post_id, 'wcv_commission_amount' );
            delete_post_meta( $post_id, 'wcv_commission_fee' );
        }

        $this->save_commission_tiers( 'product', $post_id );
    }

    /**
     * Save commission tiers for product, vendor or global settings
     *
     * @param   string  $save_where Where to save the data.
     * @param   integer $id         The post ID.
     *
     * @return  void
     * @since   1.6.0
     * @version 1.6.0
     */
    public function save_commission_tiers( $save_where = 'global', $id = 0 ) {

        if ( ! isset( $_POST['save_commission_tiers_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['save_commission_tiers_nonce'] ) ), 'save_commission_tiers' ) ) {
            return;
        }

        $commission_type_index = '';
        $tiers                 = array();
        switch ( $save_where ) {
            case 'global':
                $commission_type_index = 'wcvendors_commission_type';
                $tiers                 = get_option( 'wcv_global_commission_tiers', array() );
                break;
            case 'product':
                $commission_type_index = 'wcv_commission_type';
                $tiers                 = get_post_meta( $id, 'wcv_product_commission_tiers', true );
                break;
            case 'vendor':
                $commission_type_index = '_wcv_commission_type';
                $tiers                 = get_user_meta( $id, 'wcv_vendor_commission_tiers', true );
                break;
            default:
                $commission_type_index = 'wcvendors_commission_type';
                $tiers                 = get_option( 'wcv_global_commission_tiers', array() );
                break;
        }

        $commission_type = isset( $_POST[ $commission_type_index ] ) ? wc_clean( $_POST[ $commission_type_index ] ) : '';

        if ( '' === $commission_type ) {
            return;
        }

        if ( isset( $_POST['wcv_commission_tiers_names'] ) ) {
            $commission_tiers_names    = isset( $_POST['wcv_commission_tiers_names'] ) ? $_POST['wcv_commission_tiers_names'] : array();
            $commission_tiers_rules    = isset( $_POST['wcv_commission_tiers_rules'] ) ? $_POST['wcv_commission_tiers_rules'] : array();
            $commission_tiers_values   = isset( $_POST['wcv_commission_tiers_values'] ) ? $_POST['wcv_commission_tiers_values'] : array();
            $commission_tiers_types    = isset( $_POST['wcv_commission_tiers_types'] ) ? $_POST['wcv_commission_tiers_types'] : array();
            $commission_tiers_amounts  = isset( $_POST['wcv_commission_tiers_amounts'] ) ? $_POST['wcv_commission_tiers_amounts'] : array();
            $commission_tiers_percents = isset( $_POST['wcv_commission_tiers_percents'] ) ? $_POST['wcv_commission_tiers_percents'] : array();
            $commission_tiers_fees     = isset( $_POST['wcv_commission_tiers_fees'] ) ? $_POST['wcv_commission_tiers_fees'] : array();
            $tier_count                = count( $commission_tiers_names );
            $commission_type           = $_POST[ $commission_type_index ];
            $tier_rows                 = array();
            $tiers                     = (array) $tiers;
            for ( $i = 0; $i < $tier_count; $i++ ) {
                if ( '' === $commission_tiers_names[ $i ] ) {
                    continue;
                }

                $name    = array_key_exists( $i, $commission_tiers_names ) ? wc_clean( $commission_tiers_names[ $i ] ) : '';
                $rule    = array_key_exists( $i, $commission_tiers_rules ) ? wc_clean( $commission_tiers_rules[ $i ] ) : '';
                $value   = array_key_exists( $i, $commission_tiers_values ) ? wc_format_decimal( $commission_tiers_values[ $i ] ) : 0;
                $type    = array_key_exists( $i, $commission_tiers_types ) ? wc_clean( $commission_tiers_types[ $i ] ) : '';
                $amount  = array_key_exists( $i, $commission_tiers_amounts ) ? wc_format_decimal( $commission_tiers_amounts[ $i ] ) : 0;
                $percent = array_key_exists( $i, $commission_tiers_percents ) ? wc_format_decimal( $commission_tiers_percents[ $i ] ) : 0;
                $fee     = array_key_exists( $i, $commission_tiers_fees ) ? wc_format_decimal( $commission_tiers_fees[ $i ] ) : 0;

                $tier_rows[ $i ] = array(
                    'name'    => $name,
                    'rule'    => $rule,
                    'type'    => $type,
                    'value'   => $value,
                    'amount'  => $amount,
                    'percent' => $percent,
                    'fee'     => $fee,
                );
            }

            $tier_rows = apply_filters_deprecated(
                "wcv_{$save_where}_commission_tiers",
                array( $tier_rows ),
                '1.7.10',
                "wcvendors_{$save_where}_commission_tiers"
            );

            $tier_rows = apply_filters( "wcvendors_{$save_where}_commission_tiers", $tier_rows );

            if ( empty( $tier_rows ) ) {
                return;
            }

            $tiers[ $commission_type ] = $tier_rows;

            if ( 'global' === $save_where && 0 === $id ) {
                update_option( 'wcv_global_commission_tiers', $tiers );
            } elseif ( 'vendor' === $save_where && $id > 0 ) {
                update_user_meta( $id, 'wcv_vendor_commission_tiers', $tiers );
            } elseif ( 'product' === $save_where && $id > 0 ) {
                update_post_meta( $id, 'wcv_commission_type', $_POST['wcv_commission_type'] );
                update_post_meta( $id, 'wcv_product_commission_tiers', $tiers );
            }

            do_action( "after_save_{$save_where}_commission_tiers", $id, $tiers );
        } else {
            if ( isset( $tiers[ $commission_type ] ) ) {
                unset( $tiers[ $commission_type ] );
            }

            if ( 'global' === $save_where && 0 === $id ) {
                update_option( 'wcv_global_commission_tiers', $tiers );
            } elseif ( 'vendor' === $save_where && $id > 0 ) {
                update_user_meta( $id, 'wcv_vendor_commission_tiers', $tiers );
            } elseif ( 'product' === $save_where && $id > 0 ) {
                update_post_meta( $id, 'wcv_product_commission_tiers', $tiers );
            }

            do_action( "after_save_{$save_where}_commission_tiers", $id, $tiers );
        }
    }

    /**
     * Save commission tiers for global commission settings
     *
     * @return  void
     * @since   1.6.0
     * @version 1.6.0
     */
    public function save_commission_tiers_settings() {
        $this->save_commission_tiers( 'global' );
    }

    /**
     *  Disable the product commission tab enabled by free
     *
     * @since    1.0.0
     */
    public function update_product_meta() {
        return false;
    }

    /**
     *  Add the product commission tab
     *
     * @since    1.0.0
     */
    public function add_commission_tab() {

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            return;
        }

        include apply_filters( 'wcvendors_pro_add_commission_tab_path', 'partials/product/wcvendors-pro-product-meta-tab.php' );
    }

    /**
     * Add the panel to the product commission tab
     *
     * @since    1.0.0
     */
    public function add_commission_panel() {

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            return;
        }

        global $post;

        $commission_type    = get_post_meta( $post->ID, 'wcv_commission_type', true );
        $commission_percent = get_post_meta( $post->ID, 'wcv_commission_percent', true );
        $commission_amount  = get_post_meta( $post->ID, 'wcv_commission_amount', true );
        $commission_fee     = get_post_meta( $post->ID, 'wcv_commission_fee', true );

        include apply_filters( 'wcvendors_pro_add_commission_panel_path', 'partials/product/wcvendors-pro-commission-panel.php' );
    }

    /**
     * Add commission tiers to product commission panel
     *
     * @param WP_User $user The user object.
     *
     * @return  void
     * @since   1.6.0
     * @version 1.6.0
     */
    public function add_vendor_commission_tiers_panel( $user ) {

        $fields = array(
            array(
                'title'       => sprintf(
                    // translators: %s The name used to refer to vendor.
                    __( '%s Sales', 'wcvendors-pro' ),
                    wcv_get_vendor_name()
                ),
                'desc'        => sprintf(
                    // translators: %s The name used to refer to vendor.
                    __( 'Commissions based on %s sales', 'wcvendors-pro' ),
                    wcv_get_vendor_name()
                ),
                'id'          => 'wcvendors_commission_tier_vendor_sales',
                'key'         => 'vendor_sales',
                'value_label' => __( 'Sales', 'wcvendors-pro' ),
                'type'        => 'include',
                'file'        => WCV_PRO_ABSPATH_ADMIN . 'settings/partials/tiered-commissions.php',
            ),
            array(
                'title'       => __( 'Product Price', 'wcvendors-pro' ),
                'desc'        => __( 'Define the commission tiers based on the product price.', 'wcvendors-pro' ),
                'id'          => 'wcvendors_commission_tier_product_price',
                'type'        => 'include',
                'key'         => 'product_price',
                'value_label' => __( 'Price', 'wcvendors-pro' ),
                'file'        => WCV_PRO_ABSPATH_ADMIN . 'settings/partials/tiered-commissions.php',
            ),
            array(
                'title'       => __( 'Product Sales', 'wcvendors-pro' ),
                'desc'        => __( 'Commissions will be applied based on product sales.' ),
                'id'          => 'wcvendors_commission_tier_product_sales',
                'type'        => 'include',
                'key'         => 'product_sales',
                'value_label' => __( 'Sales', 'wcvendors-pro' ),
                'file'        => WCV_PRO_ABSPATH_ADMIN . 'settings/partials/tiered-commissions.php',
            ),
        );

        $fields = apply_filters( 'wcv_commission_tiers_panel_fields', $fields );

        foreach ( $fields as $field_details ) {
            $commission_tiers = self::get_commission_tiers( 'vendor', $field_details['key'], $user->ID );
            ?>
            <tr class="wcv_form_fields_table" id="<?php echo esc_attr( $field_details['id'] ); ?>">
                <td colspan="2">
                    <?php include WCV_PRO_ABSPATH_ADMIN . 'settings/partials/tiered-commissions.php'; ?>
                </td>
            </tr>
            <?php
        }
    }

    /**
     * Add commission tiers panel to product page.
     *
     * @return void
     * @version 1.0.0
     * @since   1.0.0
     */
    public function add_product_commission_tiers_panel() {
        global $post;

        $field_details    = array(
            'title'       => '',
            'desc'        => __( 'Commissions will be applied based on product sales.', 'wcvendors-pro' ),
            'id'          => 'wcvendors_commission_tier_product_sales',
            'type'        => 'include',
            'key'         => 'product_sales',
            'value_label' => __( 'Sales', 'wcvendors-pro' ),
            'file'        => WCV_PRO_ABSPATH_ADMIN . 'settings/partials/tiered-commissions.php',
        );
        $commission_tiers = self::get_commission_tiers( 'product', $field_details['key'], $post->ID );
        ?>
        <div class="wcv_form_fields_table" id="<?php echo esc_attr( $field_details['id'] ); ?>">
            <?php include WCV_PRO_ABSPATH_ADMIN . 'settings/partials/tiered-commissions.php'; ?>
        </div>
        <?php
    }

    /**
     * Save the data for the product
     *
     * @param    int $post_id post_id being saved.
     *
     * @since    1.0.0
     */
    public function save_commission_panel( $post_id ) {
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            return;
        }

        $this->save_commission_details( $post_id );
    }

    /**
     *  Add new commission interface to user edit screen
     *
     * @param WP_User $user The user object.
     *
     * @since    1.0.0
     */
    public function store_commission_meta_fields( $user ) {

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            return;
        }

        if ( ! WCV_Vendors::is_vendor( $user->ID ) ) {
            return;
        }

        // Get the default commission rate.
        $free_override_commission = get_user_meta( $user->ID, 'pv_custom_commission_rate', true );

        $commission_type    = get_user_meta( $user->ID, '_wcv_commission_type', true );
        $commission_percent = get_user_meta( $user->ID, '_wcv_commission_percent', true );
        $commission_amount  = get_user_meta( $user->ID, '_wcv_commission_amount', true );
        $commission_fee     = get_user_meta( $user->ID, '_wcv_commission_fee', true );

        include apply_filters( 'wcvendors_pro_store_commission_meta_fields_path', 'partials/vendor/wcvendors-pro-vendor-commission-fields.php' );
    }

    /**
     *  Save the store commission fields on the user edit screen.
     *
     * @param    int $vendor_id post_id being saved.
     *
     * @since    1.0.0
     */
    public function store_commission_meta_fields_save( $vendor_id ) {

        if (
            ! isset( $_POST['save_commissions_nonce'] ) ||
            ! wp_verify_nonce(
                sanitize_text_field( wp_unslash( $_POST['save_commissions_nonce'] ) ),
                'save_commissions'
            ) ) {
            return;
        }

        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            return;
        }

        if ( ! WCV_Vendors::is_vendor( $vendor_id ) ) {
            return;
        }

        if ( isset( $_POST['_wcv_commission_type'] ) && '' !== $_POST['_wcv_commission_type'] ) {

            update_user_meta( $vendor_id, '_wcv_commission_type', wc_clean( $_POST['_wcv_commission_type'] ) );

            // Save commission percentage.
            if ( isset( $_POST['_wcv_commission_percent'] ) && '' !== $_POST['_wcv_commission_percent'] ) {
                update_user_meta( $vendor_id, '_wcv_commission_percent', (float) $_POST['_wcv_commission_percent'] );
            } else {
                delete_user_meta( $vendor_id, '_wcv_commission_percent' );
            }

            // Commission fee.
            if ( isset( $_POST['_wcv_commission_fee'] ) && '' !== $_POST['_wcv_commission_fee'] ) {
                update_user_meta( $vendor_id, '_wcv_commission_fee', (float) $_POST['_wcv_commission_fee'] );
            } else {
                delete_user_meta( $vendor_id, '_wcv_commission_fee' );
            }

            // Commission amount.
            if ( isset( $_POST['_wcv_commission_amount'] ) && '' !== $_POST['_wcv_commission_amount'] ) {
                update_user_meta( $vendor_id, '_wcv_commission_amount', (float) $_POST['_wcv_commission_amount'] );
            } else {
                delete_user_meta( $vendor_id, '_wcv_commission_amount' );
            }
        } else {
            delete_user_meta( $vendor_id, '_wcv_commission_type' );
            delete_user_meta( $vendor_id, '_wcv_commission_percent' );
            delete_user_meta( $vendor_id, '_wcv_commission_amount' );
            delete_user_meta( $vendor_id, '_wcv_commission_fee' );
        }

        $this->save_commission_tiers( 'vendor', $vendor_id );
    }

    /**
     * Commission types
     *
     * @since    1.0.0
     */
    public static function commission_types() {
        return apply_filters(
            'wcv_commission_types',
            array(
                'fixed'       => __( 'Fixed', 'wcvendors-pro' ),
                'fixed_fee'   => __( 'Fixed + fee', 'wcvendors-pro' ),
                'percent'     => __( 'Percentage', 'wcvendors-pro' ),
                'percent_fee' => __( 'Percentage + fee', 'wcvendors-pro' ),
            )
        );
    }

    /**
     * Get the commission rules
     *
     * @return  array
     * @since   1.6.0
     * @version 1.6.0
     */
    public static function commission_rules() {
        $rules = apply_filters(
            'wcv_commission_rules',
            array(
                'less_than' => __( 'Less than', 'wcvendors-pro' ),
                'up_to'     => __( 'Up to', 'wcvendors-pro' ),
                'more_than' => __( 'More than', 'wcvendors-pro' ),
            )
        );

        return $rules;
    }

    /**
     * Get commission tiers
     *
     * @param   string  $from Where to get the commission from.
     * @param   string  $key  Return tiers for this commission type if given. Expected vendor_sales|product_sales|product_price.
     * @param   integer $id   The post id if product commissions.
     *
     * @return  array   $tiers
     * @since   1.6.0
     * @version 1.6.0
     */
    public static function get_commission_tiers( $from = 'global', $key = '', $id = 0 ) {

        $_tiers = array();
        $tiers  = array();
        if ( 'global' === $from ) {
            $_tiers = get_option( 'wcv_global_commission_tiers', array() );
        } elseif ( 'vendor' === $from && $id > 0 ) {
            $_tiers = get_user_meta( $id, 'wcv_vendor_commission_tiers', true );
        } elseif ( 'product' === $from && $id > 0 ) {
            $_tiers = get_post_meta( $id, 'wcv_product_commission_tiers', true );
        }

        if ( in_array(
            $key,
            array(
                'vendor_sales',
                'product_sales',
                'product_price',
            ),
            true
        ) && ! empty( $_tiers[ $key ] ) ) {
            $tiers = $_tiers[ $key ];
        }

        return apply_filters( "wcv_get_{$from}_commission_tiers", $tiers, $key, $id );
    }

    /**
     * Get shipping due for vendor shipping this uses the new package stored
     * vendor_costs in the order. No need for secondary calculations
     *
     * @since   1.4.0
     * @version 1.5.0
     *
     * @param array         $shipping_costs The shipping costs.
     * @param int           $order_id       The order id.
     * @param WC_Order_Item $order_item The order item.
     * @param int           $vendor_id The vendor ID.
     * @param int           $product_id The product ID.
     *
     * @return array $shipping_costs The calculated shipping costs.
     */
    public function get_shipping_due_from_order( $shipping_costs, $order_id, $order_item, $vendor_id, $product_id ) {
        $item_shipping_cost         = 0;
        $tax                        = 0;
        $taxable                    = $order_item->get_tax_status();
        $vendor_shipping_settings   = get_option( 'woocommerce_wcv_pro_vendor_shipping_settings', array() );
        $vendor_shipping_tax_status = isset( $vendor_shipping_settings['tax_status'] ) ? $vendor_shipping_settings['tax_status'] : 'none';
        $shipping_costs             = empty( $shipping_costs )
            ? array(
                'amount' => 0,
                'tax'    => 0,
            )
            : $shipping_costs;
        $order                      = new WC_Order( $order_id );

        $vendor_product = wc_get_product( $product_id );
        $tax_class      = $order_item->get_tax_class();

        if ( ! is_a( $vendor_product, 'WC_Product' ) || ! $vendor_product->needs_shipping() || $vendor_product->is_virtual() ) {
            return $shipping_costs;
        }

        $vendor_shipping_items = WCVendors_Pro_Shipping_Utils::get_shipping_items_for_vendor( $order, $vendor_id );

        if ( empty( $vendor_shipping_items ) ) {
            return $shipping_costs;
        }

        foreach ( $vendor_shipping_items as $shipping_item ) {
            if ( 'wcv_pro_vendor_shipping' === $shipping_item->get_method_id() ) {
                $item_shipping_cost = WCVendors_Pro_Shipping_Utils::get_vendor_shipping_cost( $shipping_item, $product_id );
                $tax                = ( wc_tax_enabled() && 'taxable' === $vendor_shipping_tax_status && (float) $item_shipping_cost > 0 ) ? WCV_Shipping::calculate_shipping_tax( $item_shipping_cost, $order, $tax_class ) : 0;
            } elseif ( 'flat_rate' === $shipping_item->get_method_id() ) {
                $shipping_meta_data = $shipping_item->get_meta_data();
                foreach ( $shipping_meta_data as $meta ) {
                    if ( 'extra_data' === $meta->key ) {
                        $extra_data    = $meta->value;
                        $order_item_id = $extra_data['line_item_id'];
                        if ( (int) $order_item_id === $order_item->get_id() ) {
                            $item_shipping_cost = WCVendors_Pro_Shipping_Utils::get_flat_rate_shipping_cost( $shipping_item, $vendor_shipping_items, $extra_data );
                            $tax                = ( 'taxable' === $taxable ) ? WCV_Shipping::calculate_shipping_tax( $item_shipping_cost, $order, $tax_class ) : 0;
                            break;
                        }
                    }
                }
            }
        }

        $shipping_costs['amount'] = $item_shipping_cost;
        $shipping_costs['tax']    = $tax;

        return $shipping_costs;
    }

    /**
     * Get_fee function from woocommerce
     *
     * @param mixed $fee The fee.
     * @param mixed $total The total.
     *
     * @return float
     */
    public function get_fee( $fee, $total ) {

        if ( strstr( $fee, '%' ) ) {
            $fee = ( $total / 100 ) * str_replace( '%', '', $fee );
        }

        return $fee;
    }

    /**
     * Import the commission overrides for vendors
     *
     * @since  1.3.6
     * @access public
     */
    public static function import_vendor_commission_overrides() {

        $all_vendor_ids = get_users(
            array(
                'role'   => 'vendor',
                'fields' => 'ID',
            )
        );

        if ( isset( $all_vendor_ids ) ) {

            foreach ( $all_vendor_ids as $vendor_id ) {

                $store_free_commission = get_user_meta( $vendor_id, 'pv_custom_commission_rate', true );

                // There is a free commission override. Import it into pro.
                if ( isset( $store_free_commission ) ) {
                    update_user_meta( $vendor_id, '_wcv_commission_type', 'percent' );
                    update_user_meta( $vendor_id, '_wcv_commission_percent', $store_free_commission );
                }
            }
            ?>
            <div class="updated inline">
                <p>
                <?php
                echo esc_html(
                    sprintf(
                        // translators: %s: name used to refer to vendor.
                        __( '%s commission overrides successfully imported.', 'wcvendors-pro' ),
                        wcv_get_vendor_name( true, true )
                    )
                );
                ?>
                </p>
            </div>
            <?php
        }
    }

    /**
     * Import the commission overrides for products
     *
     * @since  1.3.6
     * @access public
     */
    public static function import_product_commission_overrides() {

        $all_products = get_posts( array( 'post_type' => 'product' ) );

        if ( isset( $all_products ) ) {

            foreach ( $all_products as $product ) {

                $free_product_override_commission = get_post_meta( $product->ID, 'pv_commission_rate', true );

                if ( isset( $free_product_override_commission ) ) {
                    update_post_meta( $product->ID, 'wcv_commission_type', 'percent' );
                    update_post_meta( $product->ID, 'wcv_commission_percent', $free_product_override_commission );
                }
            }

            ?>
            <div class="updated inline">
                <p><?php esc_attr_e( 'Product commission overrides successfully imported.', 'wcvendors-pro' ); ?></p>
            </div>
            <?php
        }
    }

    /**
     * Add action to bulk calculate commissions on order list
     *
     * @param   array $actions Order actions.
     *
     * @return  array $actions Modified bulk actions
     * @since   1.6.0
     * @version 1.6.0
     */
    public function add_bulk_order_commissions_action( $actions ) {

        $actions['wcv_bulk_order_commissions'] = __( 'Recalculate Commissions', 'wcvendors-pro' );

        return $actions;
    }

    /**
     * Add action to calculate commissions on single order edit screen
     *
     * @param array $actions The order actions.
     *
     * @return array $actions The modified list of order actions.
     * @since
     * @version
     */
    public function add_order_commissions_action( $actions ) {

        $actions['wcv_order_commissions'] = __( 'Recalculate Commissions', 'wcvendors-pro' );

        return $actions;
    }

    /**
     * Calculate order commissions
     *
     * @param string $redirect_to The redirect URL.
     * @param string $action The action being taken.
     * @param array  $ids The order ids.
     *
     * @return  string $redirect_to The URL to redirect to after the action.
     * @since   1.8.8 - Added HPOS compatibility.
     * @since   1.6.0
     * @version 1.7.3
     */
    public function calculate_bulk_order_commissions( $redirect_to, $action, $ids ) {
        if ( 'wcv_bulk_order_commissions' !== $action ) {
            return $redirect_to;
        }

        if ( function_exists( 'set_time_limit' ) ) {
            set_time_limit( 0 );
        }

        $recalculate_order_statuses = apply_filters( 'wcv_recalculate_commission_complete_order_statuses', array( 'completed', 'processing' ) );

        $send_back_args = wcv_cot_enabled()
            ? array(
                'commissions_calculated' => 'commissions_calculated',
                'ids'                    => join( ',', $ids ),
                'error_count'            => 0,
            )
            : array(
                'post_type'              => 'shop_order',
                'commissions_calculated' => 'commissions_calculated',
                'ids'                    => join( ',', $ids ),
            );

        $changed = 0;

        foreach ( $ids as $order_id ) {
            $order = wc_get_order( $order_id );

            if ( ! in_array( $order->get_status(), $recalculate_order_statuses, true ) ) {
                continue;
            }

            $this->calculate_order_commissions( $order_id );
            ++$changed;

            do_action( 'wcv_order_commissions_calculated', $order );
        }

        do_action( 'wcv_bulk_order_commissions_calculated', $ids );

        $send_back_args['changed']          = $changed;
        $send_back_args['wcv_notice_nonce'] = wp_create_nonce( 'wcv_commissions_notice' );

        $redirect_to = add_query_arg( $send_back_args, $redirect_to );

        if ( wcv_cot_enabled() ) {
            wp_safe_redirect( esc_url_raw( $redirect_to ) );
            exit();
        }

        return esc_url_raw( $redirect_to );
    }

    /**
     * Calculate single order commissions
     *
     * @param int|array|WC_Order $order Order object/array or ID.
     *
     * @return  void
     * @since   1.6.0
     * @version 1.6.0
     */
    public function calculate_order_commissions( $order ) {

        if ( is_numeric( $order ) ) {
            $order = wc_get_order( $order );
        } elseif ( is_array( $order ) ) {
            $order = wc_get_order( $order['order_id'] );
        }

        foreach ( $order->get_items() as $item ) {
            /**
             * Represents a product item in a WooCommerce order.
             *
             * @var WC_Order_Item_Product $item
             */
            $give_tax          = 'yes' === get_option( 'wcvendors_vendor_give_taxes', 'no' ) ? true : false;
            $give_shipping     = 'yes' === get_option( 'wcvendors_vendor_give_shipping', 'no' ) ? true : false;
            $total_shipping    = 0;
            $total_tax         = 0;
            $shipping_costs    = array();
            $product_id        = ( $item->get_variation_id() ) ? $item->get_variation_id() : $item->get_product_id();
            $product_id_parent = wp_get_post_parent_id( $product_id );

            if ( ! $product_id ) {
                continue;
            }

            $product  = wc_get_product( $product_id );
            $order_id = $item->get_order_id();

            $qty = $item->get_quantity();

            $product_price = $item->get_total();
            $refund_amount = $order->get_total_refunded_for_item( $item->get_id() );
            $is_refunded   = false;
            if ( $refund_amount > 0 && $refund_amount <= $product_price ) {
                $product_price = $product_price - $refund_amount;
                $is_refunded   = true;
            }

            $vendor_id = get_post_field( 'post_author', $product_id );

            if ( $product_id_parent ) {
                $vendor_id = get_post_field( 'post_author', $product_id_parent );
            }

            $is_vendor = WCV_Vendors::is_vendor( $vendor_id );

            $commission = WCV_Commission::calculate_commission( $product_price, $product_id, $order, $qty, $item );
            $commission = is_numeric( $commission ) ? $this->process_commission( $commission, $product_id, $product_price, $order, $qty, $item ) : 0;
            $line_tax   = ! empty( $item['line_tax'] ) ? (float) $item['line_tax'] : 0;

            if ( 'no' === get_option( 'woocommerce_calc_shipping', 'no' ) || 'no' === get_option( 'woocommerce_enable_shipping_calc', 'no' ) ) {
                $shipping_amount = 0;
                $shipping_tax    = 0;
            } else {
                $shipping_costs  = $this->get_shipping_due_from_order( $shipping_costs, $order_id, $item, $vendor_id, $product_id );
                $shipping_amount = $shipping_costs['amount'];
                $shipping_tax    = $shipping_costs['tax'];
            }

            $total_tax = $product && ( $product->is_taxable() ) ? (float) $line_tax + (float) $shipping_tax : 0;

            if ( $is_vendor ) {

                $give_tax_override      = get_user_meta( $vendor_id, 'wcv_give_vendor_tax', true );
                $give_shipping_override = get_user_meta( $vendor_id, 'wcv_give_vendor_shipping', true );

                if ( $give_tax_override ) {
                    $give_tax = true;
                }
                if ( $give_shipping_override ) {
                    $give_shipping = true;
                }

                $total_shipping = $give_shipping ? $shipping_amount : 0;
                $total_tax      = $give_tax ? $total_tax : 0;
            }

            $data = array(
                'vendor_id'      => $vendor_id,
                'order_id'       => $item->get_order_id(),
                'product_id'     => $product_id,
                'total_due'      => $commission,
                'qty'            => $qty,
                'total_shipping' => $total_shipping,
                'tax'            => $total_tax,
                'time'           => date_i18n( 'Y-m-d H:i:s', strtotime( $order->get_date_created() ) ),
            );

            if ( $is_refunded ) {
                $data['status'] = 'reversed';
            }

            if ( $product_id && $vendor_id ) {
                $this->update_commission( $data );
            }

            do_action( 'wcv_order_commissions_calculated', $order );
        }
    }

    /**
     * Update/Insert commission
     *
     * @param array $data Commission data to update.
     *
     * @return  void
     * @since   1.6.0
     * @version 1.7.0
     */
    public function update_commission( $data ) {
        global $wpdb;
        $table = $wpdb->prefix . 'pv_commission';

        $where = array(
            'vendor_id'  => $data['vendor_id'],
            'order_id'   => $data['order_id'],
            'product_id' => $data['product_id'],
        );

        // Is the commission already paid?
        $count_paid     = WCV_Commission::check_commission_status( $where, 'paid' );
        $count_due      = WCV_Commission::check_commission_status( $where, 'due' );
        $count_reversed = WCV_Commission::check_commission_status( $where, 'reversed' );

        if ( 0 === $count_paid ) {
            $format = array( '%d', '%d', '%d', '%f', '%d', '%f', '%f', '%s', '%s' );
            $update = $wpdb->update( $table, $data, $where, $format );
            if ( ! $update && $count_due < 1 && $count_reversed < 1 ) {
                $insert = $wpdb->insert( $table, $data, $format );
            }
        }
    }

    /**
     * Add admin notice after calculating order commissions
     *
     * @return  void
     * @since   1.6.0
     * @version 1.6.0
     */
    public function commissions_calculated_notice() {
        global $pagenow, $post_type;

        if ( ! isset( $_REQUEST['wcv_notice_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_REQUEST['wcv_notice_nonce'] ), 'wcv_commissions_notice' ) ) {
            return;
        }

        $is_cpt_orders_page = ( 'edit.php' === $pagenow || 'post.php' === $pagenow ) && 'shop_order' === $post_type;
        $is_cot_orders_page = ( 'admin.php' === $pagenow && 'wc-orders' === $_REQUEST['page'] );

        // Bail if not on required page.
        if ( ( ! $is_cpt_orders_page && ! $is_cot_orders_page ) || ! isset( $_REQUEST['commissions_calculated'] ) ) {
            return;
        }

        $changed = isset( $_REQUEST['changed'] ) ? absint( wp_unslash( $_REQUEST['changed'] ) ) : 0;

        $message = sprintf(
            // translators: %s: number of orders.
            _n( 'Order commissions recalculated for %s order.', 'Commissions calculated for %s orders.', $changed, 'wcvendors-pro' ),
            number_format_i18n( $changed )
        );
        ?>
        <div class="updated">
            <p><?php echo esc_html( $message ); ?></p>
        </div>
        <?php
    }

    /**
     * Disable the free commission input on the users edit screen.
     *
     * @return bool
     */
    public function disable_free_commission_user() {
        return false;
    }

    /**
     * Update commission status after refund
     *
     * @param  int $order_id ID of order .
     * @return void
     * @version 1.8.0
     * @since 1.8.0
     */
    public function reversed_refunded_status( $order_id ) {
        global $wpdb;

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

        $order = wc_get_order( $order_id );

        if ( $order->get_parent_id() > 0 ) {
            return;
        }

        $order_refunds = $order->get_refunds();

        foreach ( $order_refunds as $refund ) {

            foreach ( $refund->get_items() as $item_id => $item ) {
                $product_id = $item->get_product_id();
                $vendor_id  = WCV_Vendors::get_vendor_from_product( $product_id );

                $where = array(
                    'order_id'   => esc_sql( $order_id ),
                    'product_id' => $product_id,
                    'vendor_id'  => $vendor_id,
                );

                $status = array(
                    'status' => __( 'reversed', 'wcvendors-pro' ),
                );

                $wpdb->update( $table, $status, $where );

            }
        }
        $this->calculate_order_commissions( $order_id );
    }

    /**
     * Update sub orders if parent order is refunded.
     *
     * @param array $order_id ID of parent order.
     * @return void
     * @version 1.8.8
     * @since   1.8.8
     */
    public function update_sub_order_refund_status( $order_id ) {
        $parent_order = wc_get_order( $order_id );

        if ( ! $parent_order ) {
            return;
        }

        $sub_orders = array_filter( (array) $parent_order->get_meta( 'wcv_sub_orders' ) );

        if ( empty( $sub_orders ) ) {
            return;
        }

        foreach ( $sub_orders as $vendor_order_id ) {
            $vendor_order = wcv_get_order( $vendor_order_id );

            if ( $this->is_vendor_order_refunded( $vendor_order ) ) {
                $vendor_order->set_status( 'refunded' );
                $vendor_order->save();
            }
        }
    }

    /**
     * Check if the vendor order is refunded.
     *
     * @param WC_Order_Vendor $vendor_order The vendor order.
     * @return boolean
     * @version 1.8.8
     * @since   1.8.8
     */
    public function is_vendor_order_refunded( $vendor_order ) {

        if ( ! $vendor_order ) {
            return false;
        }

        $parent_order = $vendor_order->get_parent_order();

        $total = $vendor_order->get_total();

        $refunded_amount = 0;

        if ( ! $parent_order ) {
            return false;
        }

        foreach ( $parent_order->get_items() as $item ) {
            $post_author = get_post_field( 'post_author', $item->get_product_id() );

            if ( (int) $post_author !== (int) $vendor_order->get_vendor_id() ) {
                continue;
            }
            $refunded_amount += $parent_order->get_total_refunded_for_item( $item->get_id() );
        }

        return $refunded_amount > 0 && $refunded_amount <= $total;
    }

    /**
     * Recursive parent category commission type if not set
     *
     * @param int $category_id ID of category.
     * @return array $commission_args
     *
     * @version 1.8.4
     * @since   1.8.4
     */
    public function recursive_fallback_commission( $category_id ) {
        $category        = get_term( $category_id, 'product_cat' );
        $commission_args = $this->category_commission_args( $category_id );

        if ( ! $commission_args['type'] || empty( $commission_args['type'] ) ) {
            $parent_id = $category->parent;
            if ( 0 !== $parent_id ) {
                $commission_args = $this->recursive_fallback_commission( $parent_id );
            }
        }

        return $commission_args;
    }

    /**
     * Get commission options for the category by its ID
     *
     * @param int $category_id The ID of the category to get commission for.
     * @return array
     * @version 1.8.4
     * @since   1.8.4
     */
    public function category_commission_args( $category_id ) {
        $commission_args = array(
            'type'    => '',
            'percent' => 0,
            'amount'  => 0,
            'fee'     => 0,
        );

        $commission_args['type']    = get_term_meta( $category_id, '_wcv_commission_type', true );
        $commission_args['percent'] = (float) get_term_meta( $category_id, '_wcv_commission_percent', true );
        $commission_args['amount']  = (float) get_term_meta( $category_id, '_wcv_commission_amount', true );
        $commission_args['fee']     = (float) get_term_meta( $category_id, '_wcv_commission_fee', true );

        return apply_filters( 'wcvendors_category_commission_args_' . $category_id, $commission_args, $category_id );
    }
}
