<?php

namespace GriffinForms\Frontend\Html\Forms\Traits;

/**
 * SecurityAccess Trait
 *
 * Handles form security and access control including:
 * - Bot limiting and anti-spam measures
 * - User access validation
 * - Role-based access control
 * - Form submission limits
 *
 * This trait provides a clean separation of concerns by extracting
 * security and access control logic from the main Form class.
 */
trait SecurityAccess
{
    /**
     * Initializes the bot limiter for anti-spam protection
     *
     * Sets up rate limiting and blacklist checking for form submissions
     * to prevent bot abuse and spam.
     */
    protected function setBotLimiter()
    {
        $this->bot_limiter = \GriffinForms\Frontend\Security\BotLimiter::getInstance();
        $this->bot_limiter->init($this->id);
    }

    /**
     * Initializes user action tracking
     *
     * Loads the user_action setting from form configuration for
     * tracking form interactions and submissions.
     */
    protected function setUserAction()
    {
        $this->user_action = $this->item->getProp('user_action');
    }

    /**
     * Checks if the current user has permission to access the form
     *
     * Validates access level settings:
     * - Public Access: Anyone can view and submit
     * - Registered Access: Only logged-in users
     * - Role-Based Access: Specific user roles only
     *
     * Sets $this->access_alert if access is denied with appropriate message.
     *
     * @return bool True if user has access, false otherwise
     */
    private function hasAccess()
    {
        $access_level = $this->item->getProp('access_level');

        // Public access - everyone allowed
        if (!isset($access_level['access']) or $access_level['access'] === 'public_access') {
            return true;
        }

        // Registered access - only logged-in users
        if ($access_level['access'] === 'registered_access') {

            // Check if user is logged in
            if (!is_user_logged_in()) {
                $this->access_alert = $this->alerts->loginToAccess();
                return false;
            }

            // Role-based access - only specific roles
            if ($access_level['role_access']) {

                // Validate that roles are configured
                if (!is_array($access_level['roles']) or empty($access_level['roles'])) {
                    $this->access_alert = $this->alerts->invalidRoleAccess();
                    return false;
                }

                // Check if user has one of the required roles
                $user = wp_get_current_user();
                $match = array_intersect($access_level['roles'], $user->roles);

                if (empty($match)) {
                    $this->access_alert = $this->alerts->invalidRoleAccess();
                    return false;
                } else {
                    return true;
                }
            } else {
                // Registered access granted, no role restriction
                return true;
            }
        }
    }

    /**
     * Check if the form is outside its availability window.
     *
     * @return string|null Message to show when closed, or null if available.
     */
    private function availabilityWindowMessage()
    {
        $window = $this->item->getProp('availability_window');
        if (!is_array($window) || empty($window['toggle'])) {
            return null;
        }

        $start_utc = isset($window['start_utc']) ? $window['start_utc'] : '';
        $end_utc = isset($window['end_utc']) ? $window['end_utc'] : '';
        $pre_message = isset($window['pre_message']) ? $window['pre_message'] : '';
        $post_message = isset($window['post_message']) ? $window['post_message'] : '';

        $default_pre = __('This form is not accepting submissions yet. Please check back later.', 'griffinforms-form-builder');
        $default_post = __('This form is no longer accepting submissions.', 'griffinforms-form-builder');

        $now = current_time('timestamp', true);

        if (!empty($start_utc)) {
            $start_ts = (new \DateTimeImmutable($start_utc, new \DateTimeZone('UTC')))->getTimestamp();
            if ($now < $start_ts) {
                return $pre_message !== '' ? $pre_message : $default_pre;
            }
        }

        if (!empty($end_utc)) {
            $end_ts = (new \DateTimeImmutable($end_utc, new \DateTimeZone('UTC')))->getTimestamp();
            if ($now > $end_ts) {
                return $post_message !== '' ? $post_message : $default_post;
            }
        }

        return null;
    }
}
