<?php

namespace CouponsPlus\App\Conditions\BuiltIn\Conditions;

use CouponsPlus\App\Conditions\Condition;
use CouponsPlus\Original\Collections\Collection;
use CouponsPlus\Original\Characters\StringManager;
use Automattic\WooCommerce\Utilities\DiscountsUtil;
use CouponsPlus\Original\Collections\Mapper\Types;

#[\AllowDynamicProperties]
Class UserEmail extends Condition
{
    const TYPE = 'UserEmail';

    static public function getName() : string
    {
        return __('User Emails', 'coupons-plus-for-woocommerce');
    }

    static public function getDescription() : string
    {
        return '';
    }

    static public function getUseCases(): Collection
    {
        return new Collection([
                              ]);
    }

    // desc:
    // USER MUST BE LOGGED IN (AKA HAVE AN ACCOUNT) FOR THESE CHECKS TO WORK,
    // IF THE USER IS NOT LOGGED IN (AKA A SIMPLE GUEST/VISITOR), THIS CONDITION WILL ALWAYS FAIL REGARDLESS OF
    // THE OPTIONS SET.
    public static function getOptions() : Collection
    {
        return new Collection([
              'inclusionType' => Types::STRING()->allowed([
                      __('Eligible', 'coupons-plus-for-woocommerce') => 'allowed',
                      __('Not Eligible', 'coupons-plus-for-woocommerce') => 'forbidden'
              ])->withDefault('allowed'),
			'lists' => [
				'addresses' => Types::COLLECTION(), // /n separated
            	'regexes' => Types::COLLECTION(),
            	'domains' => Types::COLLECTION(),
			]
        ]);
    }

    protected function test() : bool
    {
		(array) $currentUserEmailsToCheck = [];

		(object) $user = wp_get_current_user();

		if ($user->ID) {
			$currentUserEmailsToCheck[] = $user->user_email;
		}

		if (WC()->customer instanceof \WC_Customer) {
			$currentUserEmailsToCheck[] = WC()->customer->get_billing_email();
		}

		$currentUserEmailsToCheck = array_unique(
			array_filter(
				array_map('strtolower', array_map('sanitize_email', $currentUserEmailsToCheck))
			)
		);

		if (empty($currentUserEmailsToCheck)) {
			return false;
		}

		(bool) $matchFound = $this->emailMatchesAnyList($currentUserEmailsToCheck);

		return $this->options->inclusionType->is('allowed') ? $matchFound : !$matchFound;
    }

	protected function emailMatchesAnyList(array $emails): bool
	{
		return $this->emailMatchesAddresses($emails)
			|| $this->emailMatchesRegexes($emails)
			|| $this->emailMatchesDomains($emails);
	}

	/**
	 * Check if any email matches the addresses list.
	 * Uses WooCommerce's DiscountsUtil::is_coupon_emails_allowed for wildcard matching.
	 */
	protected function emailMatchesAddresses(array $emails): bool
	{
		(array) $restrictions = array_filter(
			array_map(
				function ($address) {
					return strtolower(trim($address));
				},
				$this->options->lists->addresses->asArray()
			)
		);

		if (empty($restrictions)) {
			return false;
		}

		return DiscountsUtil::is_coupon_emails_allowed($emails, $restrictions);
	}

	/**
	 * Check if any email matches the regexes list.
	 */
	protected function emailMatchesRegexes(array $emails): bool
	{
		foreach ($this->options->lists->regexes->asArray() as $regex) {
			(string) $regex = trim($regex);

			if (empty($regex)) {
				continue;
			}

			foreach ($emails as $email) {
				if (preg_match($regex, $email)) {
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * Check if any email matches the domains list.
	 */
	protected function emailMatchesDomains(array $emails): bool
	{
        /** @var Collection $domains */
        $domains = $this->options->lists->domains->map('strtolower')->map('trim')->filter();

		if (!$domains->haveAny()) {
			return false;
		}

		foreach ($emails as $email) {
            $email = new StringManager($email);

			foreach ($domains->asArray() as $domain) {
				$pattern = '/@' . preg_quote($domain, '/') . '$/';

				if ($email->matches($pattern)) {
					return true;
				}
			}
		}

		return false;
	}
}
