<?php

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

class Niwa_AI_Security_Service {

	const RATE_LIMIT_MAX     = Niwa_AI_Constants::RATE_LIMIT_MAX;
	const RATE_LIMIT_WINDOW  = Niwa_AI_Constants::RATE_LIMIT_WINDOW;

	/**
	 * Validate an email submission for spam / abuse.
	 *
	 * @return array { allowed: bool, reason: string }
	 */
	public static function validate_email_submission() {
		if ( self::is_honeypot_triggered() ) {
			return array(
				'allowed' => false,
				'reason'  => 'bot_detected',
			);
		}

		if ( self::is_admin_bypass() ) {
			return array(
				'allowed' => true,
				'reason'  => 'admin_bypass',
			);
		}

		if ( ! self::check_rate_limit() ) {
			return array(
				'allowed' => false,
				'reason'  => 'rate_limit_exceeded',
			);
		}

		return array(
			'allowed' => true,
			'reason'  => 'ok',
		);
	}

	/**
	 * Minimum seconds a human needs to fill out a form.
	 */
	const FORM_MIN_SECONDS = 2;

	/**
	 * Check if the honeypot field was filled (bot indicator)
	 * or the form was submitted too quickly (time-based check).
	 *
	 * @return bool
	 */
	public static function is_honeypot_triggered() {
		// phpcs:ignore WordPress.Security.NonceVerification.Missing
		$website = isset( $_POST['website'] ) ? sanitize_text_field( wp_unslash( $_POST['website'] ) ) : '';
		if ( '' !== $website ) {
			return true;
		}

		// Time-based bot detection: form submitted faster than a human can type.
		// phpcs:ignore WordPress.Security.NonceVerification.Missing
		$rendered_at = isset( $_POST['_niwa_t'] ) ? intval( $_POST['_niwa_t'] ) : 0;
		if ( $rendered_at > 0 ) {
			$elapsed = time() - $rendered_at;
			if ( $elapsed < self::FORM_MIN_SECONDS ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Check if current user is an admin (bypass rate limit).
	 *
	 * @return bool
	 */
	public static function is_admin_bypass() {
		return current_user_can( 'manage_options' );
	}

	/**
	 * Check whether the current IP is within rate limit.
	 *
	 * @return bool True if within limit, false if exceeded.
	 */
	public static function check_rate_limit() {
		$key     = 'niwa_ai_rate_' . md5( self::get_client_ip() );
		$current = (int) get_transient( $key );

		return $current < self::RATE_LIMIT_MAX;
	}

	/**
	 * Increment the rate limit counter for the current IP.
	 */
	public static function increment_rate_limit() {
		if ( self::is_admin_bypass() ) {
			return;
		}

		$key     = 'niwa_ai_rate_' . md5( self::get_client_ip() );
		$current = (int) get_transient( $key );

		set_transient( $key, $current + 1, self::RATE_LIMIT_WINDOW );
	}

	/**
	 * Get the real client IP address.
	 *
	 * Delegates to the shared implementation in Niwa_AI_Session_Utils to ensure
	 * consistent IP resolution across session fingerprinting and rate limiting.
	 *
	 * @return string
	 */
	public static function get_client_ip() {
		return Niwa_AI_Session_Utils::get_client_ip();
	}
}
