<?php

namespace Tests\Modules\PCP;

use Tests\TestCase;

/**
 * Testes para o módulo PCP
 */
class PCPTest extends TestCase {
    
    protected function setUp(): void {
        parent::setUp();
        
        // Criar tabelas do PCP
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS production_orders (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                tenant_id VARCHAR(100) NOT NULL,
                numero VARCHAR(50) NOT NULL,
                product_id INTEGER NOT NULL,
                quantidade_solicitada DECIMAL(18,3) NOT NULL,
                status VARCHAR(20) DEFAULT "rascunho",
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
        
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS production_material_consumption (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                tenant_id VARCHAR(100) NOT NULL,
                order_id INTEGER NOT NULL,
                material_product_id INTEGER NOT NULL,
                quantidade_prevista DECIMAL(18,3) NOT NULL,
                quantidade_consumida DECIMAL(18,3) DEFAULT 0,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
        
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS estoque_reservas (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                tenant_id VARCHAR(100) NOT NULL,
                production_order_id INTEGER NOT NULL,
                product_id INTEGER NOT NULL,
                quantidade_reservada DECIMAL(18,3) NOT NULL,
                quantidade_utilizada DECIMAL(18,3) DEFAULT 0,
                status VARCHAR(20) DEFAULT "reservada",
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ');
    }
    
    public function testCreateProductionOrder(): void {
        $productId = $this->createTestProduct();
        
        // Criar ordem de produção
        $stmt = $this->pdo->prepare('
            INSERT INTO production_orders (tenant_id, numero, product_id, quantidade_solicitada, status)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, 'OP001', $productId, 10.0, 'rascunho']);
        $orderId = (int)$this->pdo->lastInsertId();
        
        // Verificar ordem
        $stmt = $this->pdo->prepare('SELECT * FROM production_orders WHERE id = ?');
        $stmt->execute([$orderId]);
        $order = $stmt->fetch();
        
        $this->assertNotFalse($order);
        $this->assertEquals('OP001', $order['numero']);
        $this->assertEquals(10.0, $order['quantidade_solicitada']);
    }
    
    public function testReserveMaterials(): void {
        $productId = $this->createTestProduct(['estoque' => 100.0]);
        $materialId = $this->createTestProduct(['codigo' => 'MAT001', 'estoque' => 50.0]);
        
        // Criar ordem de produção
        $stmt = $this->pdo->prepare('
            INSERT INTO production_orders (tenant_id, numero, product_id, quantidade_solicitada, status)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, 'OP002', $productId, 10.0, 'aprovada']);
        $orderId = (int)$this->pdo->lastInsertId();
        
        // Criar consumo de material
        $stmt = $this->pdo->prepare('
            INSERT INTO production_material_consumption (tenant_id, order_id, material_product_id, quantidade_prevista)
            VALUES (?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, $orderId, $materialId, 20.0]);
        
        // Reservar material
        $stmt = $this->pdo->prepare('
            INSERT INTO estoque_reservas (tenant_id, production_order_id, product_id, quantidade_reservada, status)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, $orderId, $materialId, 20.0, 'reservada']);
        
        // Verificar reserva
        $stmt = $this->pdo->prepare('SELECT * FROM estoque_reservas WHERE production_order_id = ?');
        $stmt->execute([$orderId]);
        $reserva = $stmt->fetch();
        
        $this->assertNotFalse($reserva);
        $this->assertEquals(20.0, $reserva['quantidade_reservada']);
        $this->assertEquals('reservada', $reserva['status']);
    }
    
    public function testInsufficientStockForReservation(): void {
        $productId = $this->createTestProduct();
        $materialId = $this->createTestProduct(['codigo' => 'MAT002', 'estoque' => 10.0]);
        
        // Criar ordem de produção
        $stmt = $this->pdo->prepare('
            INSERT INTO production_orders (tenant_id, numero, product_id, quantidade_solicitada, status)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, 'OP003', $productId, 10.0, 'aprovada']);
        $orderId = (int)$this->pdo->lastInsertId();
        
        // Verificar disponibilidade
        $stmt = $this->pdo->prepare('SELECT estoque FROM products WHERE id = ?');
        $stmt->execute([$materialId]);
        $material = $stmt->fetch();
        
        $estoqueDisponivel = (float)$material['estoque'];
        $quantidadeNecessaria = 20.0;
        
        $this->assertLessThan($quantidadeNecessaria, $estoqueDisponivel);
    }
    
    public function testUseReservedMaterial(): void {
        $productId = $this->createTestProduct();
        $materialId = $this->createTestProduct(['codigo' => 'MAT003', 'estoque' => 50.0]);
        
        // Criar ordem de produção
        $stmt = $this->pdo->prepare('
            INSERT INTO production_orders (tenant_id, numero, product_id, quantidade_solicitada, status)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, 'OP004', $productId, 10.0, 'em_producao']);
        $orderId = (int)$this->pdo->lastInsertId();
        
        // Criar reserva
        $stmt = $this->pdo->prepare('
            INSERT INTO estoque_reservas (tenant_id, production_order_id, product_id, quantidade_reservada, status)
            VALUES (?, ?, ?, ?, ?)
        ');
        $stmt->execute([$this->tenantId, $orderId, $materialId, 20.0, 'reservada']);
        $reservaId = (int)$this->pdo->lastInsertId();
        
        // Utilizar material
        $quantidadeUtilizada = 15.0;
        $stmt = $this->pdo->prepare('
            UPDATE estoque_reservas 
            SET quantidade_utilizada = quantidade_utilizada + ?,
                status = CASE 
                    WHEN quantidade_utilizada + ? >= quantidade_reservada THEN "utilizada"
                    ELSE "parcialmente_utilizada"
                END
            WHERE id = ?
        ');
        $stmt->execute([$quantidadeUtilizada, $quantidadeUtilizada, $reservaId]);
        
        // Verificar reserva
        $stmt = $this->pdo->prepare('SELECT * FROM estoque_reservas WHERE id = ?');
        $stmt->execute([$reservaId]);
        $reserva = $stmt->fetch();
        
        $this->assertEquals(15.0, $reserva['quantidade_utilizada']);
        $this->assertEquals('parcialmente_utilizada', $reserva['status']);
    }
}

