<?php

namespace WC_Affiliate\Models;

defined( 'ABSPATH' ) || exit;

use EasyCommerce\Models\Order;
use WC_Affiliate\Traits\Validation;
use WC_Order;
use WC_Order_Item_Product;

/**
 * Class Commission
 *
 * Handles commission calculation for affiliate orders. This includes different commission types,
 * bases, exclusions, and product-specific settings.
 */
class Commission {


	use Validation;

	/**
	 * Commission types
	 */
	const TYPE_FIXED   = 'fixed';
	const TYPE_PERCENT = 'percent';

	/**
	 * Commission bases
	 */
	const BASE_ORDER_TOTAL   = 'order_total';
	const BASE_PRODUCT_PRICE = 'product_price';

	/**
	 * Calculate commission for an order
	 *
	 * @param WC_Order $order               WooCommerce order object.
	 * @param int      $affiliate_id        Affiliate ID.
	 * @param array    $commission_settings Commission settings.
	 *
	 * @return array {
	 *     Commission details including total, products, and breakdown.
	 *
	 * @type float      $total_commission    Total commission amount.
	 * @type array      $products            List of products in the order.
	 * @type array      $breakdown           Detailed breakdown of commission calculation.
	 *                                       }
	 */
	public static function calculate_for_wc_order( $order, int $affiliate_id, array $commission_settings = array() ): array {
		// Allow plugins to prevent commission calculation.
		$can_calculate = apply_filters( 'wc_affiliate_can_calculate_commission', true, $order, $affiliate_id );
		if ( ! $can_calculate ) {
			return apply_filters(
				'wc_affiliate_commission_result',
				array(
					'total_commission' => 0,
					'products'         => array(),
					'breakdown'        => array(),
				),
				$order,
				$affiliate_id,
				'',
				array()
			);
		}

		// Fire action before commission calculation.
		do_action( 'wc_affiliate_before_commission_calculation', $order, $affiliate_id );

		$affiliate       = new Affiliate( $affiliate_id );
		$commission_base = wca_get_commission_base();

		if ( empty( $commission_settings ) ) {
			$commission_settings = $affiliate->get_commission_settings();
		}

		// Allow filtering commission base before calculation.
		$commission_base = apply_filters( 'wc_affiliate_commission_base', $commission_base, $order, $affiliate_id );

		// Allow filtering commission settings.
		$commission_settings = apply_filters( 'wc_affiliate_commission_settings', $commission_settings, $order, $affiliate_id, $commission_base );

		if ( self::BASE_PRODUCT_PRICE === $commission_base ) {
			$result = self::calculate_by_wc_products( $order, $commission_settings );
		} else {
			$result = self::calculate_by_wc_order_total( $order, $commission_settings );
		}

		// Allow filtering final commission result.
		$result = apply_filters( 'wc_affiliate_commission_result', $result, $order, $affiliate_id, $commission_base, $commission_settings );

		// Fire action after commission calculation.
		do_action( 'wc_affiliate_after_commission_calculation', $result, $order, $affiliate_id, $commission_base, $commission_settings );

		return $result;
	}

	/**
	 * Calculate commission based on order total
	 *
	 * @param WC_Order $order               WooCommerce order object.
	 * @param array    $commission_settings {
	 *                                      Commission settings array.
	 *
	 * @type string     $type                Commission type ('fixed' or 'percent').
	 * @type float      $amount              Commission amount/rate.
	 *                                       }
	 *
	 * @return array {
	 *     Commission details including total, products, and breakdown.
	 *
	 * @type float      $total_commission    Total commission amount.
	 * @type array      $products            List of products in the order.
	 * @type array      $breakdown           Detailed breakdown of commission calculation.
	 *                                       }
	 */
	public static function calculate_by_wc_order_total( WC_Order $order, array $commission_settings ): array {
		$order_total = $order->get_total();
		$items       = $order->get_items();

		// Apply global exclusions.
		$excluded_amount        = self::get_excluded_amount_for_wc_order( $order );
		$commission_base_amount = $order_total - $excluded_amount;

		if ( $commission_base_amount <= 0 ) {
			return array(
				'total_commission' => 0,
				'products'         => array(),
				'breakdown'        => array(),
			);
		}

		$commission = self::calculate_commission_amount(
			$commission_base_amount,
			$commission_settings['type'],
			$commission_settings['amount']
		);

		// Allow filtering the calculated commission.
		$commission = apply_filters( 'wc_affiliate_calculated_commission', $commission, $order, $commission_base_amount, $commission_settings );

		// Get product list for reference.
		$products = array();
		foreach ( $items as $item ) {
			if ( ! $item instanceof WC_Order_Item_Product ) {
				continue;
			}

			$products[ $item->get_product_id() ] = $item->get_name();
		}

		return array(
			'total_commission' => $commission,
			'products'         => $products,
			'breakdown'        => array(
				'base_amount'        => $commission_base_amount,
				'commission_type'    => $commission_settings['type'],
				'commission_rate'    => $commission_settings['amount'],
				'excluded_amount'    => $excluded_amount,
				'calculation_method' => 'order_total',
			),
		);
	}

