<?php

namespace Tests\Modules\Workflows;

use Tests\TestCase;

/**
 * Testes para o módulo Workflows
 */
class WorkflowsTest extends TestCase {
    
    protected function setUp(): void {
        parent::setUp();
        
        // Criar tabelas de workflows
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS workflows (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                tenant_id VARCHAR(100) NOT NULL,
                nome VARCHAR(255) NOT NULL,
                status VARCHAR(20) DEFAULT "rascunho",
                ativo BOOLEAN DEFAULT 0,
                definition TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
        
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS workflow_executions (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                tenant_id VARCHAR(100) NOT NULL,
                workflow_id INTEGER NOT NULL,
                status VARCHAR(20) DEFAULT "pendente",
                input_data TEXT,
                output_data TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
        
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS workflow_approvals (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                tenant_id VARCHAR(100) NOT NULL,
                execution_id INTEGER NOT NULL,
                workflow_id INTEGER NOT NULL,
                status VARCHAR(20) DEFAULT "pendente",
                aprovadores_json TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
        
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS system_notifications (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                tenant_id VARCHAR(100) NOT NULL,
                user_id INTEGER NOT NULL,
                tipo VARCHAR(20) DEFAULT "info",
                titulo VARCHAR(255) NOT NULL,
                mensagem TEXT NOT NULL,
                lida BOOLEAN DEFAULT 0,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
    }
    
    public function testCreateWorkflow(): void {
        // Criar workflow
        $definition = json_encode([
            'nodes' => [
                ['id' => 'start', 'type' => 'start'],
                ['id' => 'action1', 'type' => 'action', 'action' => 'notify']
            ],
            'edges' => [
                ['source' => 'start', 'target' => 'action1']
            ]
        ]);
        
        $stmt = $this->pdo->prepare('
            INSERT INTO workflows (tenant_id, nome, status, ativo, definition)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, 'Test Workflow', 'ativo', 1, $definition]);
        $workflowId = (int)$this->pdo->lastInsertId();
        
        // Verificar workflow
        $stmt = $this->pdo->prepare('SELECT * FROM workflows WHERE id = ?');
        $stmt->execute([$workflowId]);
        $workflow = $stmt->fetch();
        
        $this->assertNotFalse($workflow);
        $this->assertEquals('Test Workflow', $workflow['nome']);
        $this->assertEquals('ativo', $workflow['status']);
        $this->assertEquals(1, $workflow['ativo']);
    }
    
    public function testExecuteWorkflow(): void {
        // Criar workflow
        $definition = json_encode([
            'nodes' => [
                ['id' => 'start', 'type' => 'start']
            ],
            'edges' => []
        ]);
        
        $stmt = $this->pdo->prepare('
            INSERT INTO workflows (tenant_id, nome, status, ativo, definition)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, 'Test Workflow', 'ativo', 1, $definition]);
        $workflowId = (int)$this->pdo->lastInsertId();
        
        // Criar execução
        $inputData = json_encode(['test' => 'data']);
        $stmt = $this->pdo->prepare('
            INSERT INTO workflow_executions (tenant_id, workflow_id, status, input_data)
            VALUES (?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, $workflowId, 'executando', $inputData]);
        $executionId = (int)$this->pdo->lastInsertId();
        
        // Verificar execução
        $stmt = $this->pdo->prepare('SELECT * FROM workflow_executions WHERE id = ?');
        $stmt->execute([$executionId]);
        $execution = $stmt->fetch();
        
        $this->assertNotFalse($execution);
        $this->assertEquals($workflowId, $execution['workflow_id']);
        $this->assertEquals('executando', $execution['status']);
    }
    
    public function testCreateApproval(): void {
        // Criar workflow
        $stmt = $this->pdo->prepare('
            INSERT INTO workflows (tenant_id, nome, status, ativo, definition)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, 'Test Workflow', 'ativo', 1, '{}']);
        $workflowId = (int)$this->pdo->lastInsertId();
        
        // Criar execução
        $stmt = $this->pdo->prepare('
            INSERT INTO workflow_executions (tenant_id, workflow_id, status, input_data)
            VALUES (?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, $workflowId, 'pendente', '{}']);
        $executionId = (int)$this->pdo->lastInsertId();
        
        // Criar aprovação
        $aprovadores = json_encode([
            ['user_id' => 1, 'status' => 'pendente'],
            ['user_id' => 2, 'status' => 'pendente']
        ]);
        
        $stmt = $this->pdo->prepare('
            INSERT INTO workflow_approvals (tenant_id, execution_id, workflow_id, status, aprovadores_json)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, $executionId, $workflowId, 'pendente', $aprovadores]);
        $approvalId = (int)$this->pdo->lastInsertId();
        
        // Verificar aprovação
        $stmt = $this->pdo->prepare('SELECT * FROM workflow_approvals WHERE id = ?');
        $stmt->execute([$approvalId]);
        $approval = $stmt->fetch();
        
        $this->assertNotFalse($approval);
        $this->assertEquals('pendente', $approval['status']);
    }
    
    public function testCreateNotification(): void {
        $userId = $this->createTestUser();
        
        // Criar notificação
        $stmt = $this->pdo->prepare('
            INSERT INTO system_notifications (tenant_id, user_id, tipo, titulo, mensagem, lida)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $this->tenantId,
            $userId,
            'info',
            'Test Notification',
            'Test Message',
            0
        ]);
        $notificationId = (int)$this->pdo->lastInsertId();
        
        // Verificar notificação
        $stmt = $this->pdo->prepare('SELECT * FROM system_notifications WHERE id = ?');
        $stmt->execute([$notificationId]);
        $notification = $stmt->fetch();
        
        $this->assertNotFalse($notification);
        $this->assertEquals('Test Notification', $notification['titulo']);
        $this->assertEquals(0, $notification['lida']);
    }
    
    public function testMarkNotificationAsRead(): void {
        $userId = $this->createTestUser();
        
        // Criar notificação
        $stmt = $this->pdo->prepare('
            INSERT INTO system_notifications (tenant_id, user_id, tipo, titulo, mensagem, lida)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $this->tenantId,
            $userId,
            'info',
            'Test Notification',
            'Test Message',
            0
        ]);
        $notificationId = (int)$this->pdo->lastInsertId();
        
        // Marcar como lida
        $stmt = $this->pdo->prepare('
            UPDATE system_notifications
            SET lida = 1
            WHERE id = ? AND user_id = ?
        ');
        $stmt->execute([$notificationId, $userId]);
        
        // Verificar notificação
        $stmt = $this->pdo->prepare('SELECT lida FROM system_notifications WHERE id = ?');
        $stmt->execute([$notificationId]);
        $notification = $stmt->fetch();
        
        $this->assertEquals(1, $notification['lida']);
    }
}

