<?php
/**
 * Commission & Payment Functions
 *
 * Functions for commission calculation, referral management, payment processing,
 * and credit system operations. This includes calculating commissions for orders,
 * managing referral records, handling payments, and credit-based transactions.
 *
 * @since   3.0.0
 * @package WC_Affiliate
 */

use EasyCommerce\Models\Order;
use WC_Affiliate\Models\Affiliate;
use WC_Affiliate\Models\Commission;
use WC_Affiliate\Models\Referral;
use WC_Affiliate\Models\Transaction;

/**
 * Insert credit/referral record
 *
 * @since 2.0.0
 *
 * @param int    $affiliate_id   Affiliate ID.
 * @param float  $commission     Commission amount.
 * @param string $type           Referral type (default: 'sale').
 * @param int    $visit          Visit ID (default: 0).
 * @param int    $order_id       Order ID (default: 0).
 * @param array  $products       Products data (default: '').
 * @param float  $order_total    Order total (default: 0).
 * @param string $payment_status Payment status (default: 'pending').
 *
 * @return int|WP_Error Insert ID on success, false on failure
 */
function wca_insert_credit( int $affiliate_id, float $commission, string $type = 'sale', int $visit = 0, int $order_id = 0, array $products = array(), $order_total = 0, string $payment_status = 'pending' ) {
	$referral_model = new Referral();

	$referral_data = array(
		'affiliate'      => $affiliate_id,
		'type'           => $type,
		'visit'          => $visit,
		'order_id'       => $order_id,
		'products'       => $products,
		'order_total'    => $order_total,
		'commission'     => $commission,
		'payment_status' => $payment_status,
		'transaction_id' => 0,
		'time'           => time(),
	);

	$referral = $referral_model->create( $referral_data );
	if ( is_wp_error( $referral ) ) {
		return $referral;
	}

	// Trigger email action.
	do_action( 'wc_affiliate_add_credit', $affiliate_id, $order_id, $referral_data );

	return $referral->get_id();
}

/**
 * Get user credits (approved unpaid referral records)
 *
 * @since 2.16.0
 *
 * @param int $user_id User ID. Defaults to current user if not provided.
 *
 * @return array Array of approved referral records for the user.
 */
function wca_get_user_credits( int $user_id = 0 ): array {
	if ( ! $user_id ) {
		$user_id = get_current_user_id();
	}

	if ( ! $user_id ) {
		return array();
	}

	$referral_model = new Referral();

	return $referral_model->get_approved_referrals_for_affiliate( $user_id );
}

/**
 * Get referrals for current user
 *
 * @since 2.16.0
 *
 * @param int $from_timestamp Optional start timestamp.
 * @param int $to_timestamp   Optional end timestamp.
 *
 * @return array Array of referral data
 */
function wca_get_referrals( int $from_timestamp = 0, int $to_timestamp = 0 ): array {
	$referral_model = new Referral();

	$args = array(
		'affiliate_id' => get_current_user_id(),
		'limit'        => -1,
	);

	if ( $from_timestamp > 0 && $to_timestamp > 0 ) {
		$args['start_date'] = wp_date( 'Y-m-d', $from_timestamp );
		$args['end_date']   = wp_date( 'Y-m-d', $to_timestamp );
	}

	return $referral_model->get_referrals( $args );
}

/**
 * Get referral statuses
 *
 * @since 2.16.0
 *
 * @return array Array of referral status options
 */
function wca_get_referral_statuses(): array {
	$referral_model = new Referral();

	return $referral_model->get_available_statuses();
}

/**
 * Get transaction statuses
 *
 * @since 2.16.0
 *
 * @return array Array of transaction status options
 */
function wca_get_transactions_statuses(): array {
	$transaction_model = new Transaction();

	return $transaction_model->get_available_statuses();
}

/**
 * Calculate commission for WooCommerce order
 *
 * @since 2.16.0
 *
 * @param WC_Order $order        WooCommerce order object.
 * @param int      $affiliate_id Affiliate ID.
 *
 * @return array Commission calculation results.
 */
function wca_wc_calculate_commissions( WC_Order $order, int $affiliate_id ): array {
	$commission_model = new Commission();

	return $commission_model->calculate_for_wc_order( $order, $affiliate_id );
}

/**
 * Calculate commission for EasyCommerce order
 *
 * @since 2.16.0
 *
 * @param Order $order        EasyCommerce order object.
 * @param int   $affiliate_id Affiliate ID.
 *
 * @return array Commission calculation results.
 */
function wca_ec_calculate_commissions( Order $order, int $affiliate_id ): array {
	$commission_model = new Commission();

	return $commission_model->calculate_for_ec_order( $order, $affiliate_id );
}