	/**
	 * Calculate commission based on individual products
	 *
	 * @param WC_Order $order                        WooCommerce order object.
	 * @param array    $default_commission_settings  {
	 *                                              Default commission settings array.
	 *
	 * @type string    $type                         Commission type ('fixed' or 'percent').
	 * @type float     $amount                       Commission amount/rate.
	 *                                               }
	 *
	 * @return array {
	 *     Commission details including total, products, and breakdown.
	 *
	 * @type float      $total_commission            Total commission amount.
	 * @type array      $products                    List of products with commissions.
	 * @type array      $breakdown                   Detailed breakdown by product.
	 *                                               }
	 */
	public static function calculate_by_wc_products( WC_Order $order, array $default_commission_settings ): array {
		$items = $order->get_items();

		$total_commission = 0;
		$products         = array();
		$breakdown        = array();

		foreach ( $items as $item ) {
			$product_id = $item->get_product_id();
			$line_total = $item->get_total();

			if ( ! $product_id || $line_total <= 0 ) {
				continue;
			}

			// Check if commission is disabled for this product.
			$affiliate_commission = get_post_meta( $product_id, 'affiliate_commission', true );
			if ( 'disabled' === $affiliate_commission ) {
				continue;
			}

			// Get product-specific commission settings.
			$commission_settings = self::get_product_commission_settings( $product_id, $default_commission_settings );

			// Calculate commission for this product.
			$product_commission = self::calculate_commission_amount(
				$line_total,
				$commission_settings['type'],
				$commission_settings['amount']
			);

			if ( $product_commission > 0 ) {
				$total_commission       += $product_commission;
				$products[ $product_id ] = $item->get_name();

				$breakdown[ $product_id ] = array(
					'product_name'      => $item->get_name(),
					'line_total'        => $line_total,
					'quantity'          => $item->get_quantity(),
					'commission_type'   => $commission_settings['type'],
					'commission_rate'   => $commission_settings['amount'],
					'commission_amount' => $product_commission,
				);
			}
		}

		return array(
			'total_commission' => $total_commission,
			'products'         => $products,
			'breakdown'        => $breakdown,
		);
	}

	/**
	 * Get product-specific commission settings
	 *
	 * @param int   $product_id       Product ID.
	 * @param array $default_settings Default commission settings array with 'type' and 'amount'.
	 *
	 * @return array Commission settings for the product
	 */
	public static function get_product_commission_settings( int $product_id, array $default_settings ): array {
		// Allow filtering product ID and default settings.
		$product_id       = apply_filters( 'wc_affiliate_product_commission_product_id', $product_id, $default_settings );
		$default_settings = apply_filters( 'wc_affiliate_product_commission_defaults', $default_settings, $product_id );

		$affiliate_commission = get_post_meta( $product_id, 'affiliate_commission', true );

		// Allow filtering whether product has custom commission.
		$has_custom_commission = apply_filters( 'wc_affiliate_product_has_custom_commission', 'custom' === $affiliate_commission, $product_id, $affiliate_commission );

		if ( $has_custom_commission ) {
			$commission_type   = get_post_meta( $product_id, 'commission_type', true );
			$commission_amount = get_post_meta( $product_id, 'commission_amount', true );

			if ( $commission_type && is_numeric( $commission_amount ) ) {
				$custom_settings = array(
					'type'   => $commission_type,
					'amount' => (float) $commission_amount,
				);

				// Allow filtering custom product commission settings.
				return apply_filters( 'wc_affiliate_product_custom_commission', $custom_settings, $product_id, $default_settings );
			}
		}

		// Allow filtering default product commission settings.
		return apply_filters( 'wc_affiliate_product_commission_settings', $default_settings, $product_id );
	}

