<?php
/**
 * Referral helper functions.
 *
 * @package Awesomemotive\Rewardswp\Helpers
 * @since 1.0.0
 */

namespace Awesomemotive\Rewardswp\Helpers;

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

use Awesomemotive\Rewardswp\Models\Referral;
use Awesomemotive\Rewardswp\Services\ReferralsService;
use Exception;
use WP_Error;

/**
 * Create a new referral.
 *
 * @param array $args The arguments for creating the referral.
 *
 * @return Referral|WP_Error The created referral object or a WP_Error on failure.
 */
function create_referral( array $args ) {
	$args = wp_parse_args(
		$args,
		[
			'advocate_id'      => 0,
			'event_id'         => 0,
			'referred_user_id' => null,
			'referred_email'   => '',
			'order_id'         => null,
			'status'           => 'pending',
			'type'             => '',
			'source'           => 'unknown',
			'created_at'       => get_current_time(),
			'converted_at'     => null,
		]
	);

	try {
		// Create a new referral object.
		$referral = am_rewardswp()->get_container()->make( Referral::class );

		// Populate the object.
		$referral->hydrate( $args );

		// Attempt to create the referral.
		$referral->create();

		/**
		 * Fires after a referral is created.
		 *
		 * @since 1.3.0
		 *
		 * @param Referral $referral The created referral.
		 */
		do_action( 'rewardswp_referral_created', $referral );

		return $referral;
	} catch ( Exception $e ) {
		return new WP_Error( 'general_error', $e->getMessage() );
	}
}

/**
 * Update a referral.
 *
 * @param int   $referral_id The referral ID to update.
 * @param array $args        The arguments for creating the referral.
 *
 * @return Referral|WP_Error The updated referral object or a WP_Error on failure.
 */
function update_referral( int $referral_id, array $args ) {
	$args = array_filter(
		wp_parse_args(
			$args,
			[
				'advocate_id'      => 0,
				'event_id'         => 0,
				'referred_user_id' => null,
				'referred_email'   => '',
				'order_id'         => null,
				'status'           => '',
				'type'             => '',
				'source'           => '',
				'converted_at'     => null,
			]
		)
	);

	try {
		// Create a new referral object.
		$referral = am_rewardswp()->get_container()->make( Referral::class );

		// Load the object.
		$referral->load( $referral_id );

		// Populate the object.
		$referral->hydrate( $args );

		// Attempt to create the referral.
		$referral->update();

		return $referral;
	} catch ( Exception $e ) {
		return new WP_Error( 'general_error', $e->getMessage() );
	}
}

/**
 * Return a referral by id.
 *
 * @since 1.0.0
 *
 * @param int $referral_id The referral ID.
 *
 * @return Referral|null
 */
function get_referral( int $referral_id ): ?Referral {
	try {
		$referral = am_rewardswp()->get_container()->make( Referral::class );

		$referral->load( $referral_id );

		return $referral;
	} catch ( Exception $e ) {
		return null;
	}
}

/**
 * Retrieve referrals based on the given parameters and pagination options.
 *
 * @since 1.0.0
 *
 * @param array $query_args An associative array of conditions to filter referrals.
 *                          See {@see ReferralsTable::get_columns()} for available parameters.
 * @param int   $per_page   Optional. The number of items per page for pagination. Defaults to 10.
 * @param int   $page       Optional. The page number for pagination. Defaults to 1.
 *
 * @return Referral[] Array of referrals.
 */
function get_referrals( array $query_args = [], int $per_page = 10, int $page = 1 ): array {
	try {
		$referrals_service = am_rewardswp()->get_container()->make( ReferralsService::class );
		return $referrals_service->get_referrals( $query_args, $per_page, $page );
	} catch ( Exception $e ) {
		return [];
	}
}

/**
 * Retrieve referrals count based on the given parameters and pagination options.
 *
 * @since 1.0.0
 *
 * @param array $query_args An associative array of conditions to filter referrals.
 *                          See {@see ReferralsTable::get_columns()} for available parameters.
 *
 * @return int.
 */
function count_referrals( array $query_args = [] ): ?int {
	try {
		$referrals_service = am_rewardswp()->get_container()->make( ReferralsService::class );
		return $referrals_service->count_referrals( $query_args );
	} catch ( Exception $e ) {
		return null;
	}
}

/**
 * Retrieve a list of referrals from a the current user IP address.
 *
 * @since 1.0.0
 *
 * @param int $per_page The number of items per page.
 * @param int $page     The page number.
 *
 * @return array
 */
function get_referrals_from_current_user_ip( int $per_page = 10, int $page = 1 ): array {
	try {
		$referrals_service = am_rewardswp()->get_container()->make( ReferralsService::class );

		return $referrals_service->get_referrals_from_ip(
			get_user_ip(),
			$per_page,
			$page
		);
	} catch ( Exception $e ) {
		return [];
	}
}

/**
 * Delete all referrals associated with a given member ID.
 *
 * @since 1.1.0
 *
 * @param int $member_id The ID of the member (advocate).
 * @return bool|int Number of rows deleted or false on error.
 */
function delete_referrals_by_member_id( int $member_id ) {
	try {
		/**
		 * Referrals service instance.
		 *
		 * @var ReferralsService $referrals_service
		 */
		$referrals_service = am_rewardswp()->get_container()->get( ReferralsService::class );
		return $referrals_service->delete_by_member_id( $member_id );
	} catch ( Exception $e ) {
		return false;
	}
}
