<?php
/**
 * Reward types service for listing and resolving reward types.
 *
 * @package RewardsWP
 */

namespace Awesomemotive\Rewardswp\Services;

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

use Awesomemotive\Rewardswp\Factories\RewardTypesFactory;
use Awesomemotive\Rewardswp\Helpers\IconHelper;
use Awesomemotive\Rewardswp\Interfaces\IntegrationInterface;
use Awesomemotive\Rewardswp\Models\Reward;
use Awesomemotive\Rewardswp\Settings\Options\Points\PointsEnabledOption;
use Awesomemotive\Rewardswp\Settings\Options\Referrals\RewardsOption;
use DI\Container;
use DI\DependencyException;
use DI\NotFoundException;
use Exception;
use function Awesomemotive\Rewardswp\Helpers\get_option_value;

class RewardTypesService {
	/**
	 * Icon helper instance.
	 *
	 * @since 1.0.0
	 *
	 * @var IconHelper
	 */
	private IconHelper $icon_helper;

	/**
	 * Integration instance.
	 *
	 * @since 1.0.0
	 *
	 * @var IntegrationInterface
	 */
	private IntegrationInterface $integration;

	/**
	 * Reward types factory instance.
	 *
	 * @since 1.0.0
	 *
	 * @var RewardTypesFactory
	 */
	private RewardTypesFactory $reward_types_factory;

	/**
	 * DI container instance.
	 *
	 * @since 1.0.0
	 *
	 * @var Container
	 */
	private Container $container;

	/**
	 * The list of reward types supported.
	 *
	 * @since 1.0.0
	 *
	 * @var array|string[]
	 */
	private array $reward_types;

	/**
	 * Construct.
	 *
	 * @since 1.0.0
	 *
	 * @param IconHelper           $icon_helper
	 * @param IntegrationInterface $integration
	 * @param RewardTypesFactory   $reward_types_factory
	 * @param Container            $container
	 *
	 * @throws NotFoundException|DependencyException If fails to get resource from container.
	 */
	public function __construct(
		IconHelper $icon_helper,
		IntegrationInterface $integration,
		RewardTypesFactory $reward_types_factory,
		Container $container
	) {
		$this->icon_helper          = $icon_helper;
		$this->integration          = $integration;
		$this->reward_types_factory = $reward_types_factory;
		$this->container            = $container;
		$this->reward_types         = $container->get( 'reward_types_classes' );
	}

	/**
	 * Retrieve all available RewardTypes data.
	 *
	 * @since 1.0.0
	 *
	 * @return array[]
	 */
	public function get_reward_types_data(): array {
		$all_reward_types = [];

		foreach ( $this->reward_types as $reward_type_class ) {
			$reward_type = $this->reward_types_factory->get_reward_type( $reward_type_class );

			if ( is_null( $reward_type ) ) {
				continue;
			}

			$type = $reward_type->get_type();

			$all_reward_types[ $type ] = [
				'title'                  => $reward_type->get_admin_title(),
				'icon'                   => $this->icon_helper->get_icon( $reward_type->get_icon_name(), '' ),
				'defaults'               => $reward_type->get_defaults(),
				'advocate_title'         => $reward_type->get_admin_advocate_title(),
				'friend_title'           => $reward_type->get_admin_friend_title(),
				'available_for'          => $reward_type->available_for(),
				'feature_slug'           => 'redeem_' . $type,
				'points_program_enabled' => get_option_value( PointsEnabledOption::class ),
			];
		}

		return $all_reward_types;
	}

	/**
	 * Get the necessary data to display an example of the panel.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	public function get_mock_rewards(): array {
		$mock_rewards = [];

		foreach ( $this->reward_types as $reward_type_class ) {
			$reward_type = $this->reward_types_factory->get_reward_type( $reward_type_class );

			if ( is_null( $reward_type ) ) {
				continue;
			}

			if ( ! in_array( $this->integration->get_source(), $reward_type->available_for(), true ) ) {
				continue;
			}

			if ( ! in_array( $reward_type->get_type(), [ 'fixed_discount', 'percentage_discount', 'free_shipping' ], true ) ) {
				continue; // Only display the basic types for now.
			}

			try {
				$rewards             = get_option_value( RewardsOption::class );
				$values              = [
					$rewards['advocate']['reward_amount'] = empty( $reward_type->get_defaults()['reward_amount'] )
						? 5
						: $reward_type->get_defaults()['reward_amount'],
					$rewards['friend']['reward_amount']   = empty( $reward_type->get_defaults()['reward_amount'] )
						? 10
						: $reward_type->get_defaults()['reward_amount'],
				];
				$fake_reward         = $this->container->make( Reward::class );
				$fake_reward->amount = $values[ array_rand( $values ) ];

				$reward_type->set_reward( $fake_reward );
			} catch ( Exception $exception ) {
				$fake_reward = null;
			}

			$mock_rewards[] = [
				'icon_name'       => $reward_type->get_icon_name(),
				'reward_title'    => $reward_type->get_panel_title(),
				'reward_subtitle' => $reward_type->get_panel_subtitle(),
				'reward_content'  => [
					'discount_code_instructions' => $reward_type->get_panel_instructions(),
					'discount_code_notice'       => esc_html__( 'Reward expires today.', 'rewardswp' ),
					'discount_code_coupon'       => esc_html__( 'EXAMPLE_COUPON', 'rewardswp' ),
				],
			];
		}

		return $mock_rewards;
	}
}