	/**
	 * Calculate commission amount based on type and rate
	 *
	 * @param float  $base_amount The base amount to calculate commission on.
	 * @param string $type        Commission type ('fixed' or 'percent').
	 * @param float  $rate        Commission rate (fixed amount or percentage).
	 *
	 * @return float Calculated commission amount.
	 */
	public static function calculate_commission_amount( float $base_amount, string $type, float $rate ) {
		if ( $base_amount <= 0 || $rate <= 0 ) {
			return 0;
		}

		// Allow filtering commission calculation parameters.
		$args = apply_filters(
			'wc_affiliate_commission_calculation_args',
			array(
				'base_amount' => $base_amount,
				'type'        => $type,
				'rate'        => $rate,
			),
			$base_amount,
			$type,
			$rate
		);

		$base_amount = $args['base_amount'];
		$type        = $args['type'];
		$rate        = $args['rate'];

		$commission = 0;

		if ( self::TYPE_FIXED === $type ) {
			$commission = (float) $rate;
		} elseif ( self::TYPE_PERCENT === $type ) {
			$commission = ( $base_amount * $rate ) / 100;
		}

		// Allow filtering the commission amount calculation.
		return apply_filters( 'wc_affiliate_commission_amount', $commission, $base_amount, $type, $rate );
	}

	/**
	 * Get excluded amount from order (shipping, taxes, etc.)
	 *
	 * @param WC_Order $order WooCommerce order object.
	 *
	 * @return float Total excluded amount.
	 */
	public static function get_excluded_amount_for_wc_order( WC_Order $order ): float {
		$excluded_amount  = 0;
		$exclude_shipping = wca_should_exclude_shipping();
		$exclude_tax      = wca_should_exclude_tax();
		$exclude_fees     = wca_should_exclude_fees();

		// Allow filtering exclusion settings.
		$exclusion_settings = apply_filters(
			'wc_affiliate_exclusion_settings',
			array(
				'exclude_shipping' => $exclude_shipping,
				'exclude_tax'      => $exclude_tax,
				'exclude_fees'     => $exclude_fees,
			),
			$order
		);

		// Exclude shipping if configured.
		if ( $exclusion_settings['exclude_shipping'] ) {
			$shipping_total   = $order->get_shipping_total();
			$excluded_amount += (float) $shipping_total;
		}

		// Exclude taxes if configured.
		if ( $exclusion_settings['exclude_tax'] ) {
			$tax_total        = $order->get_total_tax();
			$excluded_amount += (float) $tax_total;
		}

		// Exclude fees if configured.
		if ( $exclusion_settings['exclude_fees'] ) {
			$fees = $order->get_fees();
			foreach ( $fees as $fee ) {
				$fee_total        = $fee->get_total();
				$excluded_amount += (float) $fee_total;
			}
		}

		// Allow filtering the final excluded amount.
		return apply_filters( 'wc_affiliate_excluded_amount', $excluded_amount, $order, $exclusion_settings );
	}

	/**
	 * Calculate commission for EasyCommerce order
	 *
	 * @param Order $order        EasyCommerce order object.
	 * @param int   $affiliate_id Affiliate ID.
	 *
	 * @return array Commission details including total, products, and breakdown.
	 */
	public function calculate_for_ec_order( Order $order, int $affiliate_id ): array {
		if ( ! $order instanceof Order ) {
			return array(
				'total_commission' => 0,
				'products'         => array(),
				'breakdown'        => array(),
			);
		}

		$affiliate           = new Affiliate( $affiliate_id );
		$commission_settings = $affiliate->get_commission_settings();
		$commission_base     = wca_get_commission_base();

		if ( self::BASE_PRODUCT_PRICE === $commission_base ) {
			$result = self::calculate_ec_by_products( $order, $commission_settings );
		} else {
			$result = self::calculate_ec_by_order_total( $order, $commission_settings );
		}

		return apply_filters( 'wc_affiliate_ec_commission_result', $result, $order, $affiliate_id, $commission_base, $commission_settings );
	}

