<?php

namespace Tests\Modules\Locadora;

use Tests\TestCase;
use PDO;

/**
 * Testes para o módulo Locadora
 */
class LocadoraTest extends TestCase {
    
    protected function setUp(): void {
        parent::setUp();
        $this->createLocadoraTables();
    }
    
    private function createLocadoraTables(): void {
        // Tabela de frota
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS locadora_frota (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                placa VARCHAR(10) NOT NULL,
                marca VARCHAR(100) NOT NULL,
                modelo VARCHAR(100) NOT NULL,
                ano_fabricacao INTEGER NULL,
                ano_modelo INTEGER NULL,
                cor VARCHAR(50) NULL,
                km_atual DECIMAL(10,0) NOT NULL DEFAULT 0,
                km_ultima_manutencao DECIMAL(10,0) NULL,
                km_proxima_manutencao DECIMAL(10,0) NULL,
                status VARCHAR(20) NOT NULL DEFAULT "disponivel",
                categoria VARCHAR(20) NULL,
                valor_diaria DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                ncm VARCHAR(8) NULL,
                cest VARCHAR(7) NULL,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
        
        // Tabela de contratos
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS locadora_contratos (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                numero VARCHAR(50) NOT NULL,
                cliente_id INTEGER NOT NULL,
                veiculo_id INTEGER NOT NULL,
                data_inicio DATE NOT NULL,
                data_fim DATE NOT NULL,
                data_devolucao DATE NULL,
                km_saida DECIMAL(10,0) NOT NULL DEFAULT 0,
                km_retorno DECIMAL(10,0) NULL,
                valor_diaria DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                quantidade_dias INTEGER NOT NULL DEFAULT 1,
                valor_total DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                valor_adicional DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                valor_final DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                status VARCHAR(20) NOT NULL DEFAULT "aberto",
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
        
        // Tabela de histórico KM
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS locadora_km_historico (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                veiculo_id INTEGER NOT NULL,
                contrato_id INTEGER NULL,
                km_anterior DECIMAL(10,0) NOT NULL,
                km_atual DECIMAL(10,0) NOT NULL,
                km_percorrido DECIMAL(10,0) NOT NULL,
                tipo VARCHAR(20) NOT NULL DEFAULT "manual",
                data_registro DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
        
        // Tabela de manutenção
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS locadora_manutencao (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                veiculo_id INTEGER NOT NULL,
                tipo VARCHAR(20) NOT NULL DEFAULT "preventiva",
                descricao VARCHAR(255) NOT NULL,
                km_manutencao DECIMAL(10,0) NOT NULL,
                data_manutencao DATE NOT NULL,
                valor DECIMAL(12,2) NOT NULL DEFAULT 0.00,
                proxima_km DECIMAL(10,0) NULL,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
    }
    
    public function testCreateVeiculo(): void {
        $stmt = $this->pdo->prepare('
            INSERT INTO locadora_frota (
                placa, marca, modelo, ano_fabricacao, ano_modelo, km_atual,
                status, categoria, valor_diaria
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
        ');
        
        $stmt->execute([
            'ABC1234',
            'Toyota',
            'Corolla',
            2023,
            2023,
            0,
            'disponivel',
            'executivo',
            150.00
        ]);
        
        $id = (int)$this->pdo->lastInsertId();
        $this->assertGreaterThan(0, $id);
        
        // Verificar
        $stmt = $this->pdo->prepare('SELECT * FROM locadora_frota WHERE id = ?');
        $stmt->execute([$id]);
        $veiculo = $stmt->fetch();
        
        $this->assertNotFalse($veiculo);
        $this->assertEquals('ABC1234', $veiculo['placa']);
        $this->assertEquals('Toyota', $veiculo['marca']);
        $this->assertEquals('disponivel', $veiculo['status']);
    }
    
    public function testAtualizarKm(): void {
        // Criar veículo
        $stmt = $this->pdo->prepare('
            INSERT INTO locadora_frota (placa, marca, modelo, km_atual, status)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute(['DEF5678', 'Honda', 'Civic', 10000, 'disponivel']);
        $veiculoId = (int)$this->pdo->lastInsertId();
        
        // Atualizar KM
        $kmNovo = 15000;
        $kmAnterior = 10000;
        $kmPercorrido = $kmNovo - $kmAnterior;
        
        $this->pdo->beginTransaction();
        
        // Atualizar veículo
        $stmt = $this->pdo->prepare('UPDATE locadora_frota SET km_atual = ? WHERE id = ?');
        $stmt->execute([$kmNovo, $veiculoId]);
        
        // Registrar no histórico
        $stmt = $this->pdo->prepare('
            INSERT INTO locadora_km_historico (
                veiculo_id, km_anterior, km_atual, km_percorrido, tipo, data_registro
            ) VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
        ');
        $stmt->execute([$veiculoId, $kmAnterior, $kmNovo, $kmPercorrido, 'manual']);
        
        $this->pdo->commit();
        
        // Verificar
        $stmt = $this->pdo->prepare('SELECT km_atual FROM locadora_frota WHERE id = ?');
        $stmt->execute([$veiculoId]);
        $veiculo = $stmt->fetch();
        
        $this->assertEquals($kmNovo, $veiculo['km_atual']);
    }
    
    public function testCreateContrato(): void {
        // Criar veículo
        $stmt = $this->pdo->prepare('
            INSERT INTO locadora_frota (placa, marca, modelo, km_atual, status, valor_diaria)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute(['GHI9012', 'Ford', 'Ka', 5000, 'disponivel', 80.00]);
        $veiculoId = (int)$this->pdo->lastInsertId();
        
        // Criar cliente de teste
        $clienteId = $this->createTestClient(['nome' => 'Cliente Locadora']);
        
        // Criar contrato
        $numero = 'LOC-000001';
        $dataInicio = date('Y-m-d');
        $dataFim = date('Y-m-d', strtotime('+7 days'));
        $quantidadeDias = 7;
        $valorDiaria = 80.00;
        $valorTotal = $valorDiaria * $quantidadeDias;
        $kmSaida = 5000;
        
        $this->pdo->beginTransaction();
        
        $stmt = $this->pdo->prepare('
            INSERT INTO locadora_contratos (
                numero, cliente_id, veiculo_id, data_inicio, data_fim,
                km_saida, valor_diaria, quantidade_dias, valor_total, status
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $numero, $clienteId, $veiculoId, $dataInicio, $dataFim,
            $kmSaida, $valorDiaria, $quantidadeDias, $valorTotal, 'aberto'
        ]);
        $contratoId = (int)$this->pdo->lastInsertId();
        
        // Atualizar status do veículo
        $stmt = $this->pdo->prepare('UPDATE locadora_frota SET status = ? WHERE id = ?');
        $stmt->execute(['locado', $veiculoId]);
        
        $this->pdo->commit();
        
        // Verificar
        $stmt = $this->pdo->prepare('SELECT * FROM locadora_contratos WHERE id = ?');
        $stmt->execute([$contratoId]);
        $contrato = $stmt->fetch();
        
        $this->assertNotFalse($contrato);
        $this->assertEquals($numero, $contrato['numero']);
        $this->assertEquals('aberto', $contrato['status']);
        $this->assertEquals($valorTotal, $contrato['valor_total']);
    }
    
    public function testEncerrarContrato(): void {
        // Criar veículo e contrato
        $stmt = $this->pdo->prepare('
            INSERT INTO locadora_frota (placa, marca, modelo, km_atual, status, valor_diaria)
            VALUES (?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute(['JKL3456', 'Volkswagen', 'Gol', 20000, 'locado', 90.00]);
        $veiculoId = (int)$this->pdo->lastInsertId();
        
        $clienteId = $this->createTestClient();
        
        $stmt = $this->pdo->prepare('
            INSERT INTO locadora_contratos (
                numero, cliente_id, veiculo_id, data_inicio, data_fim,
                km_saida, valor_diaria, quantidade_dias, valor_total, status
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            'LOC-000002', $clienteId, $veiculoId, date('Y-m-d'), date('Y-m-d', strtotime('+5 days')),
            20000, 90.00, 5, 450.00, 'em_andamento'
        ]);
        $contratoId = (int)$this->pdo->lastInsertId();
        
        // Encerrar contrato
        $kmRetorno = 20500;
        $kmSaida = 20000;
        $kmPercorrido = $kmRetorno - $kmSaida;
        $dataDevolucao = date('Y-m-d');
        $valorAdicional = 50.00;
        $valorFinal = 450.00 + $valorAdicional;
        
        $this->pdo->beginTransaction();
        
        // Atualizar contrato
        $stmt = $this->pdo->prepare('
            UPDATE locadora_contratos SET
                status = ?, data_devolucao = ?, km_retorno = ?,
                valor_adicional = ?, valor_final = ?
            WHERE id = ?
        ');
        $stmt->execute(['encerrado', $dataDevolucao, $kmRetorno, $valorAdicional, $valorFinal, $contratoId]);
        
        // Atualizar veículo
        $stmt = $this->pdo->prepare('UPDATE locadora_frota SET status = ?, km_atual = ? WHERE id = ?');
        $stmt->execute(['disponivel', $kmRetorno, $veiculoId]);
        
        // Registrar KM de retorno
        $stmt = $this->pdo->prepare('
            INSERT INTO locadora_km_historico (
                veiculo_id, contrato_id, km_anterior, km_atual, km_percorrido, tipo, data_registro
            ) VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
        ');
        $stmt->execute([$veiculoId, $contratoId, $kmSaida, $kmRetorno, $kmPercorrido, 'retorno']);
        
        $this->pdo->commit();
        
        // Verificar
        $stmt = $this->pdo->prepare('SELECT * FROM locadora_contratos WHERE id = ?');
        $stmt->execute([$contratoId]);
        $contrato = $stmt->fetch();
        
        $this->assertEquals('encerrado', $contrato['status']);
        $this->assertEquals($kmRetorno, $contrato['km_retorno']);
        $this->assertEquals($valorFinal, $contrato['valor_final']);
    }
    
    public function testAdicionarManutencao(): void {
        // Criar veículo
        $stmt = $this->pdo->prepare('
            INSERT INTO locadora_frota (placa, marca, modelo, km_atual, status)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute(['MNO7890', 'Chevrolet', 'Onix', 30000, 'disponivel']);
        $veiculoId = (int)$this->pdo->lastInsertId();
        
        // Adicionar manutenção
        $this->pdo->beginTransaction();
        
        $stmt = $this->pdo->prepare('
            INSERT INTO locadora_manutencao (
                veiculo_id, tipo, descricao, km_manutencao, data_manutencao, valor, proxima_km
            ) VALUES (?, ?, ?, ?, ?, ?, ?)
        ');
        $stmt->execute([
            $veiculoId,
            'preventiva',
            'Troca de óleo e filtros',
            30000,
            date('Y-m-d'),
            200.00,
            35000
        ]);
        $manutencaoId = (int)$this->pdo->lastInsertId();
        
        // Atualizar veículo
        $stmt = $this->pdo->prepare('
            UPDATE locadora_frota SET
                km_ultima_manutencao = ?,
                km_proxima_manutencao = ?
            WHERE id = ?
        ');
        $stmt->execute([30000, 35000, $veiculoId]);
        
        $this->pdo->commit();
        
        // Verificar
        $stmt = $this->pdo->prepare('SELECT * FROM locadora_manutencao WHERE id = ?');
        $stmt->execute([$manutencaoId]);
        $manutencao = $stmt->fetch();
        
        $this->assertNotFalse($manutencao);
        $this->assertEquals('preventiva', $manutencao['tipo']);
        $this->assertEquals(30000, $manutencao['km_manutencao']);
    }
}

