<?php

use PHPUnit\Framework\TestCase;

require_once __DIR__ . '/../../api/models/User.php';

class UserModelTest extends TestCase
{
    private $user;
    
    protected function setUp(): void
    {
        $this->user = new User();
    }

    public function testValidateUserData()
    {
        $validData = [
            'nombre' => 'Juan Pérez',
            'email' => 'juan@example.com',
            'password' => 'password123',
            'rol' => 'Técnico de Campo'
        ];
        
        $result = $this->user->validateUserData($validData);
        $this->assertTrue($result['valid']);
        $this->assertEmpty($result['errors']);
    }

    public function testValidateUserDataWithInvalidEmail()
    {
        $invalidData = [
            'nombre' => 'Juan Pérez',
            'email' => 'invalid-email',
            'password' => 'password123',
            'rol' => 'Técnico de Campo'
        ];
        
        $result = $this->user->validateUserData($invalidData);
        $this->assertFalse($result['valid']);
        $this->assertContains('Email inválido', $result['errors']);
    }

    public function testValidateUserDataWithInvalidRole()
    {
        $invalidData = [
            'nombre' => 'Juan Pérez',
            'email' => 'juan@example.com',
            'password' => 'password123',
            'rol' => 'Rol Inválido'
        ];
        
        $result = $this->user->validateUserData($invalidData);
        $this->assertFalse($result['valid']);
        $this->assertContains('Rol inválido', $result['errors']);
    }

    public function testValidateUserDataWithShortPassword()
    {
        $invalidData = [
            'nombre' => 'Juan Pérez',
            'email' => 'juan@example.com',
            'password' => '123',
            'rol' => 'Técnico de Campo'
        ];
        
        $result = $this->user->validateUserData($invalidData);
        $this->assertFalse($result['valid']);
        $this->assertContains('La contraseña debe tener al menos 6 caracteres', $result['errors']);
    }

    public function testValidateUserDataWithMissingFields()
    {
        $incompleteData = [
            'nombre' => 'Juan Pérez',
            'email' => 'juan@example.com'
            // Faltan password y rol
        ];
        
        $result = $this->user->validateUserData($incompleteData);
        $this->assertFalse($result['valid']);
        $this->assertGreaterThan(0, count($result['errors']));
    }

    public function testHashPassword()
    {
        $password = 'password123';
        $hashedPassword = $this->user->hashPassword($password);
        
        $this->assertNotEquals($password, $hashedPassword);
        $this->assertTrue(password_verify($password, $hashedPassword));
    }

    public function testVerifyPassword()
    {
        $password = 'password123';
        $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
        
        $this->assertTrue($this->user->verifyPassword($password, $hashedPassword));
        $this->assertFalse($this->user->verifyPassword('wrongpassword', $hashedPassword));
    }

    public function testGetValidRoles()
    {
        $roles = $this->user->getValidRoles();
        
        $this->assertIsArray($roles);
        $this->assertContains('Administrador', $roles);
        $this->assertContains('Regente', $roles);
        $this->assertContains('Técnico de Campo', $roles);
        $this->assertCount(3, $roles);
    }

    public function testSanitizeUserData()
    {
        $dirtyData = [
            'nombre' => '  Juan Pérez  ',
            'email' => '  JUAN@EXAMPLE.COM  ',
            'rol' => 'técnico de campo'
        ];
        
        $cleanData = $this->user->sanitizeUserData($dirtyData);
        
        $this->assertEquals('Juan Pérez', $cleanData['nombre']);
        $this->assertEquals('juan@example.com', $cleanData['email']);
        $this->assertEquals('Técnico de Campo', $cleanData['rol']);
    }

    public function testCanAccessResource()
    {
        // Test admin access
        $this->assertTrue($this->user->canAccessResource('Administrador', 'users'));
        $this->assertTrue($this->user->canAccessResource('Administrador', 'projects'));
        $this->assertTrue($this->user->canAccessResource('Administrador', 'reports'));
        
        // Test regente access
        $this->assertFalse($this->user->canAccessResource('Regente', 'users'));
        $this->assertTrue($this->user->canAccessResource('Regente', 'projects'));
        $this->assertTrue($this->user->canAccessResource('Regente', 'reports'));
        
        // Test técnico access
        $this->assertFalse($this->user->canAccessResource('Técnico de Campo', 'users'));
        $this->assertFalse($this->user->canAccessResource('Técnico de Campo', 'projects'));
        $this->assertTrue($this->user->canAccessResource('Técnico de Campo', 'field-data'));
    }

    public function testGenerateUserToken()
    {
        $userData = [
            'id' => 1,
            'nombre' => 'Juan Pérez',
            'email' => 'juan@example.com',
            'rol' => 'Técnico de Campo'
        ];
        
        $token = $this->user->generateUserToken($userData);
        
        $this->assertIsString($token);
        $this->assertNotEmpty($token);
        
        // Verify token structure (JWT has 3 parts separated by dots)
        $tokenParts = explode('.', $token);
        $this->assertCount(3, $tokenParts);
    }
}