<?php

use PHPUnit\Framework\TestCase;

require_once __DIR__ . '/../../api/controllers/AuthController.php';

class AuthControllerTest extends TestCase
{
    private $authController;
    private $testUser;
    
    protected function setUp(): void
    {
        $this->authController = new AuthController();
        $this->testUser = [
            'id' => 1,
            'nombre' => 'Test User',
            'email' => 'test@example.com',
            'rol' => 'Administrador'
        ];
    }

    public function testLoginWithValidCredentials()
    {
        $credentials = [
            'email' => 'test@example.com',
            'password' => 'password123'
        ];
        
        // Mock the authentication process
        $response = $this->authController->login($credentials);
        
        $this->assertArrayHasKey('success', $response);
        $this->assertArrayHasKey('token', $response);
        $this->assertArrayHasKey('user', $response);
        $this->assertTrue($response['success']);
    }

    public function testLoginWithInvalidCredentials()
    {
        $credentials = [
            'email' => 'test@example.com',
            'password' => 'wrongpassword'
        ];
        
        $response = $this->authController->login($credentials);
        
        $this->assertArrayHasKey('success', $response);
        $this->assertArrayHasKey('message', $response);
        $this->assertFalse($response['success']);
        $this->assertEquals('Credenciales inválidas', $response['message']);
    }

    public function testLoginWithMissingFields()
    {
        $credentials = [
            'email' => 'test@example.com'
            // Missing password
        ];
        
        $response = $this->authController->login($credentials);
        
        $this->assertFalse($response['success']);
        $this->assertContains('Email y contraseña son requeridos', $response['message']);
    }

    public function testTokenValidation()
    {
        $validToken = $this->authController->generateToken($this->testUser);
        $result = $this->authController->validateToken($validToken);
        
        $this->assertNotFalse($result);
        $this->assertEquals($this->testUser['id'], $result['user_id']);
        $this->assertEquals($this->testUser['email'], $result['email']);
        $this->assertEquals($this->testUser['rol'], $result['rol']);
    }

    public function testTokenValidationWithInvalidToken()
    {
        $invalidToken = 'invalid.token.here';
        $result = $this->authController->validateToken($invalidToken);
        
        $this->assertFalse($result);
    }

    public function testTokenValidationWithExpiredToken()
    {
        // Create an expired token (mock)
        $expiredTokenData = array_merge($this->testUser, [
            'iat' => time() - 3600,
            'exp' => time() - 1800 // Expired 30 minutes ago
        ]);
        
        $expiredToken = $this->authController->generateTokenWithCustomExpiry($expiredTokenData, -1800);
        $result = $this->authController->validateToken($expiredToken);
        
        $this->assertFalse($result);
    }

    public function testRefreshToken()
    {
        $validToken = $this->authController->generateToken($this->testUser);
        $refreshResponse = $this->authController->refreshToken($validToken);
        
        $this->assertArrayHasKey('success', $refreshResponse);
        $this->assertArrayHasKey('token', $refreshResponse);
        $this->assertTrue($refreshResponse['success']);
        $this->assertNotEquals($validToken, $refreshResponse['token']);
    }

    public function testLogout()
    {
        $token = $this->authController->generateToken($this->testUser);
        $logoutResponse = $this->authController->logout($token);
        
        $this->assertArrayHasKey('success', $logoutResponse);
        $this->assertTrue($logoutResponse['success']);
    }

    public function testGetCurrentUser()
    {
        $token = $this->authController->generateToken($this->testUser);
        $userResponse = $this->authController->getCurrentUser($token);
        
        $this->assertArrayHasKey('success', $userResponse);
        $this->assertArrayHasKey('user', $userResponse);
        $this->assertTrue($userResponse['success']);
        $this->assertEquals($this->testUser['email'], $userResponse['user']['email']);
    }

    public function testRoleBasedAccess()
    {
        // Test admin access
        $adminToken = $this->authController->generateToken([
            'id' => 1,
            'email' => 'admin@example.com',
            'rol' => 'Administrador'
        ]);
        
        $this->assertTrue($this->authController->hasRole($adminToken, ['Administrador']));
        $this->assertTrue($this->authController->hasRole($adminToken, ['Administrador', 'Regente']));
        $this->assertFalse($this->authController->hasRole($adminToken, ['Técnico de Campo']));
        
        // Test regente access
        $regenteToken = $this->authController->generateToken([
            'id' => 2,
            'email' => 'regente@example.com',
            'rol' => 'Regente'
        ]);
        
        $this->assertTrue($this->authController->hasRole($regenteToken, ['Regente']));
        $this->assertTrue($this->authController->hasRole($regenteToken, ['Administrador', 'Regente']));
        $this->assertFalse($this->authController->hasRole($regenteToken, ['Administrador']));
        
        // Test técnico access
        $tecnicoToken = $this->authController->generateToken([
            'id' => 3,
            'email' => 'tecnico@example.com',
            'rol' => 'Técnico de Campo'
        ]);
        
        $this->assertTrue($this->authController->hasRole($tecnicoToken, ['Técnico de Campo']));
        $this->assertFalse($this->authController->hasRole($tecnicoToken, ['Administrador', 'Regente']));
    }
}