<?php

namespace GriffinForms\Frontend\Security\FieldValidations;

/**
 * Class InputEmail
 * Handles validation for email input fields in GriffinForms.
 */
class InputEmail extends Format
{
    /**
     * Custom validation for input email fields.
     *
     * @param string $value The user-inputted email address.
     */
    protected function customValidate($value, $iteration_index)
    {
        $validations = $this->field->getProp('validations');
        if (!$validations) return;
    
        // Email format validation
        if (!$this->validateEmailFormat($value)) {
            return; // Stop further checks if format is invalid
        }
    
        // Apply additional validations
        if (!empty($validations['restricted_domains'])) {
            $this->validateRestrictedDomains($value, $validations['restricted_domains']);
        }
        if (!empty($validations['excluded_domains'])) {
            $this->validateExcludedDomains($value, $validations['excluded_domains']);
        }
        if (!empty($validations['pattern'])) {
            $this->validatePattern($value, $validations['pattern']);
        }
    }

    /**
     * Validates the email format.
     *
     * @param string $value The email to validate.
     * @return bool Returns true if valid, false otherwise.
     */
    private function validateEmailFormat($value)
    {
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
            $this->addError(__('Please enter a valid email address.', 'griffinforms-form-builder'));
            return false;
        }
        return true;
    }

    /**
     * Extracts the domain from an email address.
     *
     * @param string $value The email address.
     * @return string The extracted domain or an empty string if invalid.
     */
    private function extractEmailDomain($value)
    {
        $parts = explode('@', $value);
        return count($parts) === 2 ? strtolower(trim($parts[1])) : '';
    }

    /**
     * Validates that the email belongs to a restricted (allowed) domain.
     *
     * @param string $value The email address.
     * @param mixed $domains Allowed domains as a string (comma-separated) or an array.
     */
    private function validateRestrictedDomains($value, $domains)
    {
        $email_domain = $this->extractEmailDomain($value);
        $domains_array = is_array($domains) ? $domains : array_map('trim', explode(',', $domains));

        if (!in_array($email_domain, $domains_array)) {
            /* translators: %s is a comma-separated list of allowed email domains */
            $this->addError(sprintf(__('Email domain must be one of the following: %s', 'griffinforms-form-builder'), implode(', ', $domains_array)));
        }
    }

    /**
     * Validates that the email does not belong to an excluded domain.
     *
     * @param string $value The email address.
     * @param mixed $domains Forbidden domains as a string or an array.
     */
    private function validateExcludedDomains($value, $domains)
    {
        $email_domain = $this->extractEmailDomain($value);
        $domains_array = is_array($domains) ? $domains : array_map('trim', explode(',', $domains));

        if (in_array($email_domain, $domains_array)) {
            /* translators: %s is a comma-separated list of disallowed email domains */
            $this->addError(sprintf(__('Email domain cannot be one of the following: %s', 'griffinforms-form-builder'), implode(', ', $domains_array)));
        }
    }
}