<?php
/**
 * Trait for centralizing security checks across the plugin.
 *
 * @package automation-web-platform
 */

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

trait WAWP_Security_Trait {

	/**
	 * Central permissions and nonce check.
	 *
	 * @param string $nonce_action Custom nonce action to check.
	 * @param string $nonce_field Field name in $_POST/$_REQUEST. Default 'nonce'.
	 */
	protected function check_permissions( $nonce_action = '', $nonce_field = 'nonce' ) {
		self::check_permissions_static( $nonce_action, $nonce_field );
	}

	/**
	 * Check nonce for frontend actions (allowing guests).
	 *
	 * @param string $nonce_action Custom nonce action.
	 * @param string $nonce_field Field name in $_POST/$_REQUEST.
	 */
	protected function check_frontend_nonce( $nonce_action = 'wawp_otp_nonce', $nonce_field = 'nonce' ) {
		self::check_frontend_nonce_static( $nonce_action, $nonce_field );
	}

	/**
	 * Static check for frontend nonce.
	 *
	 * @param string $nonce_action Custom nonce action.
	 * @param string $nonce_field  Field name in $_POST/$_REQUEST.
	 */
	public static function check_frontend_nonce_static( $nonce_action = 'wawp_otp_nonce', $nonce_field = 'nonce' ) {
		if ( ! check_ajax_referer( $nonce_action, $nonce_field, false ) ) {
			self::send_error( esc_html__( 'Invalid security token.', 'automation-web-platform' ), 403 );
		}
	}

	/**
	 * Static version for static handlers.
	 *
	 * @param string $nonce_action Custom nonce action.
	 * @param string $nonce_field  Field name in $_POST/$_REQUEST.
	 */
	public static function check_permissions_static( $nonce_action = 'wawp_nonce', $nonce_field = 'nonce' ) {
		// 1. Capability check.
		if ( ! current_user_can( WAWP_CAPABILITY ) && ! current_user_can( 'manage_options' ) ) {
			self::send_error( esc_html__( 'You do not have sufficient permissions to perform this action.', 'automation-web-platform' ), 403 );
		}

		// 2. Nonce verification.
		$verified = false;

		// A. Try explicit nonce fields from the request.
		$fields_to_try = array_unique( array( $nonce_field, 'nonce', 'security', '_wpnonce', '_ajax_nonce' ) );
		foreach ( $fields_to_try as $field ) {
			if ( isset( $_REQUEST[ $field ] ) && check_ajax_referer( $nonce_action, $field, false ) ) {
				$verified = true;
				break;
			}
		}

		// B. Try REST API Nonce (X-WP-Nonce).
		if ( ! $verified ) {
			$rest_nonce = isset( $_SERVER['HTTP_X_WP_NONCE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_WP_NONCE'] ) ) : '';
			if ( ! empty( $rest_nonce ) && wp_verify_nonce( $rest_nonce, 'wp_rest' ) ) {
				$verified = true;
			}
		}

		// C. Fallback: Trust authenticated JSON requests if current user is admin.
		if ( ! $verified ) {
			$is_rest = ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
						( function_exists( 'wp_is_json_request' ) && wp_is_json_request() );

			if ( $is_rest && get_current_user_id() > 0 ) {
				$verified = true;
			}
		}

		// Critical: Everyone must be verified to prevent CSRF.
		if ( ! $verified ) {
			self::send_error( esc_html__( 'Security check failed. Please refresh the page and try again.', 'automation-web-platform' ), 403 );
		}
	}

	/**
	 * Unified Success Response.
	 *
	 * @param string $message Success message.
	 * @param array  $data    Extra data.
	 */
	public static function send_success( $message = 'Success', $data = array() ) {
		$response = array( 'message' => $message );
		if ( ! empty( $data ) ) {
			$response = array_merge( $response, $data );
		}
		wp_send_json_success( $response );
	}

	/**
	 * Unified Error Response.
	 *
	 * @param string $message     Error message.
	 * @param int    $status_code HTTP status code.
	 * @param array  $data        Extra data.
	 */
	public static function send_error( $message = 'Error', $status_code = 400, $data = array() ) {
		$response = array( 'message' => $message );
		if ( ! empty( $data ) ) {
			$response = array_merge( $response, $data );
		}
		wp_send_json_error( $response, $status_code );
	}
	/**
	 * Get secure client IP address.
	 *
	 * @return string Sanitized IP address.
	 */
	public function get_client_ip() {
		$ip = '0.0.0.0';
		if ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) {
			$ip = sanitize_text_field( wp_unslash( $_SERVER['HTTP_CLIENT_IP'] ) );
		} elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
			$ip = sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) );
		} elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
			$ip = sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) );
		}

		// Handle comma separated list of IPs (proxies).
		if ( strpos( $ip, ',' ) !== false ) {
			$ip_parts = explode( ',', $ip );
			$ip       = trim( $ip_parts[0] );
		}

		return $ip;
	}
}