	/**
	 * Calculate EasyCommerce commission by order total
	 *
	 * @param Order $order               EasyCommerce order object.
	 * @param array $commission_settings Commission settings array with 'type' and 'amount'.
	 *
	 * @return array Commission details including total, products, and breakdown.
	 */
	protected function calculate_ec_by_order_total( Order $order, array $commission_settings ): array {
		$order_total = $order->get_total();
		$items       = $order->get_items();

		// Apply exclusions (similar logic for EasyCommerce).
		$excluded_amount        = self::get_ec_excluded_amount( $order );
		$commission_base_amount = $order_total - $excluded_amount;

		if ( $commission_base_amount <= 0 ) {
			return array(
				'total_commission' => 0,
				'products'         => array(),
				'breakdown'        => array(),
			);
		}

		$commission = self::calculate_commission_amount(
			$commission_base_amount,
			$commission_settings['type'],
			$commission_settings['amount']
		);

		// Get product list.
		$products = array();
		if ( is_array( $items ) ) {
			foreach ( $items as $item ) {
				$product_id   = $item['product_id'] ?? 0;
				$product_name = $item['name'] ?? '';

				if ( $product_id && $product_name ) {
					$products[ $product_id ] = $product_name;
				}
			}
		}

		$result = array(
			'total_commission' => $commission,
			'products'         => $products,
			'breakdown'        => array(
				'base_amount'        => $commission_base_amount,
				'commission_type'    => $commission_settings['type'],
				'commission_rate'    => $commission_settings['amount'],
				'excluded_amount'    => $excluded_amount,
				'calculation_method' => 'order_total',
				'platform'           => 'easycommerce',
			),
		);

		return apply_filters( 'wc_affiliate_ec_commission_by_order_total', $result, $order, $commission_settings );
	}

	/**
	 * Calculate EasyCommerce commission by products
	 *
	 * @param Order $order                       EasyCommerce order object.
	 * @param array $default_commission_settings Default commission settings array with 'type' and 'amount'.
	 *
	 * @return array Commission details including total, products, and breakdown.
	 */
	protected function calculate_ec_by_products( Order $order, array $default_commission_settings ): array {
		$items = $order->get_items();

		$total_commission = 0;
		$products         = array();
		$breakdown        = array();

		if ( ! is_array( $items ) ) {
			return array(
				'total_commission' => 0,
				'products'         => array(),
				'breakdown'        => array(),
			);
		}

		foreach ( $items as $item ) {
			$product_id   = $item['product_id'] ?? 0;
			$product_name = $item['name'] ?? '';
			$line_total   = (float) ( $item['total'] ?? 0 );
			$quantity     = (int) ( $item['quantity'] ?? 1 );

			if ( ! $product_id || ! $product_name || $line_total <= 0 ) {
				continue;
			}

			// Check if commission is disabled.
			$affiliate_commission = get_post_meta( $product_id, 'affiliate_commission', true );
			if ( 'disabled' === $affiliate_commission ) {
				continue;
			}

			// Get product-specific settings.
			$commission_settings = self::get_product_commission_settings( $product_id, $default_commission_settings );

			// Calculate commission.
			$product_commission = self::calculate_commission_amount(
				$line_total,
				$commission_settings['type'],
				$commission_settings['amount']
			);

			if ( $product_commission > 0 ) {
				$total_commission       += $product_commission;
				$products[ $product_id ] = $product_name;

				$breakdown[ $product_id ] = array(
					'product_name'      => $product_name,
					'line_total'        => $line_total,
					'quantity'          => $quantity,
					'commission_type'   => $commission_settings['type'],
					'commission_rate'   => $commission_settings['amount'],
					'commission_amount' => $product_commission,
				);
			}
		}

		$result = array(
			'total_commission' => $total_commission,
			'products'         => $products,
			'breakdown'        => $breakdown,
		);

		return apply_filters( 'wc_affiliate_ec_commission_by_products', $result, $order, $default_commission_settings );
	}

	/**
	 * Get EasyCommerce excluded amounts
	 *
	 * @param Order $order EasyCommerce order object.
	 *
	 * @return float Total excluded amount.
	 */
	protected function get_ec_excluded_amount( Order $order ) {
		$excluded_amount = 0;

		// Exclude shipping.
		if ( wca_should_exclude_shipping() ) {
			$excluded_amount += (float) $order->get_shipping_total();
		}

		// Exclude taxes.
		if ( wca_should_exclude_tax() ) {
			$excluded_amount += (float) $order->get_tax_total();
		}

		return apply_filters( 'wc_affiliate_ec_excluded_amount', $excluded_amount, $order );
	}

