<?php

namespace Tests\Modules\Financeiro;

use Tests\TestCase;

/**
 * Testes para o módulo Financeiro
 */
class FinanceiroTest extends TestCase {
    
    protected function setUp(): void {
        parent::setUp();
        
        // Criar tabela de contas a pagar
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS contas_pagar (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                tenant_id VARCHAR(100) NOT NULL,
                numero VARCHAR(50) NOT NULL,
                descricao VARCHAR(255) NOT NULL,
                valor DECIMAL(18,2) NOT NULL,
                data_vencimento DATE NOT NULL,
                status VARCHAR(20) DEFAULT "pendente",
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
        
        // Criar tabela de contas a receber
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS contas_receber (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                tenant_id VARCHAR(100) NOT NULL,
                numero VARCHAR(50) NOT NULL,
                descricao VARCHAR(255) NOT NULL,
                valor DECIMAL(18,2) NOT NULL,
                data_vencimento DATE NOT NULL,
                status VARCHAR(20) DEFAULT "pendente",
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
        
        // Criar tabela de fluxo de caixa
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS fluxo_caixa (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                tenant_id VARCHAR(100) NOT NULL,
                data DATE NOT NULL,
                tipo VARCHAR(20) NOT NULL,
                descricao VARCHAR(255) NOT NULL,
                valor DECIMAL(18,2) NOT NULL,
                saldo DECIMAL(18,2) NOT NULL,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
    }
    
    public function testCreateContaPagar(): void {
        // Criar conta a pagar
        $stmt = $this->pdo->prepare('
            INSERT INTO contas_pagar (tenant_id, numero, descricao, valor, data_vencimento, status)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $this->tenantId,
            'CP001',
            'Fornecedor Test',
            1000.00,
            date('Y-m-d', strtotime('+30 days')),
            'pendente'
        ]);
        $contaId = (int)$this->pdo->lastInsertId();
        
        // Verificar conta
        $stmt = $this->pdo->prepare('SELECT * FROM contas_pagar WHERE id = ?');
        $stmt->execute([$contaId]);
        $conta = $stmt->fetch();
        
        $this->assertNotFalse($conta);
        $this->assertEquals('CP001', $conta['numero']);
        $this->assertEquals(1000.00, $conta['valor']);
        $this->assertEquals('pendente', $conta['status']);
    }
    
    public function testCreateContaReceber(): void {
        // Criar conta a receber
        $stmt = $this->pdo->prepare('
            INSERT INTO contas_receber (tenant_id, numero, descricao, valor, data_vencimento, status)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $this->tenantId,
            'CR001',
            'Cliente Test',
            2000.00,
            date('Y-m-d', strtotime('+15 days')),
            'pendente'
        ]);
        $contaId = (int)$this->pdo->lastInsertId();
        
        // Verificar conta
        $stmt = $this->pdo->prepare('SELECT * FROM contas_receber WHERE id = ?');
        $stmt->execute([$contaId]);
        $conta = $stmt->fetch();
        
        $this->assertNotFalse($conta);
        $this->assertEquals('CR001', $conta['numero']);
        $this->assertEquals(2000.00, $conta['valor']);
        $this->assertEquals('pendente', $conta['status']);
    }
    
    public function testPayContaPagar(): void {
        // Criar conta a pagar
        $stmt = $this->pdo->prepare('
            INSERT INTO contas_pagar (tenant_id, numero, descricao, valor, data_vencimento, status)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $this->tenantId,
            'CP002',
            'Fornecedor Test',
            500.00,
            date('Y-m-d'),
            'pendente'
        ]);
        $contaId = (int)$this->pdo->lastInsertId();
        
        // Pagar conta
        $stmt = $this->pdo->prepare('
            UPDATE contas_pagar 
            SET status = "pago"
            WHERE id = ? AND tenant_id = ?
        ');
        $stmt->execute([$contaId, $this->tenantId]);
        
        // Registrar no fluxo de caixa
        $stmt = $this->pdo->prepare('
            INSERT INTO fluxo_caixa (tenant_id, data, tipo, descricao, valor, saldo)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $this->tenantId,
            date('Y-m-d'),
            'saida',
            'Pagamento CP002',
            -500.00,
            -500.00
        ]);
        
        // Verificar status
        $stmt = $this->pdo->prepare('SELECT status FROM contas_pagar WHERE id = ?');
        $stmt->execute([$contaId]);
        $conta = $stmt->fetch();
        
        $this->assertEquals('pago', $conta['status']);
    }
    
    public function testReceiveContaReceber(): void {
        // Criar conta a receber
        $stmt = $this->pdo->prepare('
            INSERT INTO contas_receber (tenant_id, numero, descricao, valor, data_vencimento, status)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $this->tenantId,
            'CR002',
            'Cliente Test',
            750.00,
            date('Y-m-d'),
            'pendente'
        ]);
        $contaId = (int)$this->pdo->lastInsertId();
        
        // Receber conta
        $stmt = $this->pdo->prepare('
            UPDATE contas_receber 
            SET status = "recebido"
            WHERE id = ? AND tenant_id = ?
        ');
        $stmt->execute([$contaId, $this->tenantId]);
        
        // Registrar no fluxo de caixa
        $stmt = $this->pdo->prepare('
            INSERT INTO fluxo_caixa (tenant_id, data, tipo, descricao, valor, saldo)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $this->tenantId,
            date('Y-m-d'),
            'entrada',
            'Recebimento CR002',
            750.00,
            750.00
        ]);
        
        // Verificar status
        $stmt = $this->pdo->prepare('SELECT status FROM contas_receber WHERE id = ?');
        $stmt->execute([$contaId]);
        $conta = $stmt->fetch();
        
        $this->assertEquals('recebido', $conta['status']);
    }
    
    public function testCashFlowBalance(): void {
        // Criar movimentações
        $movements = [
            ['tipo' => 'entrada', 'valor' => 1000.00, 'descricao' => 'Venda'],
            ['tipo' => 'saida', 'valor' => -300.00, 'descricao' => 'Compra'],
            ['tipo' => 'entrada', 'valor' => 500.00, 'descricao' => 'Recebimento'],
            ['tipo' => 'saida', 'valor' => -200.00, 'descricao' => 'Pagamento']
        ];
        
        $saldo = 0;
        foreach ($movements as $movement) {
            $saldo += $movement['valor'];
            $stmt = $this->pdo->prepare('
                INSERT INTO fluxo_caixa (tenant_id, data, tipo, descricao, valor, saldo)
                VALUES (?, ?, ?, ?, ?, ?)
            ');
            $stmt->execute([
                $this->tenantId,
                date('Y-m-d'),
                $movement['tipo'],
                $movement['descricao'],
                $movement['valor'],
                $saldo
            ]);
        }
        
        // Verificar saldo final
        $stmt = $this->pdo->prepare('
            SELECT saldo FROM fluxo_caixa 
            WHERE tenant_id = ? 
            ORDER BY id DESC 
            LIMIT 1
        ');
        $stmt->execute([$this->tenantId]);
        $ultimo = $stmt->fetch();
        
        $this->assertEquals(1000.00, $ultimo['saldo']);
    }
}