/**
 * Get affiliate balance
 *
 * @since 2.16.0
 *
 * @param int $affiliate_id Affiliate ID.
 *
 * @return float Affiliate balance.
 */
function wca_get_affiliate_balance( int $affiliate_id ): float {
	$affiliate = new Affiliate( $affiliate_id );

	return $affiliate->get_balance();
}

/**
 * @param int $affiliate_id
 *
 * @return float
 */
function wca_get_affiliate_earnings( int $affiliate_id ): float {
	$affiliate = new Affiliate( $affiliate_id );

	return $affiliate->get_total_earnings();
}

/**
 * Get available payment methods options for affiliate payouts.
 *
 * @since 2.16.0
 *
 * @return array An array of payment methods with their identifiers as keys and their descriptions as values.
 */
function wca_get_payment_methods_options(): array {
	$defaults = array(
		'manual' => __( 'Manual', 'wc-affiliate' ),
	);

	return apply_filters( 'wc_affiliate_payout_methods', $defaults );
}

/**
 * Get active payment methods options for affiliate payouts.
 *
 * Returns only the payment methods that are enabled in the settings.
 *
 * @since 2.16.0
 *
 * @return array Array of active payment methods with identifiers as keys and descriptions as values.
 */
function wca_get_active_payment_methods_options(): array {
	$all_payment_methods    = wca_get_payment_methods_options();
	$active_payment_methods = wca_get_option( 'payout', 'general.payout_methods', array() );

	$payment_methods = array_filter(
		$all_payment_methods,
		function ( $label, $method ) use ( $active_payment_methods ) {
			return ! empty( $label ) && in_array( $method, $active_payment_methods, true );
		},
		ARRAY_FILTER_USE_BOTH
	);

	return apply_filters( 'wc_affiliate_active_payment_methods', $payment_methods );
}

/**
 * Get unpaid amount for a user
 *
 * @since 2.15.0
 *
 * @param int $user_id User ID.
 *
 * @return float Total unpaid amount.
 */
function wca_get_user_unpaid_amount( int $user_id ): float {
	$transaction_model = new Transaction();

	return $transaction_model->get_unpaid_amount( $user_id );
}

/**
 * Get payable affiliates
 *
 * @since 2.16.0
 *
 * @param string $affiliate Optional affiliate identifier filter.
 * @param string $from      Optional start date filter (YYYY-MM-DD format).
 * @param string $to        Optional end date filter (YYYY-MM-DD format).
 *
 * @return array Array of payable affiliates with their commission data.
 */
function wca_get_payable_affiliates( string $affiliate = '', string $from = '', string $to = '' ): array {
	$payout_amount = 0; // wc_affiliate_get_option( 'wc_affiliate_basic', 'payout_amount' );

	$referral_model = new Referral();

	return $referral_model->get_payable_affiliates_grouped( $affiliate, $from, $to, $payout_amount );
}

/**
 * Check if user can pay with credits
 *
 * @since 2.16.0
 *
 * @param int|string $user_id User ID or empty for current user.
 *
 * @return bool True if user is an active affiliate and can pay with credits.
 */
function wca_affiliate_can_pay_with_credit( $user_id = '' ): bool {
	return 'active' === wca_get_affiliate_status( $user_id );
}

/**
 * Get affiliate from WooCommerce order for credit
 *
 * @since 2.0.2
 *
 * @param WC_Order $order object.
 *
 * @return WP_User[]
 */
function wca_get_affiliate_for_credit_from_wc_order( WC_Order $order ): array {
	$users = apply_filters( 'wc_affiliates_wc_coupon_affiliates', array(), $order );
	if ( count( $users ) > 0 ) {
		return $users;
	}

	$user = wca_get_user_by_referral_token();
	if ( ! $user instanceof WP_User ) {
		return $users;
	}

	$users[] = $user;

	return apply_filters( 'wc_affiliates_user_affiliates_from_wc_order', $users, $order );
}

/**
 * Get affiliate from EasyCommerce order for credit
 *
 * @since 2.0.2
 *
 * @param Order $order object.
 *
 * @return WP_User[]
 */
function wca_get_affiliate_for_credit_from_ec_order( Order $order ): array {
	$users = apply_filters( 'wc_affiliates_ec_coupon_affiliates', array(), $order );
	if ( count( $users ) > 0 ) {
		return $users;
	}

	$user = wca_get_user_by_referral_token();
	if ( ! $user instanceof WP_User || ! $user->exists() ) {
		return $users;
	}

	$users[] = $user;

	return apply_filters( 'wc_affiliate_user_affiliates_from_ec_order', $users, $order );
}