	/**
	 * Calculate tiered commission
	 *
	 * @param int    $affiliate_id Affiliate ID.
	 * @param float  $base_amount  Base amount to calculate commission on.
	 * @param string $period       Period for performance evaluation ('monthly', 'yearly', etc.).
	 *
	 * @return float Calculated commission amount.
	 */
	public function calculate_tiered_commission( int $affiliate_id, float $base_amount, string $period = 'monthly' ) {
		$affiliate = new Affiliate( $affiliate_id );

		// Get affiliate's performance stats.
		$period_days = 'monthly' === $period ? 30 : ( 'yearly' === $period ? 365 : 90 );
		$stats       = $affiliate->get_period_statistics( $period_days );

		// Get tier settings.
		$tiers = wca_get_option( 'advanced', 'referral.commission_tiers', array() );

		// Allow filtering tier settings.
		$tiers = apply_filters( 'wc_affiliate_commission_tiers', $tiers, $affiliate_id, $period );

		if ( empty( $tiers ) ) {
			// No tiers configured, use default settings.
			$commission_settings = $affiliate->get_commission_settings();

			return self::calculate_commission_amount( $base_amount, $commission_settings['type'], $commission_settings['amount'] );
		}

		// Find applicable tier based on sales volume.
		$applicable_tier = null;
		$total_sales     = $stats['sales'];

		// Allow filtering sales volume used for tier calculation.
		$total_sales = apply_filters( 'wc_affiliate_tier_sales_volume', $total_sales, $affiliate_id, $period, $stats );

		foreach ( $tiers as $tier ) {
			if ( $total_sales >= $tier['min_sales'] ) {
				$applicable_tier = $tier;
			}
		}

		if ( ! $applicable_tier ) {
			// Use default if no tier matches.
			$commission_settings = $affiliate->get_commission_settings();

			return self::calculate_commission_amount( $base_amount, $commission_settings['type'], $commission_settings['amount'] );
		}

		// Allow filtering the applicable tier.
		$applicable_tier = apply_filters( 'wc_affiliate_applicable_tier', $applicable_tier, $affiliate_id, $total_sales, $tiers, $period );

		return self::calculate_commission_amount( $base_amount, $applicable_tier['type'], $applicable_tier['rate'] );
	}

	/**
	 * Calculate recurring commission for subscription
	 *
	 * @param mixed $subscription_order Subscription order object.
	 * @param int   $affiliate_id       Affiliate ID.
	 *
	 * @return float Recurring commission amount.
	 */
	public function calculate_recurring_commission( $subscription_order, int $affiliate_id ) {
		$recurring_rate   = wca_get_recurring_commission_rate(); // % of original
		$recurring_type   = wca_get_recurring_commission_type();
		$recurring_amount = wca_get_recurring_commission_amount();

		// Allow filtering recurring commission settings.
		$recurring_settings = apply_filters(
			'wc_affiliate_recurring_commission_settings',
			array(
				'rate'   => $recurring_rate,
				'type'   => $recurring_type,
				'amount' => $recurring_amount,
			),
			$subscription_order,
			$affiliate_id
		);

		$recurring_rate = $recurring_settings['rate'];
		$recurring_type = $recurring_settings['type'];

		if ( 'fixed' === $recurring_type ) {
			$recurring_amount = $recurring_settings['amount'];

			// Allow filtering fixed recurring amount.
			return apply_filters( 'wc_affiliate_recurring_commission_amount', (float) $recurring_amount, $subscription_order, $affiliate_id );
		} elseif ( 'percent' === $recurring_type ) {
			// Calculate original commission first.
			$original_commission = self::calculate_for_wc_order( $subscription_order, $affiliate_id );

			$calculated_amount = ( $original_commission['total_commission'] * $recurring_rate ) / 100;

			// Allow filtering percentage-based recurring amount.
			return apply_filters( 'wc_affiliate_recurring_commission_amount', $calculated_amount, $subscription_order, $affiliate_id, $original_commission, $recurring_rate );
		}

		return 0;
	}

