<?php

declare(strict_types=1);

namespace App\Controllers;

use Exception;
use PDO;

class OrcamentosAguaController extends VendasController
{
    protected array $moduleConfig = [
        'origin' => 'orcamento_agua',
        'slug' => 'orcamentos-agua',
        'routeBase' => '/orcamentos-agua',
        'viewBase' => 'orcamentos-agua',
        'icon' => 'bi bi-droplet',
        'createIcon' => 'bi bi-plus-circle',
        'singular' => 'DAV',
        'plural' => 'DAVs',
        'subtitle' => 'Controle e acompanhe os orçamentos de água mineral',
        'createSubtitle' => 'Cadastre um novo orçamento para entrega de água mineral',
        'numberPrefix' => 'OAM-',
        'statusModule' => 'orcamentos_agua',
        'generateReceivablesDefault' => false,
        'updateStockDefault' => false,
        'conversionEnabled' => false,
    ];

    public function index(): void
    {
        // Verificar permissão de visualização
        if (!$this->canView('orcamentos-agua')) {
            $this->response->forbidden('Você não tem permissão para visualizar orçamentos de água.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();
            $search = $this->request->get('search', '');
            $status = $this->request->get('status', '');

            if (!$companyId) {
                $this->error('Empresa não encontrada para o usuário atual');
                return;
            }

            $query = "
                SELECT v.*,
                    COALESCE(p.name, v.customer_name, 'Consumidor Final') as customer_name,
                    COALESCE(p.document, v.customer_document) as customer_document,
                    mp.name as payment_method_name,
                    u.name as vendor_name,
                    v.chave_nfe, v.numero_nfe, v.protocolo_nfe,
                    v.protocolo_cancelamento, v.data_cancelamento, v.pdf_cancelamento, v.xml_cancelamento,
                    v.observacoes_nfe
                FROM vendas v
                LEFT JOIN pessoas p ON v.customer_id = p.id
                LEFT JOIN metodos_pagamento mp ON v.payment_method_id = mp.id
                LEFT JOIN users u ON v.vendor_id = u.id
                WHERE v.company_id = :company_id
                  AND v.modulo_origem = :modulo_origem
            ";

            $params = [
                'company_id' => $companyId,
                'modulo_origem' => 'dav'
            ];

            if (!empty($search)) {
                $query .= " AND (v.sale_number LIKE :search OR p.name LIKE :search)";
                $params['search'] = "%{$search}%";
            }

            if (!empty($status)) {
                $query .= " AND v.status = :status";
                $params['status'] = $status;
            }

            $query .= " ORDER BY v.id DESC";

            $stmt = $this->db->prepare($query);
            $stmt->execute($params);
            $vendas = $stmt->fetchAll();

            // Busca status do módulo para o filtro
            $statusModule = $this->moduleStatusKey();
            $stmt = $this->db->prepare("
                SELECT codigo, nome, cor, icone
                FROM modulo_status
                WHERE company_id = :company_id
                  AND modulo = :modulo
                  AND ativo = 1
                ORDER BY ordem ASC
            ");
            $stmt->execute([
                'company_id' => $companyId,
                'modulo' => $statusModule
            ]);
            $statusVendas = $stmt->fetchAll();

            $this->view($this->moduleView('index'), $this->withModuleViewData([
                'vendas' => $vendas,
                'search' => $search,
                'status' => $status,
                'statusVendas' => $statusVendas,
                'nfseConfig' => [],
                'pageTitle' => $this->modulePlural(),
                'activeMenu' => $this->moduleSlug()
            ]));
        } catch (Exception $e) {
            error_log("Erro ao carregar {$this->modulePlural()}: " . $e->getMessage());
            $this->error('Erro ao carregar ' . mb_strtolower($this->modulePlural()));
        }
    }

    public function edit(): void
    {
        try {
            $id = (int) $this->request->get('id');
            $companyId = $this->getCompanyId();

            if (!$id || !$companyId) {
                $this->error('ID inválido ou empresa não encontrada');
                return;
            }

            // Buscar o orçamento
            $stmt = $this->db->prepare("
                SELECT v.*
                FROM vendas v
                WHERE v.id = :id
                  AND v.company_id = :company_id
                  AND v.modulo_origem = :modulo_origem
                LIMIT 1
            ");
            $stmt->execute([
                'id' => $id,
                'company_id' => $companyId,
                'modulo_origem' => 'dav'
            ]);
            $venda = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$venda) {
                $this->error('Orçamento não encontrado');
                return;
            }

            // Buscar clientes
            $stmt = $this->db->prepare("
                SELECT id, name, trade_name, document, email, phone, mobile
                FROM pessoas
                WHERE company_id = :company_id
                  AND is_active = 1
                  AND (tipo_cliente = 1 OR tipo_fornecedor = 1)
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $clientes = $stmt->fetchAll();

            // Verificar se as colunas fator_cashback, lancar_quebra e lancar_troca existem na tabela produtos
            $colunaFatorCashbackExiste = false;
            $colunaLancarQuebraExiste = false;
            $colunaLancarTrocaExiste = false;
            try {
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE 'fator_cashback'");
                $colunaFatorCashbackExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE 'lancar_quebra'");
                $colunaLancarQuebraExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE 'lancar_troca'");
                $colunaLancarTrocaExiste = $stmtCheck->fetch() !== false;
            } catch (Exception $e) {
                // Ignorar erro de verificação
            }

            // Buscar produtos (incluindo fator_cashback, lancar_quebra e lancar_troca se existirem)
            $fatorCashbackField = $colunaFatorCashbackExiste ? 'COALESCE(fator_cashback, 0) as cashback' : '0 as cashback';
            $lancarQuebraField = $colunaLancarQuebraExiste ? 'COALESCE(lancar_quebra, "Sim") as lancar_quebra' : '"Sim" as lancar_quebra';
            $lancarTrocaField = $colunaLancarTrocaExiste ? 'COALESCE(lancar_troca, "Sim") as lancar_troca' : '"Sim" as lancar_troca';
            $stmt = $this->db->prepare("
                SELECT id, name, sku, price, stock_quantity, unit,
                       {$fatorCashbackField},
                       {$lancarQuebraField},
                       {$lancarTrocaField}
                FROM produtos
                WHERE company_id = :company_id
                  AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $produtos = $stmt->fetchAll();

            // Buscar métodos de pagamento
            $stmt = $this->db->prepare("
                SELECT id, name, type FROM metodos_pagamento
                WHERE company_id = :company_id AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $metodosPagamento = $stmt->fetchAll();

            // Buscar vendedores
            $stmt = $this->db->prepare("
                SELECT id, name FROM users
                WHERE company_id = :company_id AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $vendedores = $stmt->fetchAll() ?: [];

            // Buscar profissionais para os itens (usuários ativos)
            $stmt = $this->db->prepare("
                SELECT id, name FROM users
                WHERE company_id = :company_id AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $profissionais = $stmt->fetchAll() ?: [];

            // Buscar status do módulo
            $stmt = $this->db->prepare("
                SELECT codigo, nome, descricao, cor, icone, ordem, is_default
                FROM modulo_status
                WHERE company_id = :company_id
                  AND modulo = :modulo
                  AND ativo = 1
                ORDER BY ordem ASC
            ");
            $stmt->execute([
                'company_id' => $companyId,
                'modulo' => $this->moduleStatusKey()
            ]);
            $statusVendas = $stmt->fetchAll() ?: [];

            // Verificar se as colunas diferenca, conferido, cashback, falta_r e qtd_informada existem
            $colunaDiferencaExiste = false;
            $colunaConferidoExiste = false;
            $colunaCashbackExiste = false;
            $colunaFaltaRExiste = false;
            $colunaQtdInformadaExiste = false;
            try {
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'diferenca'");
                $colunaDiferencaExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'conferido'");
                $colunaConferidoExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'cashback'");
                $colunaCashbackExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'falta_r'");
                $colunaFaltaRExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'qtd_informada'");
                $colunaQtdInformadaExiste = $stmtCheck->fetch() !== false;
            } catch (Exception $e) {
                // Ignorar erro de verificação
            }

            // Montar campos dinamicamente baseado na existência das colunas
            $qtdInformadaField = $colunaQtdInformadaExiste ? 'COALESCE(qtd_informada, 0) as qtd_informada,' : '0 as qtd_informada,';
            $conferidoField = $colunaConferidoExiste ? 'COALESCE(conferido, 0) as conferido,' : '0 as conferido,';
            $diferencaField = $colunaDiferencaExiste
                ? ($colunaConferidoExiste
                    ? 'COALESCE(diferenca, quantity - COALESCE(conferido, 0)) as diferenca,'
                    : 'COALESCE(diferenca, quantity) as diferenca,')
                : ($colunaConferidoExiste
                    ? '(quantity - COALESCE(conferido, 0)) as diferenca,'
                    : 'quantity as diferenca,');
            $cashbackField = $colunaCashbackExiste ? 'COALESCE(cashback, 0) as cashback,' : '0 as cashback,';
            $faltaRField = $colunaFaltaRExiste ? 'COALESCE(falta_r, 0) as falta_r,' : '0 as falta_r,';
            $compraField = $colunaCompraExiste ? 'COALESCE(compra, 0) as compra,' : '0 as compra,';

            // Buscar itens da venda incluindo quebra, troca, conferido, diferenca, cashback, falta_r, compra e qtd_informada
            $stmt = $this->db->prepare("
                SELECT
                    id, company_id, venda_id, product_id, product_name, product_sku,
                    quantity, unit_price, discount, discount_type, total_price, notes,
                    {$qtdInformadaField}
                    COALESCE(quebra, 0) as quebra,
                    COALESCE(troca, 0) as troca,
                    {$conferidoField}
                    {$diferencaField}
                    {$cashbackField}
                    {$compraField}
                    {$faltaRField}
                    numero_serie,
                    lote,
                    fabricacao,
                    validade,
                    created_at
                FROM vendas_itens
                WHERE venda_id = :venda_id AND company_id = :company_id
                ORDER BY id ASC
            ");
            $stmt->execute(['venda_id' => $id, 'company_id' => $companyId]);
            $itens = $stmt->fetchAll();

            $user = $this->getUser();
            $userRole = strtolower(trim($user['role'] ?? ''));

            // Filtrar itens baseado no role do usuário
            if ($userRole === 'operator' || $userRole === 'operador') {
                // Se for operator/operador, mostrar apenas produtos com id = 2
                $itens = array_filter($itens, function($item) {
                    return (int) $item['product_id'] === 2;
                });
            } else {
                // Caso contrário, mostrar apenas produtos com id = 1 ou id = 2
                $itens = array_filter($itens, function($item) {
                    $produtoId = (int) $item['product_id'];
                    return $produtoId === 1 || $produtoId === 2;
                });
            }
            // Reindexar array após filtro
            $itens = array_values($itens);

            $this->view($this->moduleView('edit'), $this->withModuleViewData([
                'venda' => $venda,
                'itens' => $itens,
                'clientes' => $clientes,
                'produtos' => $produtos,
                'metodosPagamento' => $metodosPagamento,
                'vendedores' => $vendedores,
                'profissionais' => $profissionais,
                'statusVendas' => $statusVendas,
                'user' => $user,
                'userRole' => $userRole,
                'pageTitle' => 'Editar ' . $this->moduleSingular() . ' #' . $venda['sale_number'],
                'activeMenu' => $this->moduleSlug()
            ]));
        } catch (Exception $e) {
            error_log("Erro ao editar {$this->moduleSingular()}: " . $e->getMessage());
            $this->error('Erro ao carregar formulário: ' . $e->getMessage());
        }
    }

    public function create(): void
    {
        // Verificar permissão de criação
        if (!$this->canCreate('orcamentos-agua')) {
            $this->response->forbidden('Você não tem permissão para criar orçamentos de água.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();

            if (!$companyId) {
                $this->error('Empresa não encontrada para o usuário atual');
                return;
            }

            $stmt = $this->db->prepare("
                SELECT id, name, trade_name, document, email, phone, mobile
                FROM pessoas
                WHERE company_id = :company_id
                  AND is_active = 1
                  AND (tipo_cliente = 1 OR tipo_fornecedor = 1)
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $clientes = $stmt->fetchAll(PDO::FETCH_ASSOC);

            // Verificar se as colunas fator_cashback, lancar_quebra e lancar_troca existem na tabela produtos
            $colunaFatorCashbackExiste = false;
            $colunaLancarQuebraExiste = false;
            $colunaLancarTrocaExiste = false;
            try {
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE 'fator_cashback'");
                $colunaFatorCashbackExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE 'lancar_quebra'");
                $colunaLancarQuebraExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE 'lancar_troca'");
                $colunaLancarTrocaExiste = $stmtCheck->fetch() !== false;
            } catch (Exception $e) {
                // Ignorar erro de verificação
            }

            $fatorCashbackField = $colunaFatorCashbackExiste ? 'COALESCE(fator_cashback, 0) as cashback' : '0 as cashback';
            $lancarQuebraField = $colunaLancarQuebraExiste ? 'COALESCE(lancar_quebra, "Sim") as lancar_quebra' : '"Sim" as lancar_quebra';
            $lancarTrocaField = $colunaLancarTrocaExiste ? 'COALESCE(lancar_troca, "Sim") as lancar_troca' : '"Sim" as lancar_troca';
            $stmt = $this->db->prepare("
                SELECT id, name, sku, price, unit,
                       {$fatorCashbackField},
                       {$lancarQuebraField},
                       {$lancarTrocaField}
                FROM produtos
                WHERE company_id = :company_id
                  AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $produtos = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $user = $this->getUser();
            $userRole = strtolower(trim($user['role'] ?? ''));

            // Filtrar produtos baseado no role do usuário
            if ($userRole === 'operator' || $userRole === 'operador') {
                // Se for operator/operador, mostrar apenas produtos com id = 2
                $produtos = array_filter($produtos, function($produto) {
                    return (int) $produto['id'] === 2;
                });
            } else {
                // Caso contrário, mostrar apenas produtos com id = 1 ou id = 2
                $produtos = array_filter($produtos, function($produto) {
                    $produtoId = (int) $produto['id'];
                    return $produtoId === 1 || $produtoId === 2;
                });
            }
            // Reindexar array após filtro
            $produtos = array_values($produtos);

            $proximoNumero = $this->gerarProximoNumeroOrcamento($companyId);

            // Buscar profissionais para os itens (usuários ativos)
            $stmt = $this->db->prepare("
                SELECT id, name FROM users
                WHERE company_id = :company_id AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            $profissionais = $stmt->fetchAll() ?: [];

            $this->view($this->moduleView('create'), $this->withModuleViewData([
                'clientes' => $clientes,
                'produtos' => $produtos,
                'profissionais' => $profissionais,
                'proximoNumero' => $proximoNumero,
                'user' => $user,
                'userRole' => $userRole,
                'pageTitle' => 'Novo Orçamento de Água',
                'activeMenu' => $this->moduleSlug(),
            ]));
        } catch (Exception $e) {
            error_log('[OrcamentosAguaController] erro ao carregar formulário: ' . $e->getMessage());
            $this->registrarLog('Erro ao carregar formulário: ' . $e->getMessage());
            $this->error('Erro ao carregar formulário de orçamento.');
        }
    }

    public function store(): void
    {
        // Verificar permissão de criação
        if (!$this->canCreate('orcamentos-agua')) {
            $this->response->forbidden('Você não tem permissão para criar orçamentos de água.');
            return;
        }

        try {
            $companyId = $this->getCompanyId();
            $user = $this->getUser();
            $userId = $this->getUserId();

            if (!$companyId || !$userId) {
                $this->error('Usuário não autenticado ou empresa não encontrada');
                return;
            }

            $customerId = (int) ($this->request->post('customer_id') ?? 0);
            $notes = trim((string) $this->request->post('notes'));
            $quantities = $this->request->post('quantities') ?? [];

            if ($customerId <= 0) {
                $this->error('Selecione um cliente para o orçamento');
                return;
            }

            if (!is_array($quantities) || empty(array_filter($quantities, function ($qty) {
                return (float) $qty > 0;
            }))) {
                $this->error('Informe ao menos um produto com quantidade maior que zero');
                return;
            }

            $produtoIds = array_keys(array_filter($quantities, function ($qty) {
                return (float) $qty > 0;
            }));

            $placeholders = implode(',', array_fill(0, count($produtoIds), '?'));
            $stmt = $this->db->prepare(
                "SELECT id, name, sku, price
                FROM produtos
                WHERE company_id = ?
                  AND id IN ($placeholders)"
            );
            $params = array_merge([$companyId], $produtoIds);
            $stmt->execute($params);
            $produtos = [];
            foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $produto) {
                $produtos[(int) $produto['id']] = $produto;
            }

            if (empty($produtos)) {
                $this->error('Nenhum produto válido selecionado');
                return;
            }

            $stmt = $this->db->prepare("
                SELECT id, name, document
                FROM pessoas
                WHERE company_id = :company_id AND id = :id
                LIMIT 1
            ");
            $stmt->execute([
                'company_id' => $companyId,
                'id' => $customerId,
            ]);
            $cliente = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$cliente) {
                $this->error('Cliente inválido para este orçamento');
                return;
            }

            $subtotal = 0.0;
            $itensPreparados = [];
            foreach ($produtoIds as $produtoId) {
                if (empty($produtos[$produtoId])) {
                    continue;
                }

                $quantidade = (float) str_replace(',', '.', (string) $quantities[$produtoId]);
                if ($quantidade <= 0) {
                    continue;
                }

                $unitPrice = (float) ($produtos[$produtoId]['price'] ?? 0);
                $totalItem = $unitPrice * $quantidade;
                $subtotal += $totalItem;

               $itensPreparados[] = [
                    'product_id' => $produtoId,
                    'product_name' => $produtos[$produtoId]['name'] ?? '',
                    'product_sku' => $produtos[$produtoId]['sku'] ?? '',
                    'quantity' => $quantidade,
                    'unit_price' => $unitPrice,
                    'total_price' => $totalItem,
                ];
            }

            if (empty($itensPreparados)) {
                $this->error('Informe ao menos um item válido para o orçamento');
                return;
            }

            $saleNumber = $this->gerarProximoNumeroOrcamento($companyId);

            $this->db->beginTransaction();

            $stmt = $this->db->prepare("
                INSERT INTO vendas (
                    company_id, modulo_origem, customer_type, customer_id, customer_name, customer_document,
                    sale_number, sale_date, subtotal, total, status, notes, vendor_id,
                    generate_receivables, update_stock, created_at, updated_at
                ) VALUES (
                    :company_id, :modulo_origem, :customer_type, :customer_id, :customer_name, :customer_document,
                    :sale_number, :sale_date, :subtotal, :total, :status, :notes, :vendor_id,
                    :generate_receivables, :update_stock, NOW(), NOW()
                )
            ");

            $stmt->execute([
                'company_id' => $companyId,
                'modulo_origem' => $this->moduleOrigin(),
                'customer_type' => 'pessoa',
                'customer_id' => $customerId,
                'customer_name' => $cliente['name'] ?? null,
                'customer_document' => $cliente['document'] ?? null,
                'sale_number' => $saleNumber,
                'sale_date' => date('Y-m-d'),
                'subtotal' => $subtotal,
                'total' => $subtotal,
                'status' => 'orcamento',
                'notes' => $notes,
                'vendor_id' => $userId,
                'generate_receivables' => 0,
                'update_stock' => 0,
            ]);

            $orcamentoId = (int) $this->db->lastInsertId();

            // Verificar se as colunas diferenca, conferido, cashback, falta_r, qtd_informada, compra e profissional_id existem
            $colunaDiferencaExiste = false;
            $colunaConferidoExiste = false;
            $colunaCashbackExiste = false;
            $colunaFaltaRExiste = false;
            $colunaQtdInformadaExiste = false;
            $colunaCompraExiste = false;
            $colunaProfissionalIdExiste = false;
            try {
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'diferenca'");
                $colunaDiferencaExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'conferido'");
                $colunaConferidoExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'cashback'");
                $colunaCashbackExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'falta_r'");
                $colunaFaltaRExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'qtd_informada'");
                $colunaQtdInformadaExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'compra'");
                $colunaCompraExiste = $stmtCheck->fetch() !== false;
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'profissional_id'");
                $colunaProfissionalIdExiste = $stmtCheck->fetch() !== false;
            } catch (Exception $e) {
                // Ignorar erro de verificação
            }

            // Preparar SQL de inserção baseado na existência das colunas
            $campos = ['company_id', 'venda_id', 'product_id', 'product_name', 'product_sku',
                      'quantity', 'unit_price', 'discount', 'discount_type', 'total_price',
                      'troca', 'quebra'];
            $valores = [':company_id', ':venda_id', ':product_id', ':product_name', ':product_sku',
                       ':quantity', ':unit_price', ':discount', ':discount_type', ':total_price',
                       ':troca', ':quebra'];

            if ($colunaQtdInformadaExiste) {
                $campos[] = 'qtd_informada';
                $valores[] = ':qtd_informada';
            }
            if ($colunaConferidoExiste) {
                $campos[] = 'conferido';
                $valores[] = ':conferido';
            }
            if ($colunaDiferencaExiste) {
                $campos[] = 'diferenca';
                $valores[] = ':diferenca';
            }
            if ($colunaCashbackExiste) {
                $campos[] = 'cashback';
                $valores[] = ':cashback';
            }
            if ($colunaCompraExiste) {
                $campos[] = 'compra';
                $valores[] = ':compra';
            }
            if ($colunaFaltaRExiste) {
                $campos[] = 'falta_r';
                $valores[] = ':falta_r';
            }
            if ($colunaProfissionalIdExiste) {
                $campos[] = 'profissional_id';
                $valores[] = ':profissional_id';
            }

            $stmtItem = $this->db->prepare("
                INSERT INTO vendas_itens (" . implode(', ', $campos) . ")
                VALUES (" . implode(', ', $valores) . ")
            ");

            $itensData = $this->request->post('itens', []);
            // Buscar profissional_id geral se existir
            $profissionalIdGeral = $this->request->post('profissional_id') ?: null;

            foreach ($itensPreparados as $item) {
                $produtoId = $item['product_id'];
                $itemData = $itensData[$produtoId] ?? [];

                $qtdInformada = (float) ($itemData['qtd_informada'] ?? $item['quantity']);
                $conferido = (float) ($itemData['conferido'] ?? 0);
                $quantidade = $item['quantity'];
                $diferenca = (float) ($itemData['diferenca'] ?? ($qtdInformada - $conferido));
                $cashback = (float) ($itemData['cashback'] ?? 0);
                $compra = (float) ($itemData['compra'] ?? 0);
                $faltaR = (float) ($itemData['falta_r'] ?? 0);
                // Buscar profissional_id do item ou usar o geral
                $profissionalId = !empty($itemData['profissional_id']) ? (int)$itemData['profissional_id'] : ($profissionalIdGeral ? (int)$profissionalIdGeral : null);

                $params = [
                    'company_id' => $companyId,
                    'venda_id' => $orcamentoId,
                    'product_id' => $item['product_id'],
                    'product_name' => $item['product_name'],
                    'product_sku' => $item['product_sku'],
                    'quantity' => $item['quantity'],
                    'unit_price' => $item['unit_price'],
                    'discount' => 0,
                    'discount_type' => 'fixed',
                    'total_price' => $item['total_price'],
                    'troca' => (float) ($itemData['troca'] ?? 0),
                    'quebra' => (float) ($itemData['quebra'] ?? 0),
                ];

                if ($colunaQtdInformadaExiste) {
                    $params['qtd_informada'] = $qtdInformada;
                }
                if ($colunaConferidoExiste) {
                    $params['conferido'] = $conferido;
                }
                if ($colunaDiferencaExiste) {
                    $params['diferenca'] = $diferenca;
                }
                if ($colunaCashbackExiste) {
                    $params['cashback'] = $cashback;
                }
                if ($colunaCompraExiste) {
                    $params['compra'] = $compra;
                }
                if ($colunaFaltaRExiste) {
                    $params['falta_r'] = $faltaR;
                }
                if ($colunaProfissionalIdExiste) {
                    // Sempre adicionar profissional_id aos params se a coluna existir (pode ser null)
                    $params['profissional_id'] = $profissionalId;
                }

                $stmtItem->execute($params);
            }

            $this->logActivity('create', 'orcamentos_agua', $orcamentoId, [
                'cliente' => $cliente['name'] ?? '',
                'total' => $subtotal,
                'responsavel' => $user['name'] ?? '',
            ]);

            $this->db->commit();

            $this->registrarLog(sprintf(
                'Orçamento %s criado para cliente %s (ID %d) por %s (ID %d) - Total: %0.2f',
                $saleNumber,
                $cliente['name'] ?? '-',
                $customerId,
                $user['name'] ?? '-',
                $userId,
                $subtotal
            ));

            $this->session->flash('success_message', 'Orçamento registrado com sucesso.');
            $this->redirect($this->moduleRouteBase());
        } catch (Exception $e) {
            if ($this->db && $this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log('[OrcamentosAguaController] erro ao salvar orçamento: ' . $e->getMessage());
            $this->registrarLog('Erro ao salvar orçamento: ' . $e->getMessage());
            $this->session->flash('error_message', 'Erro ao salvar orçamento: ' . $e->getMessage());
            $this->redirect($this->moduleRouteBase() . '/criar');
        }
    }

    private function gerarProximoNumeroOrcamento(int $companyId): string
    {
        $prefix = $this->moduleNumberPrefix();
        $prefixLength = strlen($prefix);
        $startPos = $prefixLength + 1;

        $stmt = $this->db->prepare("
            SELECT MAX(CAST(SUBSTRING(sale_number, {$startPos}) AS UNSIGNED)) AS maxnum
            FROM vendas
            WHERE company_id = :company_id
              AND sale_number LIKE :prefix
        ");
        $stmt->execute([
            'company_id' => $companyId,
            'prefix' => $prefix . '%',
        ]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        $next = ((int) ($row['maxnum'] ?? 0)) + 1;

        return $prefix . str_pad((string) $next, 6, '0', STR_PAD_LEFT);
    }

    public function updateStatus(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $userId = $this->getUserId();

            if (!$companyId || !$userId) {
                $this->error('Usuário não autenticado ou empresa não encontrada');
                return;
            }

            // Garantir que os status existam antes de tentar atualizar
            $this->garantirStatusOrcamentosAgua($companyId);

            $orcamentoId = (int) $this->request->post('id');
            $novoStatus = trim((string) $this->request->post('status'));

            error_log("[OrcamentosAguaController] updateStatus - ID: {$orcamentoId}, Status: {$novoStatus}, Company: {$companyId}, User: {$userId}");

            if ($orcamentoId <= 0) {
                if ($this->request->isAjax()) {
                    $this->response->json([
                        'success' => false,
                        'message' => 'ID do orçamento inválido',
                    ], 400);
                } else {
                    $this->error('ID do orçamento inválido');
                }
                return;
            }

            if (empty($novoStatus)) {
                if ($this->request->isAjax()) {
                    $this->response->json([
                        'success' => false,
                        'message' => 'Status não informado',
                    ], 400);
                } else {
                    $this->error('Status não informado');
                }
                return;
            }

            // Buscar o orçamento
            $stmt = $this->db->prepare("
                SELECT id, status, sale_number, customer_name
                FROM vendas
                WHERE id = :id
                  AND company_id = :company_id
                  AND modulo_origem = :modulo_origem
                LIMIT 1
            ");
            $stmt->execute([
                'id' => $orcamentoId,
                'company_id' => $companyId,
                'modulo_origem' => 'dav', // Usar 'dav' como definido no módulo
            ]);
            $orcamento = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$orcamento) {
                if ($this->request->isAjax()) {
                    $this->response->json([
                        'success' => false,
                        'message' => 'Orçamento não encontrado',
                    ], 404);
                } else {
                    $this->error('Orçamento não encontrado');
                }
                return;
            }

            $statusAtual = $orcamento['status'] ?? 'orcamento';

            // Verificar se o novo status existe no módulo
            $stmt = $this->db->prepare("
                SELECT codigo, nome, gera_financeiro, movimenta_estoque, ordem, is_final
                FROM modulo_status
                WHERE company_id = :company_id
                  AND modulo = :modulo
                  AND codigo = :codigo
                  AND ativo = 1
                LIMIT 1
            ");
            $stmt->execute([
                'company_id' => $companyId,
                'modulo' => $this->moduleStatusKey(),
                'codigo' => $novoStatus,
            ]);
            $statusInfo = $stmt->fetch(PDO::FETCH_ASSOC);

            error_log("[OrcamentosAguaController] updateStatus - Status buscado: {$novoStatus}, Módulo: {$this->moduleStatusKey()}, Status encontrado: " . ($statusInfo ? 'SIM' : 'NÃO'));

            if (!$statusInfo) {
                $errorMsg = "Status '{$novoStatus}' não encontrado no módulo '{$this->moduleStatusKey()}'";
                error_log("[OrcamentosAguaController] updateStatus - ERRO: {$errorMsg}");
                if ($this->request->isAjax()) {
                    $this->response->json([
                        'success' => false,
                        'message' => $errorMsg,
                    ], 400);
                } else {
                    $this->error($errorMsg);
                }
                return;
            }

            // Verificar ordem de transição (não pode voltar para status anterior se o atual for final)
            if ($statusAtual !== $novoStatus) {
                $stmtAtual = $this->db->prepare("
                    SELECT ordem, is_final
                    FROM modulo_status
                    WHERE company_id = :company_id
                      AND modulo = :modulo
                      AND codigo = :codigo
                      AND ativo = 1
                    LIMIT 1
                ");
                $stmtAtual->execute([
                    'company_id' => $companyId,
                    'modulo' => $this->moduleStatusKey(),
                    'codigo' => $statusAtual,
                ]);
                $statusAtualInfo = $stmtAtual->fetch(PDO::FETCH_ASSOC);

                if ($statusAtualInfo && (int) $statusAtualInfo['is_final'] === 1) {
                    if ($this->request->isAjax()) {
                        $this->response->json([
                            'success' => false,
                            'message' => 'Não é possível alterar o status de um orçamento finalizado',
                        ], 400);
                    } else {
                        $this->error('Não é possível alterar o status de um orçamento finalizado');
                    }
                    return;
                }

                // Validar ordem: não pode pular etapas (opcional - pode ser removido se necessário)
                $ordemAtual = (int) ($statusAtualInfo['ordem'] ?? 0);
                $ordemNova = (int) ($statusInfo['ordem'] ?? 0);

                if ($ordemNova < $ordemAtual) {
                    // Permitir voltar apenas se não for status final
                    if ((int) $statusInfo['is_final'] === 1) {
                        if ($this->request->isAjax()) {
                            $this->response->json([
                                'success' => false,
                                'message' => 'Não é possível voltar para um status final',
                            ], 400);
                        } else {
                            $this->error('Não é possível voltar para um status final');
                        }
                        return;
                    }
                }
            }

            $this->db->beginTransaction();

            // Atualizar status
            $stmt = $this->db->prepare("
                UPDATE vendas
                SET status = :status,
                    updated_at = NOW()
                WHERE id = :id
                  AND company_id = :company_id
            ");
            $stmt->execute([
                'status' => $novoStatus,
                'id' => $orcamentoId,
                'company_id' => $companyId,
            ]);

            // Se o status movimenta estoque, atualizar estoque
            if ((int) $statusInfo['movimenta_estoque'] === 1) {
                $this->atualizarEstoqueOrcamento($orcamentoId);
            }

            // Registrar log
            $this->logActivity('update_status', 'orcamentos_agua', $orcamentoId, [
                'status_anterior' => $statusAtual,
                'status_novo' => $novoStatus,
                'usuario' => $userId,
            ]);

            $this->db->commit();

            $this->session->flash('success_message', sprintf(
                'Status alterado de "%s" para "%s" com sucesso.',
                $statusAtual,
                $statusInfo['nome']
            ));

            if ($this->request->isAjax()) {
                $this->response->json([
                    'success' => true,
                    'message' => 'Status atualizado com sucesso',
                    'status' => $novoStatus,
                    'status_nome' => $statusInfo['nome'],
                ]);
            } else {
                $this->redirect($this->moduleRouteBase());
            }
        } catch (Exception $e) {
            if ($this->db && $this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log('[OrcamentosAguaController] erro ao atualizar status: ' . $e->getMessage());
            $this->registrarLog('Erro ao atualizar status: ' . $e->getMessage());

            if ($this->request->isAjax()) {
                $this->response->json([
                    'success' => false,
                    'message' => 'Erro ao atualizar status: ' . $e->getMessage(),
                ], 500);
            } else {
                $this->session->flash('error_message', 'Erro ao atualizar status: ' . $e->getMessage());
                $this->redirect($this->moduleRouteBase());
            }
        }
    }

    private function atualizarEstoqueOrcamento(int $orcamentoId): void
    {
        try {
            $companyId = $this->getCompanyId();

            // Buscar itens do orçamento
            $stmt = $this->db->prepare("
                SELECT product_id, quantity
                FROM vendas_itens
                WHERE venda_id = :venda_id
                  AND company_id = :company_id
            ");
            $stmt->execute([
                'venda_id' => $orcamentoId,
                'company_id' => $companyId,
            ]);
            $itens = $stmt->fetchAll(PDO::FETCH_ASSOC);

            // Atualizar estoque (reduzir)
            foreach ($itens as $item) {
                $stmt = $this->db->prepare("
                    UPDATE produtos
                    SET stock_quantity = stock_quantity - :quantity
                    WHERE id = :product_id
                      AND company_id = :company_id
                ");
                $stmt->execute([
                    'quantity' => (float) $item['quantity'],
                    'product_id' => (int) $item['product_id'],
                    'company_id' => $companyId,
                ]);
            }
        } catch (Exception $e) {
            error_log('[OrcamentosAguaController] erro ao atualizar estoque: ' . $e->getMessage());
            throw $e;
        }
    }

    public function getItens(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $vendaId = (int) $this->request->get('venda_id');

            if (!$companyId || $vendaId <= 0) {
                $this->response->json([
                    'success' => false,
                    'message' => 'Parâmetros inválidos',
                ], 400);
                return;
            }

            $stmt = $this->db->prepare("
                SELECT id, product_id, product_name, quantity, quebra, troca
                FROM vendas_itens
                WHERE venda_id = :venda_id
                  AND company_id = :company_id
            ");
            $stmt->execute([
                'venda_id' => $vendaId,
                'company_id' => $companyId,
            ]);
            $itens = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $this->response->json([
                'success' => true,
                'itens' => $itens,
            ]);
        } catch (Exception $e) {
            error_log('[OrcamentosAguaController] erro ao buscar itens: ' . $e->getMessage());
            $this->response->json([
                'success' => false,
                'message' => 'Erro ao buscar itens',
            ], 500);
        }
    }

    public function atualizarQuebraTroca(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $vendaId = (int) $this->request->post('venda_id');
            $tipo = trim((string) $this->request->post('tipo')); // 'quebra' ou 'troca'
            $valor = (float) $this->request->post('valor');

            if (!$companyId || $vendaId <= 0 || !in_array($tipo, ['quebra', 'troca'])) {
                $this->response->json([
                    'success' => false,
                    'message' => 'Parâmetros inválidos',
                ], 400);
                return;
            }

            // Verificar se o orçamento está em triagem
            $stmt = $this->db->prepare("
                SELECT status
                FROM vendas
                WHERE id = :id
                  AND company_id = :company_id
                  AND modulo_origem = :modulo_origem
                LIMIT 1
            ");
            $stmt->execute([
                'id' => $vendaId,
                'company_id' => $companyId,
                'modulo_origem' => $this->moduleOrigin(),
            ]);
            $orcamento = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$orcamento) {
                $this->response->json([
                    'success' => false,
                    'message' => 'Orçamento não encontrado',
                ], 404);
                return;
            }

            if ($orcamento['status'] !== 'triagem') {
                $this->response->json([
                    'success' => false,
                    'message' => 'Apenas orçamentos em triagem podem ter quebra/troca registrada',
                ], 400);
                return;
            }

            // Calcular valor por item (distribuir igualmente entre todos os itens)
            $stmt = $this->db->prepare("
                SELECT COUNT(*) as total_itens
                FROM vendas_itens
                WHERE venda_id = :venda_id
                  AND company_id = :company_id
            ");
            $stmt->execute([
                'venda_id' => $vendaId,
                'company_id' => $companyId,
            ]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            $totalItens = (int) ($result['total_itens'] ?? 1);
            $valorPorItem = $totalItens > 0 ? $valor / $totalItens : 0;

            // Atualizar cada item (usando prepared statement seguro)
            if ($tipo === 'quebra') {
                $stmt = $this->db->prepare("
                    UPDATE vendas_itens
                    SET quebra = :valor
                    WHERE venda_id = :venda_id
                      AND company_id = :company_id
                ");
            } else {
                $stmt = $this->db->prepare("
                    UPDATE vendas_itens
                    SET troca = :valor
                    WHERE venda_id = :venda_id
                      AND company_id = :company_id
                ");
            }

            $stmt->execute([
                'valor' => $valorPorItem,
                'venda_id' => $vendaId,
                'company_id' => $companyId,
            ]);

            $this->response->json([
                'success' => true,
                'message' => ucfirst($tipo) . ' atualizada com sucesso',
            ]);
        } catch (Exception $e) {
            error_log('[OrcamentosAguaController] erro ao atualizar quebra/troca: ' . $e->getMessage());
            $this->response->json([
                'success' => false,
                'message' => 'Erro ao atualizar ' . $tipo,
            ], 500);
        }
    }

    private function registrarLog(string $mensagem): void
    {
        try {
            $diretorio = \ROOT_PATH . '/storage/logs';
            if (!is_dir($diretorio)) {
                mkdir($diretorio, 0777, true);
            }

            $arquivo = sprintf('%s/orcamentos-agua-%s.log', $diretorio, date('Y-m-d'));
            $entrada = sprintf("[%s] %s\n", date('Y-m-d H:i:s'), $mensagem);
            file_put_contents($arquivo, $entrada, FILE_APPEND | LOCK_EX);
        } catch (\Throwable $e) {
            error_log('[OrcamentosAguaController] Falha ao registrar log: ' . $e->getMessage());
        }
    }

    /**
     * Garante que os status padrão do módulo orcamentos_agua existam no banco
     */
    private function garantirStatusOrcamentosAgua(int $companyId): void
    {
        try {
            $statusPadrao = [
                ['orcamento', 'Orçamento', 'Orçamento inicial de água mineral', 0, 0, '#6c757d', 'bi-file-earmark-text', 1, 1, 0],
                ['triagem', 'Triagem', 'Orçamento em triagem para separação', 0, 0, '#ffc107', 'bi-funnel', 2, 0, 0],
                ['separacao', 'Separação', 'Produtos sendo separados no estoque', 0, 1, '#17a2b8', 'bi-box-seam', 3, 0, 0],
                ['expedicao', 'Expedição', 'Produtos prontos para expedição', 0, 0, '#007bff', 'bi-box-arrow-up', 4, 0, 0],
                ['liberacao_veiculo', 'Liberação do Veículo', 'Veículo liberado para entrega', 0, 0, '#28a745', 'bi-truck', 5, 0, 1],
            ];

            $stmt = $this->db->prepare("
                INSERT INTO modulo_status (
                    company_id, modulo, codigo, nome, descricao,
                    gera_financeiro, movimenta_estoque, cor, icone, ordem, is_default, is_final, ativo
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)
                ON DUPLICATE KEY UPDATE
                    nome = VALUES(nome),
                    descricao = VALUES(descricao),
                    gera_financeiro = VALUES(gera_financeiro),
                    movimenta_estoque = VALUES(movimenta_estoque),
                    cor = VALUES(cor),
                    icone = VALUES(icone),
                    ordem = VALUES(ordem),
                    is_default = VALUES(is_default),
                    is_final = VALUES(is_final),
                    ativo = 1
            ");

            foreach ($statusPadrao as $status) {
                $stmt->execute([
                    $companyId,
                    'orcamentos_agua',
                    $status[0], // codigo
                    $status[1], // nome
                    $status[2], // descricao
                    $status[3], // gera_financeiro
                    $status[4], // movimenta_estoque
                    $status[5], // cor
                    $status[6], // icone
                    $status[7], // ordem
                    $status[8], // is_default
                    $status[9]  // is_final
                ]);
            }
        } catch (\Exception $e) {
            error_log('[OrcamentosAguaController] Erro ao garantir status: ' . $e->getMessage());
            // Não lançar exceção para não quebrar o fluxo
        }
    }

    public function update(): void
    {
        // Verificar permissão de edição
        if (!$this->canEdit('orcamentos-agua')) {
            $this->response->forbidden('Você não tem permissão para editar orçamentos de água.');
            return;
        }

        try {
            $id = (int) $this->request->post('id');
            $companyId = $this->getCompanyId();

            if (!$id || !$companyId) {
                $this->error('ID inválido ou empresa não encontrada');
                return;
            }

            // Buscar o orçamento
            $stmt = $this->db->prepare("
                SELECT id, status
                FROM vendas
                WHERE id = :id
                  AND company_id = :company_id
                  AND modulo_origem = :modulo_origem
                LIMIT 1
            ");
            $stmt->execute([
                'id' => $id,
                'company_id' => $companyId,
                'modulo_origem' => 'dav'
            ]);
            $venda = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$venda) {
                $this->error('Orçamento não encontrado');
                return;
            }

            $this->db->beginTransaction();

            // Se estiver em triagem, atualizar apenas campos de triagem
            if ($venda['status'] === 'triagem') {
                $itens = $this->request->post('itens', []);

                foreach ($itens as $produtoId => $itemData) {
                    // Pode vir como array indexado por produto_id ou como array sequencial
                    $itemId = (int) ($itemData['id'] ?? 0);
                    if ($itemId <= 0) {
                        // Tentar buscar o item pelo produto_id
                        $stmt = $this->db->prepare("
                            SELECT id FROM vendas_itens
                            WHERE venda_id = :venda_id
                              AND product_id = :product_id
                              AND company_id = :company_id
                            LIMIT 1
                        ");
                        $stmt->execute([
                            'venda_id' => $id,
                            'product_id' => (int) $produtoId,
                            'company_id' => $companyId
                        ]);
                        $item = $stmt->fetch(PDO::FETCH_ASSOC);
                        if (!$item) continue;
                        $itemId = (int) $item['id'];
                    }

                    $quebra = (float) ($itemData['quebra'] ?? 0);
                    $troca = (float) ($itemData['troca'] ?? 0);
                    $qtdInformada = (float) ($itemData['qtd_informada'] ?? 0);
                    $conferido = (float) ($itemData['conferido'] ?? 0);
                    $cashback = (float) ($itemData['cashback'] ?? 0);
                    $compra = (float) ($itemData['compra'] ?? 0);
                    $faltaR = (float) ($itemData['falta_r'] ?? 0);
                    // Calcular diferença se não foi informada: qtd_informada - conferido
                    $diferenca = (float) ($itemData['diferenca'] ?? ($qtdInformada - $conferido));

                    // Verificar se as colunas diferenca, conferido, cashback, falta_r, compra, qtd_informada e profissional_id existem
                    $colunaDiferencaExiste = false;
                    $colunaConferidoExiste = false;
                    $colunaCashbackExiste = false;
                    $colunaFaltaRExiste = false;
                    $colunaCompraExiste = false;
                    $colunaQtdInformadaExiste = false;
                    $colunaProfissionalIdExiste = false;
                    try {
                        $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'diferenca'");
                        $colunaDiferencaExiste = $stmtCheck->fetch() !== false;
                        $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'conferido'");
                        $colunaConferidoExiste = $stmtCheck->fetch() !== false;
                        $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'cashback'");
                        $colunaCashbackExiste = $stmtCheck->fetch() !== false;
                        $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'falta_r'");
                        $colunaFaltaRExiste = $stmtCheck->fetch() !== false;
                        $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'compra'");
                        $colunaCompraExiste = $stmtCheck->fetch() !== false;
                        $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'qtd_informada'");
                        $colunaQtdInformadaExiste = $stmtCheck->fetch() !== false;
                        $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'profissional_id'");
                        $colunaProfissionalIdExiste = $stmtCheck->fetch() !== false;
                    } catch (Exception $e) {
                        // Ignorar erro de verificação
                    }

                    // Buscar profissional_id geral ou do item
                    $itensData = $this->request->post('itens', []);
                    $profissionalIdGeral = $this->request->post('profissional_id') ?: null;
                    $profissionalId = !empty($itemData['profissional_id']) ? (int)$itemData['profissional_id'] : ($profissionalIdGeral ? (int)$profissionalIdGeral : null);

                    // Montar SQL dinamicamente
                    $setFields = ['quebra = :quebra', 'troca = :troca'];
                    $params = [
                        'quebra' => $quebra,
                        'troca' => $troca,
                        'id' => $itemId,
                        'venda_id' => $id,
                        'company_id' => $companyId
                    ];

                    if ($colunaQtdInformadaExiste) {
                        $setFields[] = 'qtd_informada = :qtd_informada';
                        $params['qtd_informada'] = $qtdInformada;
                    }
                    if ($colunaConferidoExiste) {
                        $setFields[] = 'conferido = :conferido';
                        $params['conferido'] = $conferido;
                    }
                    if ($colunaDiferencaExiste) {
                        $setFields[] = 'diferenca = :diferenca';
                        $params['diferenca'] = $diferenca;
                    }
                    if ($colunaCashbackExiste) {
                        $setFields[] = 'cashback = :cashback';
                        $params['cashback'] = $cashback;
                    }
                    if ($colunaFaltaRExiste) {
                        $setFields[] = 'falta_r = :falta_r';
                        $params['falta_r'] = $faltaR;
                    }
                    if ($colunaCompraExiste) {
                        $setFields[] = 'compra = :compra';
                        $params['compra'] = $compra;
                    }
                    if ($colunaProfissionalIdExiste) {
                        // Sempre atualizar profissional_id se a coluna existir (pode ser null)
                        $setFields[] = 'profissional_id = :profissional_id';
                        $params['profissional_id'] = $profissionalId;
                    }

                    $stmt = $this->db->prepare("
                        UPDATE vendas_itens
                        SET " . implode(', ', $setFields) . ",
                            updated_at = NOW()
                        WHERE id = :id
                          AND venda_id = :venda_id
                          AND company_id = :company_id
                    ");
                    $stmt->execute($params);
                }

                $this->db->commit();

                if ($this->request->isAjax()) {
                    $this->response->json([
                        'success' => true,
                        'message' => 'Triagem atualizada com sucesso',
                        'redirect' => url('/orcamentos-agua')
                    ]);
                } else {
                    $this->session->flash('success_message', 'Triagem atualizada com sucesso');
                    $this->redirect('/orcamentos-agua');
                }
            } else {
                // Para outros status, atualizar também os campos troca, quebra e diferenca
                $itens = $this->request->post('itens', []);

                if (!empty($itens)) {
                    foreach ($itens as $produtoId => $itemData) {
                        $itemId = (int) ($itemData['id'] ?? 0);
                        if ($itemId <= 0) {
                            // Tentar buscar o item pelo produto_id
                            $stmt = $this->db->prepare("
                                SELECT id FROM vendas_itens
                                WHERE venda_id = :venda_id
                                  AND product_id = :product_id
                                  AND company_id = :company_id
                                LIMIT 1
                            ");
                            $stmt->execute([
                                'venda_id' => $id,
                                'product_id' => (int) $produtoId,
                                'company_id' => $companyId
                            ]);
                            $item = $stmt->fetch(PDO::FETCH_ASSOC);
                            if (!$item) continue;
                            $itemId = (int) $item['id'];
                        }

                        $quebra = (float) ($itemData['quebra'] ?? 0);
                        $troca = (float) ($itemData['troca'] ?? 0);
                        $qtdInformada = (float) ($itemData['qtd_informada'] ?? 0);
                        $conferido = (float) ($itemData['conferido'] ?? 0);
                        $cashback = (float) ($itemData['cashback'] ?? 0);
                        $faltaR = (float) ($itemData['falta_r'] ?? 0);
                        $diferenca = (float) ($itemData['diferenca'] ?? ($qtdInformada - $conferido));

                        // Verificar se as colunas diferenca, conferido, cashback, falta_r, qtd_informada e profissional_id existem
                        $colunaDiferencaExiste = false;
                        $colunaConferidoExiste = false;
                        $colunaCashbackExiste = false;
                        $colunaFaltaRExiste = false;
                        $colunaQtdInformadaExiste = false;
                        $colunaProfissionalIdExiste = false;
                        $colunaCompraExiste = false;
                        try {
                            $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'diferenca'");
                            $colunaDiferencaExiste = $stmtCheck->fetch() !== false;
                            $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'conferido'");
                            $colunaConferidoExiste = $stmtCheck->fetch() !== false;
                            $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'cashback'");
                            $colunaCashbackExiste = $stmtCheck->fetch() !== false;
                            $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'falta_r'");
                            $colunaFaltaRExiste = $stmtCheck->fetch() !== false;
                            $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'qtd_informada'");
                            $colunaQtdInformadaExiste = $stmtCheck->fetch() !== false;
                            $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'profissional_id'");
                            $colunaProfissionalIdExiste = $stmtCheck->fetch() !== false;
                            $stmtCheck = $this->db->query("SHOW COLUMNS FROM vendas_itens LIKE 'compra'");
                            $colunaCompraExiste = $stmtCheck->fetch() !== false;
                        } catch (Exception $e) {
                            // Ignorar erro de verificação
                        }

                        // Buscar profissional_id geral ou do item
                        $profissionalIdGeral = $this->request->post('profissional_id') ?: null;
                        $profissionalId = !empty($itemData['profissional_id']) ? (int)$itemData['profissional_id'] : ($profissionalIdGeral ? (int)$profissionalIdGeral : null);

                        // Montar SQL dinamicamente
                        $setFields = ['quebra = :quebra', 'troca = :troca'];
                        $params = [
                            'quebra' => $quebra,
                            'troca' => $troca,
                            'id' => $itemId,
                            'venda_id' => $id,
                            'company_id' => $companyId
                        ];

                        if ($colunaQtdInformadaExiste) {
                            $setFields[] = 'qtd_informada = :qtd_informada';
                            $params['qtd_informada'] = $qtdInformada;
                        }
                        if ($colunaConferidoExiste) {
                            $setFields[] = 'conferido = :conferido';
                            $params['conferido'] = $conferido;
                        }
                        if ($colunaDiferencaExiste) {
                            $setFields[] = 'diferenca = :diferenca';
                            $params['diferenca'] = $diferenca;
                        }
                        if ($colunaCashbackExiste) {
                            $setFields[] = 'cashback = :cashback';
                            $params['cashback'] = $cashback;
                        }
                        if ($colunaFaltaRExiste) {
                            $setFields[] = 'falta_r = :falta_r';
                            $params['falta_r'] = $faltaR;
                        }
                        if ($colunaCompraExiste) {
                            $setFields[] = 'compra = :compra';
                            $params['compra'] = $compra;
                        }
                        if ($colunaProfissionalIdExiste) {
                            // Sempre atualizar profissional_id se a coluna existir (pode ser null)
                            $setFields[] = 'profissional_id = :profissional_id';
                            $params['profissional_id'] = $profissionalId;
                        }

                        $stmt = $this->db->prepare("
                            UPDATE vendas_itens
                            SET " . implode(', ', $setFields) . ",
                                updated_at = NOW()
                            WHERE id = :id
                              AND venda_id = :venda_id
                              AND company_id = :company_id
                        ");
                        $stmt->execute($params);
                    }
                }

                // Usar o método padrão do VendasController para outros campos
                parent::update();
            }
        } catch (Exception $e) {
            if ($this->db && $this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log('[OrcamentosAguaController] erro ao atualizar: ' . $e->getMessage());

            if ($this->request->isAjax()) {
                $this->response->json([
                    'success' => false,
                    'message' => 'Erro ao atualizar: ' . $e->getMessage()
                ], 500);
            } else {
                $this->session->flash('error_message', 'Erro ao atualizar: ' . $e->getMessage());
                $this->redirect('/orcamentos-agua');
            }
        }
    }
}