<?php

namespace Modules\PCP\Services;

use PDO;
use Exception;

/**
 * Serviço para gestão de ordens de produção
 */
class ProductionOrderService {
    private PDO $pdo;
    private string $tenantId;

    public function __construct(string $tenantId) {
        $this->tenantId = $tenantId;
        $this->pdo = \Gestoreasy\Core\Tenant\ConnectionManager::forTenant($tenantId);
    }

    /**
     * Cria uma nova ordem de produção
     */
    public function criarOrdem(array $dados): int {
        $this->pdo->beginTransaction();
        try {
            // Validar produto
            $stmt = $this->pdo->prepare('SELECT id FROM products WHERE id = ?');
            $stmt->execute([$dados['product_id']]);
            if (!$stmt->fetch()) {
                throw new Exception('Produto não encontrado');
            }

            // Gerar número da ordem
            $numero = $this->gerarNumeroOrdem();

            // Calcular custo previsto se BOM fornecido
            $custoPrevisto = 0;
            if (!empty($dados['bom_id'])) {
                $custoPrevisto = $this->calcularCustoBOM($dados['bom_id'], $dados['quantidade_solicitada']);
            }

            // Calcular datas previstas se roteiro fornecido
            $dataInicioPrevista = null;
            $dataFimPrevista = null;
            if (!empty($dados['routing_id'])) {
                $tempos = $this->calcularTempoProducao($dados['routing_id'], $dados['quantidade_solicitada']);
                $dataInicioPrevista = $dados['data_inicio_prevista'] ?? date('Y-m-d');
                $dataFimPrevista = date('Y-m-d', strtotime($dataInicioPrevista . " + {$tempos['dias']} days"));
            }

            // Criar ordem
            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            
            $stmt = $this->pdo->prepare('
                INSERT INTO production_orders (
                    tenant_id, numero, product_id, quantidade_solicitada,
                    bom_id, routing_id, data_solicitacao,
                    data_inicio_prevista, data_fim_prevista,
                    status, prioridade, custo_previsto,
                    observacoes, created_by
                ) VALUES (
                    ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
                )
            ');
            $stmt->execute([
                $this->tenantId,
                $numero,
                $dados['product_id'],
                $dados['quantidade_solicitada'],
                $dados['bom_id'] ?? null,
                $dados['routing_id'] ?? null,
                $dados['data_solicitacao'] ?? date('Y-m-d'),
                $dataInicioPrevista,
                $dataFimPrevista,
                $dados['status'] ?? 'rascunho',
                $dados['prioridade'] ?? 'normal',
                $custoPrevisto,
                $dados['observacoes'] ?? null,
                $userContext?->userId,
            ]);

            $orderId = (int)$this->pdo->lastInsertId();

            // Criar registros de consumo de materiais baseado no BOM
            if (!empty($dados['bom_id'])) {
                $this->criarConsumoMateriais($orderId, $dados['bom_id'], $dados['quantidade_solicitada']);
            }

            $this->pdo->commit();
            return $orderId;
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    /**
     * Aprova uma ordem de produção
     */
    public function aprovarOrdem(int $orderId): void {
        $this->pdo->beginTransaction();
        try {
            // Buscar ordem
            $stmt = $this->pdo->prepare('SELECT * FROM production_orders WHERE id = ? AND tenant_id = ?');
            $stmt->execute([$orderId, $this->tenantId]);
            $ordem = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$ordem) {
                throw new Exception('Ordem não encontrada');
            }

            if ($ordem['status'] !== 'pendente_aprovacao') {
                throw new Exception('Ordem não está pendente de aprovação');
            }

            // Validar disponibilidade de materiais
            $this->validarDisponibilidadeMateriais($orderId);

            // Aprovar
            $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
            
            $stmt = $this->pdo->prepare('
                UPDATE production_orders
                SET status = "aprovada",
                    aprovado_por = ?,
                    data_aprovacao = NOW()
                WHERE id = ?
            ');
            $stmt->execute([$userContext?->userId, $orderId]);

            $this->pdo->commit();
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    /**
     * Inicia produção
     */
    public function iniciarProducao(int $orderId): void {
        $this->pdo->beginTransaction();
        try {
            // Buscar ordem
            $stmt = $this->pdo->prepare('SELECT * FROM production_orders WHERE id = ? AND tenant_id = ?');
            $stmt->execute([$orderId, $this->tenantId]);
            $ordem = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$ordem) {
                throw new Exception('Ordem não encontrada');
            }

            if ($ordem['status'] !== 'aprovada') {
                throw new Exception('Ordem deve estar aprovada para iniciar produção');
            }

            // Reservar materiais
            $this->reservarMateriais($orderId);

            // Atualizar status
            $stmt = $this->pdo->prepare('
                UPDATE production_orders
                SET status = "em_producao",
                    data_inicio_real = CURDATE()
                WHERE id = ?
            ');
            $stmt->execute([$orderId]);

            // Registrar apontamento de início
            $this->registrarApontamento($orderId, 'inicio', [
                'data_hora' => date('Y-m-d H:i:s')
            ]);

            $this->pdo->commit();
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    /**
     * Finaliza produção
     */
    public function finalizarProducao(int $orderId, array $dados): void {
        $this->pdo->beginTransaction();
        try {
            // Buscar ordem
            $stmt = $this->pdo->prepare('SELECT * FROM production_orders WHERE id = ? AND tenant_id = ?');
            $stmt->execute([$orderId, $this->tenantId]);
            $ordem = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$ordem) {
                throw new Exception('Ordem não encontrada');
            }

            if ($ordem['status'] !== 'em_producao') {
                throw new Exception('Ordem deve estar em produção para finalizar');
            }

            $quantidadeProduzida = (float)($dados['quantidade_produzida'] ?? 0);
            $quantidadeAprovada = (float)($dados['quantidade_aprovada'] ?? $quantidadeProduzida);
            $quantidadeRejeitada = (float)($dados['quantidade_rejeitada'] ?? 0);

            // Atualizar ordem
            $stmt = $this->pdo->prepare('
                UPDATE production_orders
                SET status = "finalizada",
                    quantidade_produzida = ?,
                    quantidade_aprovada = ?,
                    quantidade_rejeitada = ?,
                    data_fim_real = CURDATE()
                WHERE id = ?
            ');
            $stmt->execute([$quantidadeProduzida, $quantidadeAprovada, $quantidadeRejeitada, $orderId]);

            // Dar baixa nos materiais consumidos
            $this->baixarMateriaisConsumidos($orderId);

            // Dar entrada no produto produzido
            $this->darEntradaProduto($orderId, $quantidadeAprovada);

            // Registrar apontamento de fim
            $this->registrarApontamento($orderId, 'fim', [
                'data_hora' => date('Y-m-d H:i:s'),
                'quantidade_produzida' => $quantidadeProduzida,
                'quantidade_aprovada' => $quantidadeAprovada,
                'quantidade_rejeitada' => $quantidadeRejeitada
            ]);

            $this->pdo->commit();
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    /**
     * Registra apontamento de produção
     */
    public function apontarProducao(int $orderId, array $dados): void {
        $this->registrarApontamento($orderId, $dados['tipo'] ?? 'quantidade', $dados);
    }

    /**
     * Cancela ordem de produção
     */
    public function cancelarOrdem(int $orderId): void {
        $this->pdo->beginTransaction();
        try {
            // Buscar ordem
            $stmt = $this->pdo->prepare('SELECT * FROM production_orders WHERE id = ? AND tenant_id = ?');
            $stmt->execute([$orderId, $this->tenantId]);
            $ordem = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$ordem) {
                throw new Exception('Ordem não encontrada');
            }

            if ($ordem['status'] === 'finalizada' || $ordem['status'] === 'cancelada') {
                throw new Exception('Ordem não pode ser cancelada neste status');
            }

            // Liberar reservas
            $this->liberarReservasOrdem($orderId);

            // Atualizar status
            $stmt = $this->pdo->prepare('
                UPDATE production_orders
                SET status = "cancelada"
                WHERE id = ?
            ');
            $stmt->execute([$orderId]);

            $this->pdo->commit();
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }

    /**
     * Lista reservas de uma ordem de produção
     */
    public function listarReservas(int $orderId): array {
        $stmt = $this->pdo->prepare('
            SELECT er.*, p.codigo as produto_codigo, p.nome as produto_nome
            FROM estoque_reservas er
            INNER JOIN products p ON er.product_id = p.id
            WHERE er.production_order_id = ? AND er.tenant_id = ?
            ORDER BY er.data_reserva DESC
        ');
        $stmt->execute([$orderId, $this->tenantId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /**
     * Lista alertas de estoque
     */
    public function listarAlertas(array $filters = []): array {
        $where = ['tenant_id = ?'];
        $params = [$this->tenantId];

        if (!empty($filters['status'])) {
            $where[] = 'status = ?';
            $params[] = $filters['status'];
        }

        if (!empty($filters['severidade'])) {
            $where[] = 'severidade = ?';
            $params[] = $filters['severidade'];
        }

        if (!empty($filters['production_order_id'])) {
            $where[] = 'production_order_id = ?';
            $params[] = $filters['production_order_id'];
        }

        $limit = (int)($filters['limit'] ?? 50);
        $offset = (int)($filters['offset'] ?? 0);

        $sql = '
            SELECT ea.*, p.codigo as produto_codigo, p.nome as produto_nome,
                   po.numero as ordem_numero
            FROM estoque_alertas ea
            INNER JOIN products p ON ea.product_id = p.id
            LEFT JOIN production_orders po ON ea.production_order_id = po.id
            WHERE ' . implode(' AND ', $where) . '
            ORDER BY ea.data_alertagem DESC
            LIMIT ? OFFSET ?
        ';
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(array_merge($params, [$limit, $offset]));

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    /**
     * Gera número da ordem
     */
    private function gerarNumeroOrdem(): string {
        $ano = date('Y');
        $stmt = $this->pdo->prepare('
            SELECT COUNT(*) as total
            FROM production_orders
            WHERE tenant_id = ? AND YEAR(created_at) = ?
        ');
        $stmt->execute([$this->tenantId, $ano]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        $numero = $result['total'] + 1;
        
        return "OP{$ano}" . str_pad($numero, 6, '0', STR_PAD_LEFT);
    }

    /**
     * Calcula custo do BOM
     */
    private function calcularCustoBOM(int $bomId, float $quantidade): float {
        $stmt = $this->pdo->prepare('
            SELECT SUM(bi.quantidade * COALESCE(p.preco, 0)) as custo_total
            FROM bom_items bi
            INNER JOIN products p ON bi.component_product_id = p.id
            WHERE bi.bom_id = ?
        ');
        $stmt->execute([$bomId]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        
        $custoUnitario = (float)($result['custo_total'] ?? 0);
        return $custoUnitario * $quantidade;
    }

    /**
     * Calcula tempo de produção
     */
    private function calcularTempoProducao(int $routingId, float $quantidade): array {
        $stmt = $this->pdo->prepare('
            SELECT tempo_setup_minutos, tempo_processamento_minutos
            FROM production_routing
            WHERE id = ?
        ');
        $stmt->execute([$routingId]);
        $routing = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$routing) {
            return ['minutos' => 0, 'horas' => 0, 'dias' => 0];
        }

        $tempoSetup = (int)($routing['tempo_setup_minutos'] ?? 0);
        $tempoProcessamento = (int)($routing['tempo_processamento_minutos'] ?? 0);
        
        $tempoTotal = $tempoSetup + ($tempoProcessamento * $quantidade);
        
        return [
            'minutos' => $tempoTotal,
            'horas' => round($tempoTotal / 60, 2),
            'dias' => ceil($tempoTotal / (60 * 8)) // 8 horas por dia
        ];
    }

    /**
     * Cria registros de consumo de materiais
     */
    private function criarConsumoMateriais(int $orderId, int $bomId, float $quantidade): void {
        $stmt = $this->pdo->prepare('
            SELECT * FROM bom_items WHERE bom_id = ?
        ');
        $stmt->execute([$bomId]);
        $itens = $stmt->fetchAll(PDO::FETCH_ASSOC);

        foreach ($itens as $item) {
            $quantidadePrevista = (float)$item['quantidade'] * $quantidade;
            
            $stmt = $this->pdo->prepare('
                INSERT INTO production_material_consumption (
                    tenant_id, order_id, material_product_id, bom_item_id, quantidade_prevista
                ) VALUES (?, ?, ?, ?, ?)
            ');
            $stmt->execute([
                $this->tenantId,
                $orderId,
                $item['component_product_id'],
                $item['id'],
                $quantidadePrevista
            ]);
        }
    }

    /**
     * Valida disponibilidade de materiais considerando reservas
     */
    private function validarDisponibilidadeMateriais(int $orderId): void {
        $stmt = $this->pdo->prepare('
            SELECT 
                mc.*, 
                p.codigo, 
                p.estoque,
                COALESCE(SUM(CASE WHEN er.status IN ("reservada", "parcialmente_utilizada") THEN er.quantidade_reservada - er.quantidade_utilizada ELSE 0 END), 0) as quantidade_reservada
            FROM production_material_consumption mc
            INNER JOIN products p ON mc.material_product_id = p.id
            LEFT JOIN estoque_reservas er ON er.product_id = p.id 
                AND er.status IN ("reservada", "parcialmente_utilizada")
                AND er.production_order_id != ?
            WHERE mc.order_id = ?
            GROUP BY mc.id, p.id, p.codigo, p.estoque, mc.quantidade_prevista
        ');
        $stmt->execute([$orderId, $orderId]);
        $materiais = $stmt->fetchAll(PDO::FETCH_ASSOC);

        $alertas = [];

        foreach ($materiais as $material) {
            $estoqueDisponivel = (float)$material['estoque'] - (float)$material['quantidade_reservada'];
            $quantidadeNecessaria = (float)$material['quantidade_prevista'];

            if ($estoqueDisponivel < $quantidadeNecessaria) {
                $quantidadeFaltante = $quantidadeNecessaria - $estoqueDisponivel;
                $severidade = $estoqueDisponivel <= 0 ? 'critica' : ($quantidadeFaltante > $quantidadeNecessaria * 0.5 ? 'alta' : 'media');
                
                // Criar alerta
                $this->criarAlertaFaltaEstoque(
                    $material['material_product_id'],
                    $orderId,
                    $quantidadeNecessaria,
                    $estoqueDisponivel,
                    $quantidadeFaltante,
                    $severidade
                );

                throw new Exception(
                    "Estoque insuficiente para material {$material['codigo']}. " .
                    "Disponível: {$estoqueDisponivel}, " .
                    "Necessário: {$quantidadeNecessaria}, " .
                    "Faltante: {$quantidadeFaltante}"
                );
            }
        }
    }

    /**
     * Reserva materiais para ordem de produção
     */
    private function reservarMateriais(int $orderId): void {
        // Buscar materiais necessários
        $stmt = $this->pdo->prepare('
            SELECT * FROM production_material_consumption
            WHERE order_id = ?
        ');
        $stmt->execute([$orderId]);
        $materiais = $stmt->fetchAll(PDO::FETCH_ASSOC);

        foreach ($materiais as $material) {
            $productId = (int)$material['material_product_id'];
            $quantidade = (float)$material['quantidade_prevista'];

            // Verificar disponibilidade considerando outras reservas
            $estoqueDisponivel = $this->getEstoqueDisponivel($productId, $orderId);

            if ($estoqueDisponivel < $quantidade) {
                throw new Exception(
                    "Estoque insuficiente para reserva. " .
                    "Produto ID: {$productId}, " .
                    "Disponível: {$estoqueDisponivel}, " .
                    "Necessário: {$quantidade}"
                );
            }

            // Criar reserva
            $dataExpiracao = date('Y-m-d H:i:s', strtotime('+30 days')); // Reserva expira em 30 dias
            
            $stmt = $this->pdo->prepare('
                INSERT INTO estoque_reservas (
                    tenant_id, production_order_id, product_id,
                    quantidade_reservada, status, data_reserva,
                    data_expiracao, material_consumption_id
                ) VALUES (?, ?, ?, ?, "reservada", NOW(), ?, ?)
            ');
            $stmt->execute([
                $this->tenantId,
                $orderId,
                $productId,
                $quantidade,
                $dataExpiracao,
                $material['id']
            ]);

            // Resolver alertas pendentes para este produto
            $this->resolverAlertas($productId, $orderId);
        }
    }

    /**
     * Obtém estoque disponível considerando reservas
     */
    private function getEstoqueDisponivel(int $productId, int $excludeOrderId = null): float {
        // Buscar estoque do produto
        $stmt = $this->pdo->prepare('SELECT estoque FROM products WHERE id = ?');
        $stmt->execute([$productId]);
        $product = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if (!$product) {
            return 0;
        }

        $estoqueTotal = (float)$product['estoque'];

        // Buscar quantidade reservada (excluindo a ordem atual se fornecida)
        $sql = '
            SELECT COALESCE(SUM(quantidade_reservada - quantidade_utilizada), 0) as quantidade_reservada
            FROM estoque_reservas
            WHERE product_id = ? 
            AND status IN ("reservada", "parcialmente_utilizada")
        ';
        $params = [$productId];

        if ($excludeOrderId) {
            $sql .= ' AND production_order_id != ?';
            $params[] = $excludeOrderId;
        }

        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);

        $quantidadeReservada = (float)($result['quantidade_reservada'] ?? 0);

        return $estoqueTotal - $quantidadeReservada;
    }

    /**
     * Utiliza material reservado (quando material é consumido)
     */
    private function utilizarMaterialReservado(int $orderId, int $productId, float $quantidade): void {
        $stmt = $this->pdo->prepare('
            SELECT * FROM estoque_reservas
            WHERE production_order_id = ? 
            AND product_id = ?
            AND status IN ("reservada", "parcialmente_utilizada")
            ORDER BY data_reserva ASC
            LIMIT 1
        ');
        $stmt->execute([$orderId, $productId]);
        $reserva = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$reserva) {
            throw new Exception("Reserva não encontrada para produto {$productId} na ordem {$orderId}");
        }

        $quantidadeDisponivel = (float)$reserva['quantidade_reservada'] - (float)$reserva['quantidade_utilizada'];
        
        if ($quantidade > $quantidadeDisponivel) {
            throw new Exception("Quantidade a utilizar ({$quantidade}) excede a quantidade reservada disponível ({$quantidadeDisponivel})");
        }

        $novaQuantidadeUtilizada = (float)$reserva['quantidade_utilizada'] + $quantidade;
        $novaQuantidadeDisponivel = (float)$reserva['quantidade_reservada'] - $novaQuantidadeUtilizada;

        // Atualizar reserva
        $status = $novaQuantidadeDisponivel <= 0 ? 'utilizada' : 'parcialmente_utilizada';
        
        $stmt = $this->pdo->prepare('
            UPDATE estoque_reservas
            SET quantidade_utilizada = ?,
                status = ?,
                data_utilizacao = COALESCE(data_utilizacao, NOW())
            WHERE id = ?
        ');
        $stmt->execute([$novaQuantidadeUtilizada, $status, $reserva['id']]);
    }

    /**
     * Libera reserva de material
     */
    public function liberarReserva(int $reservaId, float $quantidade = null): void {
        $stmt = $this->pdo->prepare('
            SELECT * FROM estoque_reservas
            WHERE id = ? AND tenant_id = ?
        ');
        $stmt->execute([$reservaId, $this->tenantId]);
        $reserva = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$reserva) {
            throw new Exception('Reserva não encontrada');
        }

        if ($reserva['status'] === 'liberada' || $reserva['status'] === 'cancelada') {
            throw new Exception('Reserva já foi liberada ou cancelada');
        }

        $quantidadeLiberar = $quantidade ?? ((float)$reserva['quantidade_reservada'] - (float)$reserva['quantidade_utilizada']);
        $novaQuantidadeLiberada = (float)$reserva['quantidade_liberada'] + $quantidadeLiberar;
        $quantidadeRestante = (float)$reserva['quantidade_reservada'] - (float)$reserva['quantidade_utilizada'] - $novaQuantidadeLiberada;

        $status = $quantidadeRestante <= 0 ? 'liberada' : $reserva['status'];

        $stmt = $this->pdo->prepare('
            UPDATE estoque_reservas
            SET quantidade_liberada = ?,
                status = ?,
                data_liberacao = COALESCE(data_liberacao, NOW())
            WHERE id = ?
        ');
        $stmt->execute([$novaQuantidadeLiberada, $status, $reservaId]);
    }

    /**
     * Libera todas as reservas de uma ordem de produção
     */
    public function liberarReservasOrdem(int $orderId): void {
        $stmt = $this->pdo->prepare('
            SELECT * FROM estoque_reservas
            WHERE production_order_id = ? 
            AND tenant_id = ?
            AND status IN ("reservada", "parcialmente_utilizada")
        ');
        $stmt->execute([$orderId, $this->tenantId]);
        $reservas = $stmt->fetchAll(PDO::FETCH_ASSOC);

        foreach ($reservas as $reserva) {
            $quantidadeLiberar = (float)$reserva['quantidade_reservada'] - (float)$reserva['quantidade_utilizada'];
            if ($quantidadeLiberar > 0) {
                $this->liberarReserva($reserva['id'], $quantidadeLiberar);
            }
        }
    }

    /**
     * Cria alerta de falta de estoque
     */
    private function criarAlertaFaltaEstoque(
        int $productId,
        int $orderId,
        float $quantidadeNecessaria,
        float $quantidadeDisponivel,
        float $quantidadeFaltante,
        string $severidade
    ): void {
        $stmt = $this->pdo->prepare('
            INSERT INTO estoque_alertas (
                tenant_id, product_id, production_order_id,
                tipo, severidade, quantidade_necessaria,
                quantidade_disponivel, quantidade_faltante,
                status, data_alertagem, mensagem
            ) VALUES (?, ?, ?, "falta_estoque", ?, ?, ?, ?, "pendente", NOW(), ?)
        ');

        $mensagem = "Falta de estoque detectada. Necessário: {$quantidadeNecessaria}, Disponível: {$quantidadeDisponivel}, Faltante: {$quantidadeFaltante}";

        $stmt->execute([
            $this->tenantId,
            $productId,
            $orderId,
            $severidade,
            $quantidadeNecessaria,
            $quantidadeDisponivel,
            $quantidadeFaltante,
            $mensagem
        ]);
    }

    /**
     * Resolve alertas de estoque
     */
    private function resolverAlertas(int $productId, int $orderId): void {
        $stmt = $this->pdo->prepare('
            UPDATE estoque_alertas
            SET status = "resolvido",
                data_resolucao = NOW()
            WHERE product_id = ?
            AND production_order_id = ?
            AND status = "pendente"
        ');
        $stmt->execute([$productId, $orderId]);
    }

    /**
     * Baixa materiais consumidos
     */
    private function baixarMateriaisConsumidos(int $orderId): void {
        $stmt = $this->pdo->prepare('
            SELECT * FROM production_material_consumption
            WHERE order_id = ?
        ');
        $stmt->execute([$orderId]);
        $materiais = $stmt->fetchAll(PDO::FETCH_ASSOC);

        foreach ($materiais as $material) {
            $quantidade = (float)($material['quantidade_consumida'] ?? $material['quantidade_prevista']);
            $productId = (int)$material['material_product_id'];
            
            // Utilizar material reservado
            try {
                $this->utilizarMaterialReservado($orderId, $productId, $quantidade);
            } catch (Exception $e) {
                // Se não houver reserva, apenas dar baixa no estoque
                // (pode acontecer se a ordem foi criada antes do sistema de reservas)
            }
            
            // Dar baixa no estoque
            $stmt = $this->pdo->prepare('
                UPDATE products
                SET estoque = estoque - ?
                WHERE id = ?
            ');
            $stmt->execute([$quantidade, $productId]);

            // Registrar movimentação
            $stmt = $this->pdo->prepare('
                INSERT INTO inventory_movements (
                    tenant_id, product_id, tipo, quantidade, motivo,
                    origem_tipo, origem_id, origem_numero
                ) VALUES (?, ?, "saida", ?, "Consumo produção", "producao", ?, ?)
            ');
            $stmt->execute([
                $this->tenantId,
                $productId,
                $quantidade,
                $orderId,
                "OP-{$orderId}"
            ]);
        }
    }

    /**
     * Dá entrada no produto produzido
     */
    private function darEntradaProduto(int $orderId, float $quantidade): void {
        // Buscar produto da ordem
        $stmt = $this->pdo->prepare('
            SELECT product_id FROM production_orders WHERE id = ?
        ');
        $stmt->execute([$orderId]);
        $ordem = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$ordem) {
            return;
        }

        // Dar entrada no estoque
        $stmt = $this->pdo->prepare('
            UPDATE products
            SET estoque = estoque + ?
            WHERE id = ?
        ');
        $stmt->execute([$quantidade, $ordem['product_id']]);

        // Registrar movimentação
        $stmt = $this->pdo->prepare('
            INSERT INTO inventory_movements (
                tenant_id, product_id, tipo, quantidade, motivo,
                origem_tipo, origem_id, origem_numero
            ) VALUES (?, ?, "entrada", ?, "Produção finalizada", "producao", ?, ?)
        ');
        $stmt->execute([
            $this->tenantId,
            $ordem['product_id'],
            $quantidade,
            $orderId,
            "OP-{$orderId}"
        ]);
    }

    /**
     * Registra apontamento
     */
    private function registrarApontamento(int $orderId, string $tipo, array $dados): void {
        $userContext = \Gestoreasy\Core\Auth\UserContext::getCurrent();
        
        $stmt = $this->pdo->prepare('
            INSERT INTO production_apontamentos (
                tenant_id, order_id, operation_id, tipo,
                quantidade_produzida, quantidade_aprovada, quantidade_rejeitada,
                data_hora, tempo_decorrido_minutos,
                qualidade_status, motivo_rejeicao,
                operador_id, observacoes
            ) VALUES (
                ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
            )
        ');
        $stmt->execute([
            $this->tenantId,
            $orderId,
            $dados['operation_id'] ?? null,
            $tipo,
            $dados['quantidade_produzida'] ?? 0,
            $dados['quantidade_aprovada'] ?? 0,
            $dados['quantidade_rejeitada'] ?? 0,
            $dados['data_hora'] ?? date('Y-m-d H:i:s'),
            $dados['tempo_decorrido_minutos'] ?? null,
            $dados['qualidade_status'] ?? null,
            $dados['motivo_rejeicao'] ?? null,
            $dados['operador_id'] ?? $userContext?->userId,
            $dados['observacoes'] ?? null,
        ]);
    }
}

