<?php
/**
 * Tests for HVAC_Security class
 *
 * @package HVAC_Community_Events
 * @subpackage Tests
 */

/**
 * Class HVAC_Security_Test
 */
class HVAC_Security_Test extends WP_UnitTestCase {

	/**
	 * Setup test
	 */
	public function setUp(): void {
		parent::setUp();
		wp_set_current_user( 0 ); // Start with no user
	}

	/**
	 * Test nonce verification
	 */
	public function test_verify_nonce() {
		$action = 'test_action';
		$nonce = wp_create_nonce( $action );
		
		// Test valid nonce
		$result = HVAC_Security::verify_nonce( $nonce, $action );
		$this->assertTrue( $result );
		
		// Test invalid nonce
		$result = HVAC_Security::verify_nonce( 'invalid_nonce', $action );
		$this->assertFalse( $result );
		
		// Test with die_on_fail
		$this->expectException( 'WPDieException' );
		HVAC_Security::verify_nonce( 'invalid_nonce', $action, true );
	}

	/**
	 * Test capability check
	 */
	public function test_check_capability() {
		// Create test user with specific capability
		$user_id = $this->factory->user->create( array(
			'role' => 'administrator',
		) );
		wp_set_current_user( $user_id );
		
		// Test valid capability
		$result = HVAC_Security::check_capability( 'manage_options' );
		$this->assertTrue( $result );
		
		// Test invalid capability
		$result = HVAC_Security::check_capability( 'non_existent_capability' );
		$this->assertFalse( $result );
		
		// Test with die_on_fail
		$this->expectException( 'WPDieException' );
		HVAC_Security::check_capability( 'non_existent_capability', true );
	}

	/**
	 * Test login requirement
	 */
	public function test_require_login() {
		// Test when not logged in
		wp_set_current_user( 0 );
		$result = HVAC_Security::require_login();
		$this->assertFalse( $result );
		
		// Test when logged in
		$user_id = $this->factory->user->create();
		wp_set_current_user( $user_id );
		$result = HVAC_Security::require_login();
		$this->assertTrue( $result );
	}

	/**
	 * Test email sanitization
	 */
	public function test_sanitize_email() {
		// Valid email
		$email = HVAC_Security::sanitize_email( 'test@example.com' );
		$this->assertEquals( 'test@example.com', $email );
		
		// Invalid email
		$email = HVAC_Security::sanitize_email( 'invalid-email' );
		$this->assertFalse( $email );
		
		// Email with spaces
		$email = HVAC_Security::sanitize_email( ' test@example.com ' );
		$this->assertEquals( 'test@example.com', $email );
		
		// XSS attempt
		$email = HVAC_Security::sanitize_email( '<script>alert("xss")</script>test@example.com' );
		$this->assertFalse( $email );
	}

	/**
	 * Test URL sanitization
	 */
	public function test_sanitize_url() {
		// Valid URL
		$url = HVAC_Security::sanitize_url( 'https://example.com/path' );
		$this->assertEquals( 'https://example.com/path', $url );
		
		// Invalid URL
		$url = HVAC_Security::sanitize_url( 'not a url' );
		$this->assertFalse( $url );
		
		// JavaScript URL
		$url = HVAC_Security::sanitize_url( 'javascript:alert("xss")' );
		$this->assertFalse( $url );
		
		// URL with spaces
		$url = HVAC_Security::sanitize_url( ' https://example.com ' );
		$this->assertEquals( 'https://example.com', $url );
	}

	/**
	 * Test array sanitization
	 */
	public function test_sanitize_array() {
		// Text array
		$input = array( 'one', '<script>alert("xss")</script>', 'three' );
		$result = HVAC_Security::sanitize_array( $input, 'text' );
		$this->assertEquals( array( 'one', 'alert(&quot;xss&quot;)', 'three' ), $result );
		
		// Email array
		$input = array( 'test@example.com', 'invalid', 'admin@example.com' );
		$result = HVAC_Security::sanitize_array( $input, 'email' );
		$this->assertEquals( array( 0 => 'test@example.com', 2 => 'admin@example.com' ), $result );
		
		// URL array
		$input = array( 'https://example.com', 'javascript:alert()', 'https://test.com' );
		$result = HVAC_Security::sanitize_array( $input, 'url' );
		$this->assertEquals( array( 0 => 'https://example.com', 2 => 'https://test.com' ), $result );
		
		// Integer array
		$input = array( '123', '456abc', '789' );
		$result = HVAC_Security::sanitize_array( $input, 'int' );
		$this->assertEquals( array( 123, 456, 789 ), $result );
	}

	/**
	 * Test output escaping
	 */
	public function test_escape_output() {
		$input = '<script>alert("xss")</script>';
		
		// HTML context
		$result = HVAC_Security::escape_output( $input, 'html' );
		$this->assertEquals( '&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;', $result );
		
		// Attribute context
		$result = HVAC_Security::escape_output( $input, 'attr' );
		$this->assertEquals( '&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;', $result );
		
		// URL context
		$url = 'https://example.com?param=<script>';
		$result = HVAC_Security::escape_output( $url, 'url' );
		$this->assertEquals( 'https://example.com?param=%3Cscript%3E', $result );
		
		// JavaScript context
		$result = HVAC_Security::escape_output( $input, 'js' );
		$this->assertStringContainsString( '\\x3c', $result ); // JS escaping
	}

	/**
	 * Test AJAX request detection
	 */
	public function test_is_ajax_request() {
		// Not AJAX by default
		$this->assertFalse( HVAC_Security::is_ajax_request() );
		
		// Simulate AJAX request
		define( 'DOING_AJAX', true );
		$this->assertTrue( HVAC_Security::is_ajax_request() );
	}

	/**
	 * Test rate limiting
	 */
	public function test_check_rate_limit() {
		$action = 'test_action';
		$limit = 3;
		$window = 60;
		
		// First attempts should succeed
		for ( $i = 0; $i < $limit; $i++ ) {
			$result = HVAC_Security::check_rate_limit( $action, $limit, $window );
			$this->assertTrue( $result );
		}
		
		// Next attempt should fail
		$result = HVAC_Security::check_rate_limit( $action, $limit, $window );
		$this->assertFalse( $result );
		
		// Different action should work
		$result = HVAC_Security::check_rate_limit( 'different_action', $limit, $window );
		$this->assertTrue( $result );
	}

	/**
	 * Test get user IP
	 */
	public function test_get_user_ip() {
		// Test with REMOTE_ADDR
		$_SERVER['REMOTE_ADDR'] = '192.168.1.1';
		$ip = HVAC_Security::get_user_ip();
		$this->assertEquals( '192.168.1.1', $ip );
		
		// Test with HTTP_X_FORWARDED_FOR
		$_SERVER['HTTP_X_FORWARDED_FOR'] = '10.0.0.1';
		$ip = HVAC_Security::get_user_ip();
		$this->assertEquals( '10.0.0.1', $ip );
		
		// Test with HTTP_CLIENT_IP (highest priority)
		$_SERVER['HTTP_CLIENT_IP'] = '172.16.0.1';
		$ip = HVAC_Security::get_user_ip();
		$this->assertEquals( '172.16.0.1', $ip );
	}
}