<?php

use PHPUnit\Framework\TestCase;

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

class ProjectControllerTest extends TestCase
{
    private $projectController;
    private $authController;
    private $adminToken;
    private $regenteToken;
    private $tecnicoToken;
    
    protected function setUp(): void
    {
        $this->projectController = new ProjectController();
        $this->authController = new AuthController();
        
        // Create test tokens for different roles
        $this->adminToken = $this->authController->generateToken([
            'id' => 1,
            'email' => 'admin@example.com',
            'rol' => 'Administrador'
        ]);
        
        $this->regenteToken = $this->authController->generateToken([
            'id' => 2,
            'email' => 'regente@example.com',
            'rol' => 'Regente'
        ]);
        
        $this->tecnicoToken = $this->authController->generateToken([
            'id' => 3,
            'email' => 'tecnico@example.com',
            'rol' => 'Técnico de Campo'
        ]);
    }

    public function testCreateProjectAsAdmin()
    {
        $projectData = [
            'nombre_proyecto' => 'Test Project Admin',
            'nombre_finca' => 'Finca Test',
            'departamento' => 'Guatemala',
            'municipio' => 'Guatemala',
            'aldea' => 'Test Village',
            'nombre_propietario' => 'Test Owner',
            'nombre_regente_forestal' => 'Test Regente'
        ];
        
        $response = $this->projectController->create($projectData, $this->adminToken);
        
        $this->assertArrayHasKey('success', $response);
        $this->assertArrayHasKey('project_id', $response);
        $this->assertTrue($response['success']);
        $this->assertIsInt($response['project_id']);
    }

    public function testCreateProjectAsRegente()
    {
        $projectData = [
            'nombre_proyecto' => 'Test Project Regente',
            'nombre_finca' => 'Finca Test',
            'departamento' => 'Guatemala',
            'municipio' => 'Guatemala',
            'aldea' => 'Test Village',
            'nombre_propietario' => 'Test Owner',
            'nombre_regente_forestal' => 'Test Regente'
        ];
        
        $response = $this->projectController->create($projectData, $this->regenteToken);
        
        $this->assertTrue($response['success']);
        $this->assertArrayHasKey('project_id', $response);
    }

    public function testCreateProjectAsTecnico()
    {
        $projectData = [
            'nombre_proyecto' => 'Test Project Tecnico',
            'nombre_finca' => 'Finca Test',
            'departamento' => 'Guatemala',
            'municipio' => 'Guatemala',
            'aldea' => 'Test Village',
            'nombre_propietario' => 'Test Owner',
            'nombre_regente_forestal' => 'Test Regente'
        ];
        
        $response = $this->projectController->create($projectData, $this->tecnicoToken);
        
        $this->assertFalse($response['success']);
        $this->assertContains('Acceso denegado', $response['message']);
    }

    public function testGetAllProjectsAsAdmin()
    {
        $response = $this->projectController->getAll($this->adminToken);
        
        $this->assertArrayHasKey('success', $response);
        $this->assertArrayHasKey('projects', $response);
        $this->assertTrue($response['success']);
        $this->assertIsArray($response['projects']);
    }

    public function testGetAllProjectsAsRegente()
    {
        $response = $this->projectController->getAll($this->regenteToken);
        
        $this->assertTrue($response['success']);
        $this->assertIsArray($response['projects']);
        // Regente should only see their own projects
    }

    public function testGetAllProjectsAsTecnico()
    {
        $response = $this->projectController->getAll($this->tecnicoToken);
        
        $this->assertTrue($response['success']);
        $this->assertIsArray($response['projects']);
        // Técnico should see projects they have access to
    }

    public function testGetProjectByIdAsAdmin()
    {
        $projectId = 1;
        $response = $this->projectController->getById($projectId, $this->adminToken);
        
        $this->assertArrayHasKey('success', $response);
        $this->assertArrayHasKey('project', $response);
        $this->assertTrue($response['success']);
    }

