<?php

namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Spatie\Permission\Models\Role;
use Tests\TestCase;

class XSSProtectionTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        
        // Create roles for testing
        Role::create(['name' => 'Super Manager']);
        Role::create(['name' => 'Manager']);
        Role::create(['name' => 'Members']);
    }

    /**
     * Test XSS protection in user creation form.
     */
    public function test_user_creation_sanitizes_xss_payloads(): void
    {
        // Create admin user with permissions
        $admin = User::factory()->create();
        $admin->givePermissionTo('create users');

        // XSS payloads to test
        $xssPayloads = [
            '<script>alert("XSS")</script>',
            '<img src="x" onerror="alert(1)">',
            'javascript:alert("XSS")',
            '<svg onload="alert(1)">',
            '"><script>alert("XSS")</script>',
            "'; DROP TABLE users; --",
            '<iframe src="javascript:alert(1)"></iframe>',
            'data:text/html,<script>alert(1)</script>',
        ];

        foreach ($xssPayloads as $payload) {
            $response = $this->actingAs($admin)->post(route('users.store'), [
                'name' => "Test User {$payload}",
                'email' => "test{$payload}@example.com",
                'password' => 'password123',
                'password_confirmation' => 'password123',
                'roles' => ['Members'],
                'is_active' => true,
            ]);

            // Should redirect successfully (validation passes after sanitization)
            $response->assertRedirect();

            // Check that the user was created with sanitized data
            $user = User::where('email', 'LIKE', '%test%@example.com')->latest()->first();
            
            if ($user) {
                // Verify that dangerous characters/scripts are removed
                $this->assertStringNotContainsString('<script>', $user->name);
                $this->assertStringNotContainsString('javascript:', $user->name);
                $this->assertStringNotContainsString('onerror=', $user->name);
                $this->assertStringNotContainsString('<', $user->name);
                $this->assertStringNotContainsString('>', $user->name);
                
                $this->assertStringNotContainsString('<script>', $user->email);
                $this->assertStringNotContainsString('javascript:', $user->email);
                $this->assertStringNotContainsString('<', $user->email);
                $this->assertStringNotContainsString('>', $user->email);
                
                // Clean up for next iteration
                $user->delete();
            }
        }
    }

    /**
     * Test XSS protection in user update form.
     */
    public function test_user_update_sanitizes_xss_payloads(): void
    {
        // Create admin user with permissions
        $admin = User::factory()->create();
        $admin->givePermissionTo('edit users');
        
        // Create target user to update
        $targetUser = User::factory()->create();
        $targetUser->assignRole('Members');

        // XSS payload
        $xssPayload = '<script>alert("XSS")</script>';

        $response = $this->actingAs($admin)->put(route('users.update', $targetUser), [
            'name' => "Updated Name {$xssPayload}",
            'email' => "updated{$xssPayload}@example.com",
            'roles' => ['Members'],
            'is_active' => true,
        ]);

        // Should redirect successfully
        $response->assertRedirect();

        // Refresh user from database
        $targetUser->refresh();

        // Verify that dangerous characters/scripts are removed
        $this->assertStringNotContainsString('<script>', $targetUser->name);
        $this->assertStringNotContainsString('alert', $targetUser->name);
        $this->assertStringNotContainsString('<', $targetUser->name);
        $this->assertStringNotContainsString('>', $targetUser->name);
        
        $this->assertStringNotContainsString('<script>', $targetUser->email);
        $this->assertStringNotContainsString('<', $targetUser->email);
        $this->assertStringNotContainsString('>', $targetUser->email);
    }

    /**
     * Test XSS protection in profile update form.
     */
    public function test_profile_update_sanitizes_xss_payloads(): void
    {
        // Create user
        $user = User::factory()->create([
            'name' => 'Original Name',
            'email' => 'original@example.com',
        ]);

        // XSS payload
        $xssPayload = '<img src="x" onerror="alert(1)">';

        $response = $this->actingAs($user)->patch(route('profile.update'), [
            'name' => "Updated Name {$xssPayload}",
            'email' => "updated{$xssPayload}@example.com",
        ]);

        // Should redirect successfully
        $response->assertRedirect();

        // Refresh user from database
        $user->refresh();

        // Verify that dangerous characters/scripts are removed
        $this->assertStringNotContainsString('<img', $user->name);
        $this->assertStringNotContainsString('onerror=', $user->name);
        $this->assertStringNotContainsString('alert', $user->name);
        $this->assertStringNotContainsString('<', $user->name);
        $this->assertStringNotContainsString('>', $user->name);
        
        $this->assertStringNotContainsString('<img', $user->email);
        $this->assertStringNotContainsString('<', $user->email);
        $this->assertStringNotContainsString('>', $user->email);
    }

    /**
     * Test that legitimate content is preserved after sanitization.
     */
    public function test_legitimate_content_is_preserved(): void
    {
        // Create admin user with permissions
        $admin = User::factory()->create();
        $admin->givePermissionTo('create users');

        $legitimateName = "John O'Connor-Smith Jr.";
        $legitimateEmail = "john.oconnor-smith+test@example-domain.com";

        $response = $this->actingAs($admin)->post(route('users.store'), [
            'name' => $legitimateName,
            'email' => $legitimateEmail,
            'password' => 'password123',
            'password_confirmation' => 'password123',
            'roles' => ['Members'],
            'is_active' => true,
        ]);

        // Should redirect successfully
        $response->assertRedirect();

        // Check that the user was created with preserved legitimate content
        $user = User::where('email', $legitimateEmail)->first();
        
        $this->assertNotNull($user);
        // Note: Our sanitization removes single quotes, so we expect some modification
        $this->assertStringContainsString('John', $user->name);
        $this->assertStringContainsString('Connor-Smith', $user->name);
        $this->assertEquals($legitimateEmail, $user->email);
    }

    /**
     * Test that empty and null inputs are handled properly.
     */
    public function test_empty_inputs_are_handled_properly(): void
    {
        // Create admin user with permissions
        $admin = User::factory()->create();
        $admin->givePermissionTo('create users');

        // Test with empty strings
        $response = $this->actingAs($admin)->post(route('users.store'), [
            'name' => '',
            'email' => '',
            'password' => 'password123',
            'password_confirmation' => 'password123',
            'roles' => ['Members'],
            'is_active' => true,
        ]);

        // Should fail validation due to required fields
        $response->assertSessionHasErrors(['name', 'email']);
    }
}