<?php
/**
 * Referral lifecycle service orchestrating side-effects when referrals change.
 *
 * @package RewardsWP
 */

namespace Awesomemotive\Rewardswp\Services;

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

use Awesomemotive\Rewardswp\Models\Referral;
use Awesomemotive\Rewardswp\Settings\Options\Points\EarnActionsOption;
use function Awesomemotive\Rewardswp\Helpers\get_member;
use function Awesomemotive\Rewardswp\Helpers\get_option_value;
use function Awesomemotive\Rewardswp\Helpers\count_referrals;

/**
 * Class ReferralLifecycleService
 *
 * Orchestrates referral lifecycle side-effects (points, etc.).
 *
 * @since 1.1.0
 */
class ReferralLifecycleService {

	/**
	 * Points service instance.
	 *
	 * @since 1.0.1
	 * @var PointsService
	 */
	private PointsService $points_service;

	/**
	 * Constructor.
	 *
	 * @since 1.0.1
	 *
	 * @param PointsService $points_service Points service instance.
	 */
	public function __construct( PointsService $points_service ) {
		$this->points_service = $points_service;
	}

	/**
	 * Handle referral completed lifecycle event.
	 *
	 * @since 1.1.0
	 *
	 * @param Referral $referral Referral instance.
	 *
	 * @return void
	 */
	public function on_referral_completed( Referral $referral ): void {
		if ( empty( $referral->id ) || empty( $referral->advocate_id ) ) {
			return;
		}

		// Award only once per referred friend (email or user_id).
		// If there's already another completed referral for the same friend, skip awarding.
		$unique_query = [];

		if ( ! empty( $referral->referred_email ) ) {
			$unique_query = [
				'referred_email' => $referral->referred_email,
				'status'         => 'completed',
			];
		} elseif ( ! empty( $referral->referred_user_id ) ) {
			$unique_query = [
				'referred_user_id' => (int) $referral->referred_user_id,
				'status'           => 'completed',
			];
		}

		if ( ! empty( $unique_query ) ) {
			$existing_completed = count_referrals( $unique_query );

			if ( is_int( $existing_completed ) && $existing_completed > 1 ) {
				return;
			}
		}

		$earn_actions = get_option_value( EarnActionsOption::class );
		$enabled      = ! empty( $earn_actions['referral']['enabled'] );
		$points       = isset( $earn_actions['referral']['points'] ) ? (int) $earn_actions['referral']['points'] : 0;

		if ( ! $enabled || $points <= 0 ) {
			return;
		}

		$member = get_member( (int) $referral->advocate_id );

		if ( is_null( $member ) ) {
			return;
		}

		$entry = [
			'member_id'   => (int) $member->id,
			'points'      => $points,
			'type'        => 'earned',
			'source_type' => 'referral',
			'source_id'   => (int) $referral->id,
			'status'      => 'approved',
			'note_public' => __( 'Points earned for a completed referral', 'rewardswp' ),
		];

		$this->points_service->create_points_entry( $entry );
	}
}