	/**
	 * Calculate bonus commission for milestones
	 *
	 * @param int    $affiliate_id    Affiliate ID.
	 * @param string $milestone_type  Type of milestone ('sales', 'referrals', etc.).
	 * @param int    $milestone_value Value achieved for the milestone.
	 *
	 * @return float Bonus commission amount.
	 */
	public function calculate_bonus_commission( int $affiliate_id, string $milestone_type, int $milestone_value ) {
		$bonus_settings = wca_get_option( 'advanced', 'referral.bonus_commissions', array() );

		// Allow filtering bonus settings.
		$bonus_settings = apply_filters( 'wc_affiliate_bonus_commission_settings', $bonus_settings, $affiliate_id, $milestone_type );

		// If settings are already grouped by milestone type (legacy format).
		if ( isset( $bonus_settings[ $milestone_type ] ) && is_array( $bonus_settings[ $milestone_type ] ) ) {
			$bonuses = $bonus_settings[ $milestone_type ];
		} else {
			// Group settings by milestone type (current format from repeater field).
			$grouped_bonuses = array();
			foreach ( $bonus_settings as $bonus ) {
				if ( isset( $bonus['milestone_type'] ) && isset( $bonus['threshold'] ) && isset( $bonus['amount'] ) ) {
					$type = $bonus['milestone_type'];
					if ( ! isset( $grouped_bonuses[ $type ] ) ) {
						$grouped_bonuses[ $type ] = array();
					}
					$grouped_bonuses[ $type ][] = array(
						'threshold' => (int) $bonus['threshold'],
						'amount'    => (float) $bonus['amount'],
					);
				}
			}
			$bonuses = $grouped_bonuses[ $milestone_type ] ?? array();
		}

		// Allow filtering the processed bonuses for this milestone type.
		$bonuses = apply_filters( 'wc_affiliate_bonus_commissions', $bonuses, $affiliate_id, $milestone_type );

		if ( empty( $bonuses ) ) {
			return 0;
		}

		$applicable_bonus = 0;

		foreach ( $bonuses as $bonus ) {
			if ( $milestone_value >= $bonus['threshold'] ) {
				$applicable_bonus = $bonus['amount'];
			}
		}

		// Allow filtering the calculated bonus amount.
		return apply_filters( 'wc_affiliate_calculated_bonus_commission', (float) $applicable_bonus, $affiliate_id, $milestone_type, $milestone_value, $bonuses );
	}

	/**
	 * Get commission summary for period
	 *
	 * @param int    $affiliate_id Affiliate ID.
	 * @param string $start_date   Start date (Y-m-d).
	 * @param string $end_date     End date (Y-m-d).
	 *
	 * @return array Commission summary including total referrals, total commission, total sales, conversion value, average commission, paid referrals, paid commission, and payment rate.
	 */
	public function get_commission_summary( int $affiliate_id, string $start_date, string $end_date ): array {
		global $wpdb;

		$start_time = strtotime( $start_date . ' 00:00:00' );
		$end_time   = strtotime( $end_date . ' 23:59:59' );

		$query = "SELECT 
					COUNT(*) as total_referrals,
					SUM(commission) as total_commission,
					SUM(order_total) as total_sales,
					AVG(commission) as avg_commission,
					COUNT(CASE WHEN payment_status = 'paid' THEN 1 END) as paid_referrals,
					SUM(IF(payment_status = 'paid', commission, 0)) as paid_commission
				  FROM {$wpdb->prefix}wca_referrals 
				  WHERE affiliate = %d AND time BETWEEN %d AND %d";

		$summary = $wpdb->get_row( $wpdb->prepare( $query, $affiliate_id, $start_time, $end_time ), ARRAY_A );

		// Calculate rates and percentages.
		$summary['conversion_value'] = $summary['total_sales'] > 0 ?
			( $summary['total_commission'] / $summary['total_sales'] ) * 100 : 0;

		$summary['payment_rate'] = $summary['total_referrals'] > 0 ?
			( $summary['paid_referrals'] / $summary['total_referrals'] ) * 100 : 0;

		return apply_filters( 'wc_affiliate_commission_summary', $summary, $affiliate_id, $start_date, $end_date );
	}