    public function testGetProjectByIdAsUnauthorizedUser()
    {
        $projectId = 999; // Non-existent or unauthorized project
        $response = $this->projectController->getById($projectId, $this->tecnicoToken);
        
        $this->assertFalse($response['success']);
        $this->assertContains('Proyecto no encontrado o acceso denegado', $response['message']);
    }

    public function testUpdateProjectAsAdmin()
    {
        $projectId = 1;
        $updateData = [
            'nombre_proyecto' => 'Updated Project Name',
            'departamento' => 'Petén'
        ];
        
        $response = $this->projectController->update($projectId, $updateData, $this->adminToken);
        
        $this->assertTrue($response['success']);
        $this->assertContains('actualizado', $response['message']);
    }

    public function testUpdateProjectAsUnauthorizedUser()
    {
        $projectId = 1;
        $updateData = [
            'nombre_proyecto' => 'Unauthorized Update'
        ];
        
        $response = $this->projectController->update($projectId, $updateData, $this->tecnicoToken);
        
        $this->assertFalse($response['success']);
        $this->assertContains('Acceso denegado', $response['message']);
    }

    public function testDeleteProjectAsAdmin()
    {
        $projectId = 999; // Test project ID
        $response = $this->projectController->delete($projectId, $this->adminToken);
        
        $this->assertArrayHasKey('success', $response);
        // Should succeed for admin (even if project doesn't exist, should handle gracefully)
    }

    public function testDeleteProjectAsNonAdmin()
    {
        $projectId = 1;
        $response = $this->projectController->delete($projectId, $this->regenteToken);
        
        $this->assertFalse($response['success']);
        $this->assertContains('Acceso denegado', $response['message']);
    }

    public function testUploadDocumentAsAuthorizedUser()
    {
        $projectId = 1;
        $documentType = 'tenencia';
        $mockFile = [
            'name' => 'test_document.pdf',
            'type' => 'application/pdf',
            'size' => 1024 * 1024,
            'tmp_name' => '/tmp/test_upload',
            'error' => UPLOAD_ERR_OK
        ];
        
        $response = $this->projectController->uploadDocument($projectId, $documentType, $mockFile, $this->regenteToken);
        
        $this->assertArrayHasKey('success', $response);
        // Note: This would fail in actual test due to file system, but tests the logic
    }

    public function testUploadDocumentWithInvalidFile()
    {
        $projectId = 1;
        $documentType = 'tenencia';
        $invalidFile = [
            'name' => 'test_document.txt',
            'type' => 'text/plain',
            'size' => 1024,
            'tmp_name' => '/tmp/test_upload',
            'error' => UPLOAD_ERR_OK
        ];
        
        $response = $this->projectController->uploadDocument($projectId, $documentType, $invalidFile, $this->regenteToken);
        
        $this->assertFalse($response['success']);
        $this->assertContains('Solo se permiten archivos PDF', $response['message']);
    }

    public function testValidateProjectData()
    {
        $validData = [
            'nombre_proyecto' => 'Valid Project',
            'nombre_finca' => 'Valid Finca',
            'departamento' => 'Guatemala',
            'municipio' => 'Guatemala',
            'aldea' => 'Valid Village',
            'nombre_propietario' => 'Valid Owner',
            'nombre_regente_forestal' => 'Valid Regente'
        ];
        
        $result = $this->projectController->validateProjectData($validData);
        $this->assertTrue($result['valid']);
        $this->assertEmpty($result['errors']);
    }

    public function testValidateProjectDataWithMissingFields()
    {
        $invalidData = [
            'nombre_proyecto' => 'Incomplete Project'
            // Missing required fields
        ];
        
        $result = $this->projectController->validateProjectData($invalidData);
        $this->assertFalse($result['valid']);
        $this->assertNotEmpty($result['errors']);
    }
}