	/**
	 * Validate commission settings
	 *
	 * @param array $settings Commission settings array with 'type' and 'amount'.
	 *
	 * @return true|array True if valid, array of error messages if invalid.
	 */
	public function validate_commission_settings( array $settings ) {
		$errors = array();

		if ( empty( $settings['type'] ) || ! in_array(
			$settings['type'],
			array(
				self::TYPE_FIXED,
				self::TYPE_PERCENT,
			),
			true
		) ) {
			$errors[] = __( 'Invalid commission type', 'wc-affiliate' );
		}

		if ( ! isset( $settings['amount'] ) || ! is_numeric( $settings['amount'] ) || $settings['amount'] < 0 ) {
			$errors[] = __( 'Commission amount must be a positive number', 'wc-affiliate' );
		}

		if ( self::TYPE_PERCENT === $settings['type'] && $settings['amount'] > 100 ) {
			$errors[] = __( 'Percentage commission cannot exceed 100%', 'wc-affiliate' );
		}

		return apply_filters( 'wc_affiliate_validate_commission_settings', empty( $errors ) ? true : $errors, $settings );
	}

	/**
	 * Get commission types
	 */
	public function get_commission_types(): array {
		$types = array(
			self::TYPE_FIXED   => __( 'Fixed Amount', 'wc-affiliate' ),
			self::TYPE_PERCENT => __( 'Percentage', 'wc-affiliate' ),
		);

		return apply_filters( 'wc_affiliate_commission_types', $types );
	}

	/**
	 * Get commission bases
	 */
	protected function get_commission_bases(): array {
		$bases = array(
			self::BASE_ORDER_TOTAL   => __( 'Order Total', 'wc-affiliate' ),
			self::BASE_PRODUCT_PRICE => __( 'Product Price', 'wc-affiliate' ),
		);

		return apply_filters( 'wc_affiliate_commission_bases', $bases );
	}

	/**
	 * Format commission for display
	 *
	 * @param string $type   Commission type ('fixed' or 'percent').
	 * @param float  $amount Commission amount.
	 *
	 * @return string Formatted commission string.
	 */
	public function format_commission_rate( string $type, float $amount ): string {
		if ( self::TYPE_FIXED === $type ) {
			return wca_format_price( $amount );
		} elseif ( self::TYPE_PERCENT === $type ) {
			return number_format( $amount, 2 ) . '%';
		}

		return '';
	}

	/**
	 * Calculate projected commission
	 *
	 * @param int   $affiliate_id Affiliate ID.
	 * @param float $cart_total   Cart total amount.
	 *
	 * @return float Projected commission amount.
	 */
	public function calculate_projected_commission( int $affiliate_id, float $cart_total ) {
		$affiliate           = new Affiliate( $affiliate_id );
		$commission_settings = $affiliate->get_commission_settings();

		return self::calculate_commission_amount(
			$cart_total,
			$commission_settings['type'],
			$commission_settings['amount']
		);
	}

	/**
	 * Get commission breakdown for display
	 *
	 * @param array $breakdown Commission breakdown array.
	 *
	 * @return string Formatted breakdown string.
	 */
	public function get_commission_breakdown_display( array $breakdown ): string {
		if ( empty( $breakdown ) ) {
			return '';
		}

		$display = '';

		if ( 'order_total' === $breakdown['calculation_method'] ) {
			// translators: 1: Calculation method (Order Total or Product-based).
			$display .= sprintf( __( 'Base Amount: %s', 'wc-affiliate' ), wca_format_price( $breakdown['base_amount'] ) ) . '<br>';

			// translators: 1: Calculation method (Order Total or Product-based).
			$display .= sprintf( __( 'Commission Rate: %s', 'wc-affiliate' ), $this->format_commission_rate( $breakdown['commission_type'], $breakdown['commission_rate'] ) ) . '<br>';

			if ( $breakdown['excluded_amount'] > 0 ) {
				// translators: 1: Excluded amount (shipping, tax, fees).
				$display .= sprintf( __( 'Excluded Amount: %s', 'wc-affiliate' ), wca_format_price( $breakdown['excluded_amount'] ) ) . '<br>';
			}
		} else {
			$display .= __( 'Product-based Commission:', 'wc-affiliate' ) . '<br>';

			foreach ( $breakdown as $product_id => $product_breakdown ) {
				if ( ! is_array( $product_breakdown ) ) {
					continue;
				}

				$display .= sprintf(
					'• %s: %s (%s)',
					esc_html( $product_breakdown['product_name'] ),
					wca_format_price( $product_breakdown['commission_amount'] ),
					$this->format_commission_rate( $product_breakdown['commission_type'], $product_breakdown['commission_rate'] )
				) . '<br>';
			}
		}

		return $display;
	}
}
