<?php

namespace App\Controllers;

use App\Helpers\UrlHelper;
use Exception;

class ProdutosController extends BaseController
{
    /**
     * Retorna a rota base correta (/itens ou /produtos) baseado na URL atual
     */
    private function getRouteBase(): string
    {
        $routePath = $this->request->path();
        $isItens = strpos($routePath, '/itens') !== false;
        return $isItens ? '/itens' : '/produtos';
    }

    /**
     * Salva log no arquivo do projeto
     */
    private function logDebug(string $message): void
    {
        $logDir = __DIR__ . '/../../storage/logs';
        if (!is_dir($logDir)) {
            @mkdir($logDir, 0755, true);
        }
        $logFile = $logDir . '/produtos_debug_' . date('Y-m-d') . '.log';
        $timestamp = date('Y-m-d H:i:s');
        @file_put_contents($logFile, "[{$timestamp}] {$message}" . PHP_EOL, FILE_APPEND);

        // Também escrever no error_log padrão do PHP
        @error_log($message);
    }

    private function sanitizeDecimal($value): ?float
    {
        if ($value === null) {
            return null;
        }

        if (is_numeric($value)) {
            return (float) $value;
        }

        $normalized = trim((string) $value);
        if ($normalized === '') {
            return null;
        }

        $normalized = str_replace(['R$', 'r$', ' '], '', $normalized);

        if (strpos($normalized, ',') !== false && strpos($normalized, '.') !== false) {
            $normalized = str_replace('.', '', $normalized);
            $normalized = str_replace(',', '.', $normalized);
        } elseif (strpos($normalized, ',') !== false) {
            $normalized = str_replace(',', '.', $normalized);
        }

        return is_numeric($normalized) ? (float) $normalized : null;
    }

    private function sanitizeString(?string $value): ?string
    {
        if ($value === null) {
            return null;
        }

        $trimmed = trim($value);

        return $trimmed === '' ? null : $trimmed;
    }

    private function buildDimensions(?float $height, ?float $width, ?float $length): ?string
    {
        $parts = [];

        foreach ([$height, $width, $length] as $value) {
            if ($value === null) {
                continue;
            }

            $formatted = number_format($value, 2, '.', '');
            $formatted = rtrim(rtrim($formatted, '0'), '.');
            $parts[] = $formatted;
        }

        return empty($parts) ? null : implode(' x ', $parts);
    }

    /**
     * Verifica e corrige a Foreign Key de grupo_tributacao_id
     */
    private function verificarEFixarFK(): void
    {
        try {
            // Verifica se existe FK incorreta apontando para categorias
            $stmt = $this->db->query("
                SELECT CONSTRAINT_NAME, REFERENCED_TABLE_NAME
                FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
                WHERE TABLE_SCHEMA = DATABASE()
                AND TABLE_NAME = 'produtos'
                AND COLUMN_NAME = 'grupo_tributacao_id'
                AND REFERENCED_TABLE_NAME IS NOT NULL
            ");
            $fkInfo = $stmt->fetch();

            if ($fkInfo && $fkInfo['REFERENCED_TABLE_NAME'] === 'categorias') {
                $this->logDebug("FK incorreta detectada: " . $fkInfo['CONSTRAINT_NAME'] . " -> categorias");

                // Remove FK incorreta
                $this->db->exec("ALTER TABLE produtos DROP FOREIGN KEY " . $fkInfo['CONSTRAINT_NAME']);
                $this->logDebug("✓ FK removida: " . $fkInfo['CONSTRAINT_NAME']);

                // Verifica se tabela impostos existe
                $checkImpostos = $this->db->query("SHOW TABLES LIKE 'impostos'");
                if ($checkImpostos->rowCount() > 0) {
                    // Ajusta tipo se necessário
                    $checkIdType = $this->db->query("
                        SELECT COLUMN_TYPE
                        FROM INFORMATION_SCHEMA.COLUMNS
                        WHERE TABLE_SCHEMA = DATABASE()
                        AND TABLE_NAME = 'impostos'
                        AND COLUMN_NAME = 'id'
                    ");
                    $idType = $checkIdType->fetch()['COLUMN_TYPE'] ?? '';

                    $checkProdType = $this->db->query("
                        SELECT COLUMN_TYPE
                        FROM INFORMATION_SCHEMA.COLUMNS
                        WHERE TABLE_SCHEMA = DATABASE()
                        AND TABLE_NAME = 'produtos'
                        AND COLUMN_NAME = 'grupo_tributacao_id'
                    ");
                    $prodType = $checkProdType->fetch()['COLUMN_TYPE'] ?? '';

                    if (strpos($idType, 'bigint') !== false && strpos($prodType, 'bigint') === false) {
                        $this->db->exec("ALTER TABLE produtos MODIFY COLUMN grupo_tributacao_id BIGINT(20) UNSIGNED NULL");
                        $this->logDebug("✓ Tipo alterado para BIGINT");
                    }

                    // Remove FK antiga se existir
                    try {
                        $this->db->exec("ALTER TABLE produtos DROP FOREIGN KEY fk_produtos_grupo_tributacao");
                    } catch (\PDOException $e) {
                        // Ignora
                    }

                    // Cria FK correta
                    $this->db->exec("
                        ALTER TABLE produtos
                        ADD CONSTRAINT fk_produtos_grupo_tributacao
                        FOREIGN KEY (grupo_tributacao_id)
                        REFERENCES impostos(id)
                        ON DELETE SET NULL
                        ON UPDATE CASCADE
                    ");
                    $this->logDebug("✓ FK correta criada: produtos.grupo_tributacao_id -> impostos.id");
                }
            }
        } catch (\Exception $e) {
            $this->logDebug("Erro ao verificar FK: " . $e->getMessage());
            // Não interrompe o fluxo, apenas loga
        }
    }
    /**
     * Lista todos os produtos
     */
    public function index(): void
    {
        try {
            // Limpar contador de redirecionamento ao iniciar (página carregando normalmente)
            unset($_SESSION['redirect_count']);

            // Verificar permissão de visualização
            if (!$this->canView('produtos')) {
                $this->response->forbidden('Você não tem permissão para visualizar produtos.');
                return;
            }

            // Verificar conexão com banco de dados
            if (!$this->db) {
                error_log("[ProdutosController::index] Erro: Conexão com banco de dados não disponível");
                if ($this->request->isAjax()) {
                    $this->error('Erro de conexão com o banco de dados.', [], 500);
                    return;
                }
                $_SESSION['error_message'] = 'Erro de conexão com o banco de dados.';
                $this->redirect('/dashboard');
                return;
            }

            $companyId = $this->getCompanyId();
            if (!$companyId) {
                error_log("[ProdutosController::index] Erro: companyId não encontrado");
                if ($this->request->isAjax()) {
                    $this->error('Sessão expirada. Faça login novamente.', [], 401);
                    return;
                }
                $this->redirect('/login');
                return;
            }

            $search = $this->request->get('search', '');
            $type = $this->request->get('type', '');
            $empresaFiltro = $this->request->get('empresa', '');

            // Paginação
            $perPage = 50; // Itens por página
            $page = max(1, (int) ($this->request->get('page') ?? 1));
            $offset = ($page - 1) * $perPage;

            // Verificar se a tabela estoque_movimentos existe e qual coluna usa
            $tabelaEstoqueMovimentosExiste = false;
            $colunaProduto = 'product_id';
            try {
                $stmtCheck = $this->db->query("SHOW TABLES LIKE 'estoque_movimentos'");
                $tabelaEstoqueMovimentosExiste = $stmtCheck->rowCount() > 0;

                if ($tabelaEstoqueMovimentosExiste) {
                    // Verificar qual coluna existe: product_id ou item_id
                    $stmtCol = $this->db->query("SHOW COLUMNS FROM estoque_movimentos LIKE 'item_id'");
                    if ($stmtCol->rowCount() > 0) {
                        $colunaProduto = 'item_id';
                    }
                }
            } catch (Exception $e) {
                error_log("Erro ao verificar tabela estoque_movimentos: " . $e->getMessage());
            }

            // Construir query base
            $query = "
                SELECT
                    p.*,
                    g.nome as grupo_name";

            // Adicionar cálculo de estoque apenas se a tabela existir
            if ($tabelaEstoqueMovimentosExiste) {
                $query .= ",
                    COALESCE((
                        SELECT SUM(
                            CASE
                                WHEN em.type = 'entrada' THEN em.quantity
                                WHEN em.type = 'saida' THEN -em.quantity
                                ELSE 0
                            END
                        )
                        FROM estoque_movimentos em
                        WHERE em.{$colunaProduto} = p.id AND em.company_id = p.company_id
                    ), COALESCE(p.stock_quantity, 0)) as stock_quantity";
            } else {
                $query .= ",
                    COALESCE(p.stock_quantity, 0) as stock_quantity";
            }

            $query .= "
                FROM produtos p
                LEFT JOIN grupos_pessoas g ON p.grupo_id = g.id AND g.company_id = p.company_id AND g.tipo = 'itens'
                WHERE p.company_id = :company_id
            ";

            $params = ['company_id' => $companyId];

            if (!empty($search)) {
                // Buscar por ID, nome, SKU, código de barras, descrição
                $searchTerm = trim($search);
                $searchPattern = "%{$searchTerm}%";

                // Se for numérico, incluir busca por ID exato
                if (is_numeric($searchTerm)) {
                    $query .= " AND (
                        p.id = :search_id_exato OR
                        CAST(p.id AS CHAR) LIKE :search_id_char OR
                        p.name LIKE :search_name OR
                        p.sku LIKE :search_sku OR
                        p.barcode LIKE :search_barcode OR
                        p.description LIKE :search_desc
                    )";
                    $params['search_id_exato'] = (int) $searchTerm;
                    $params['search_id_char'] = $searchPattern;
                    $params['search_name'] = $searchPattern;
                    $params['search_sku'] = $searchPattern;
                    $params['search_barcode'] = $searchPattern;
                    $params['search_desc'] = $searchPattern;
                } else {
                    // Busca apenas textual (nome, SKU, código de barras, descrição)
                    $query .= " AND (
                        p.name LIKE :search_name OR
                        p.sku LIKE :search_sku OR
                        p.barcode LIKE :search_barcode OR
                        p.description LIKE :search_desc
                    )";
                    $params['search_name'] = $searchPattern;
                    $params['search_sku'] = $searchPattern;
                    $params['search_barcode'] = $searchPattern;
                    $params['search_desc'] = $searchPattern;
                }
            }

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

            // Filtro por empresa (busca na tabela empresas_produtos)
            if (!empty($empresaFiltro) && is_numeric($empresaFiltro)) {
                $stmtCheckEmpresasProdutos = $this->db->query("SHOW TABLES LIKE 'empresas_produtos'");
                if ($stmtCheckEmpresasProdutos->rowCount() > 0) {
                    $query .= " AND EXISTS (
                        SELECT 1
                        FROM empresas_produtos ep
                        WHERE ep.produto_id = p.id
                        AND ep.empresa_id = :empresa_filtro
                    )";
                    $params['empresa_filtro'] = (int) $empresaFiltro;
                }
            }

            // Contar total de registros antes de aplicar LIMIT e ORDER BY
            // Encontrar a posição do primeiro FROM (não em subqueries)
            $fromPos = strpos($query, " FROM ");
            if ($fromPos === false) {
                $fromPos = strpos($query, "FROM ");
            }
            if ($fromPos !== false) {
                $queryCount = "SELECT COUNT(DISTINCT p.id) as total " . substr($query, $fromPos);
                // Remover ORDER BY se existir na query de contagem
                $queryCount = preg_replace('/\s+ORDER\s+BY\s+[^\s]+(\s+ASC|\s+DESC)?/i', '', $queryCount);
                $queryCount = preg_replace('/\s+LIMIT\s+[^\s]+(\s+OFFSET\s+[^\s]+)?/i', '', $queryCount);
            } else {
                // Fallback: usar query completa
                $queryCount = "SELECT COUNT(DISTINCT p.id) as total FROM produtos p WHERE p.company_id = :company_id";
            }

            try {
                $stmtCount = $this->db->prepare($queryCount);
                $stmtCount->execute($params);
                $total = (int) $stmtCount->fetch()['total'];
            } catch (Exception $e) {
                error_log("Erro ao contar produtos: " . $e->getMessage());
                // Se falhar, usar contagem simples
                $stmtCount = $this->db->prepare("SELECT COUNT(*) as total FROM produtos WHERE company_id = :company_id");
                $stmtCount->execute(['company_id' => $companyId]);
                $total = (int) $stmtCount->fetch()['total'];
            }

            $totalPages = max(1, (int) ceil($total / $perPage));

            // Adicionar ORDER BY e paginação na query principal
            $query .= " ORDER BY p.name ASC";

            // Aplicar paginação
            $query .= " LIMIT :limit OFFSET :offset";
            $stmt = $this->db->prepare($query);
            foreach ($params as $key => $value) {
                $stmt->bindValue(':' . $key, $value, is_int($value) ? \PDO::PARAM_INT : \PDO::PARAM_STR);
            }
            $stmt->bindValue(':limit', $perPage, \PDO::PARAM_INT);
            $stmt->bindValue(':offset', $offset, \PDO::PARAM_INT);
            $stmt->execute();
            $produtos = $stmt->fetchAll();

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

            // Buscar empresas para filtro
            $todasEmpresas = $this->getTodasEmpresas();

            // Determina qual view usar baseado na rota
            $routePath = $this->request->path();
            $isItens = ($this instanceof ItensController) || strpos($routePath, '/itens') !== false;
            $viewName = $isItens ? 'itens/index' : 'produtos/index';

            $this->view($viewName, [
                'produtos' => $produtos,
                'categorias' => $categorias,
                'search' => $search,
                'type' => $type,
                'empresa' => $empresaFiltro,
                'todasEmpresas' => $todasEmpresas ?: [],
                'pageTitle' => $isItens ? 'Itens' : 'Produtos',
                'activeMenu' => $isItens ? 'itens' : 'produtos',
                // Dados de paginação
                'page' => $page,
                'perPage' => $perPage,
                'total' => $total,
                'totalPages' => $totalPages
            ]);

        } catch (Exception $e) {
            error_log("Erro ao carregar produtos: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());

            // Se for requisição AJAX, retornar JSON
            if ($this->request->isAjax()) {
                $this->error('Erro ao carregar produtos: ' . $e->getMessage());
                return;
            }

            // Verificar se já estamos em um loop de redirecionamento
            $redirectCount = $_SESSION['redirect_count'] ?? 0;
            if ($redirectCount >= 2) {
                // Limpar contador e mostrar erro ao invés de redirecionar
                unset($_SESSION['redirect_count']);
                $_SESSION['error_message'] = 'Erro ao carregar produtos. Por favor, tente novamente ou entre em contato com o suporte.';
                $this->redirect('/dashboard');
                return;
            }

            // Incrementar contador de redirecionamento
            $_SESSION['redirect_count'] = $redirectCount + 1;

            // Caso contrário, renderizar página de erro HTML
            $_SESSION['error_message'] = 'Erro ao carregar produtos: ' . $e->getMessage();

            // Determinar rota base correta
            $routePath = $this->request->path();
            $isItens = strpos($routePath, '/itens') !== false;
            $redirectPath = $isItens ? '/itens' : '/produtos';

            $this->redirect($redirectPath);
            return;
        }
    }

    /**
     * Busca dinâmica de produtos (AJAX)
     */
    public function buscar(): void
    {
        try {
            // Verificar permissão de visualização
            if (!$this->canView('produtos')) {
                $this->response->json(['success' => false, 'message' => 'Você não tem permissão para visualizar produtos.']);
                return;
            }

            $companyId = $this->getCompanyId();
            $search = $this->request->get('search', '');
            $type = $this->request->get('type', '');
            $empresaFiltro = $this->request->get('empresa', '');

            // Verificar se a tabela estoque_movimentos existe e qual coluna usa
            $tabelaEstoqueMovimentosExiste = false;
            $colunaProduto = 'product_id';
            try {
                $stmtCheck = $this->db->query("SHOW TABLES LIKE 'estoque_movimentos'");
                $tabelaEstoqueMovimentosExiste = $stmtCheck->rowCount() > 0;

                if ($tabelaEstoqueMovimentosExiste) {
                    $stmtCol = $this->db->query("SHOW COLUMNS FROM estoque_movimentos LIKE 'item_id'");
                    if ($stmtCol->rowCount() > 0) {
                        $colunaProduto = 'item_id';
                    }
                }
            } catch (Exception $e) {
                error_log("Erro ao verificar tabela estoque_movimentos: " . $e->getMessage());
            }

            // Construir query base
            $query = "
                SELECT
                    p.*,
                    g.nome as grupo_name";

            // Adicionar cálculo de estoque apenas se a tabela existir
            if ($tabelaEstoqueMovimentosExiste) {
                $query .= ",
                    COALESCE((
                        SELECT SUM(
                            CASE
                                WHEN em.type = 'entrada' THEN em.quantity
                                WHEN em.type = 'saida' THEN -em.quantity
                                ELSE 0
                            END
                        )
                        FROM estoque_movimentos em
                        WHERE em.{$colunaProduto} = p.id AND em.company_id = p.company_id
                    ), COALESCE(p.stock_quantity, 0)) as stock_quantity";
            } else {
                $query .= ",
                    COALESCE(p.stock_quantity, 0) as stock_quantity";
            }

            $query .= "
                FROM produtos p
                LEFT JOIN grupos_pessoas g ON p.grupo_id = g.id AND g.company_id = p.company_id AND g.tipo = 'itens'
                WHERE p.company_id = :company_id
            ";

            $params = ['company_id' => $companyId];

            if (!empty($search)) {
                $searchTerm = trim($search);
                $searchPattern = "%{$searchTerm}%";

                if (is_numeric($searchTerm)) {
                    $query .= " AND (
                        p.id = :search_id_exato OR
                        CAST(p.id AS CHAR) LIKE :search_id_char OR
                        p.name LIKE :search_name OR
                        p.sku LIKE :search_sku OR
                        p.barcode LIKE :search_barcode OR
                        p.description LIKE :search_desc
                    )";
                    $params['search_id_exato'] = (int) $searchTerm;
                    $params['search_id_char'] = $searchPattern;
                    $params['search_name'] = $searchPattern;
                    $params['search_sku'] = $searchPattern;
                    $params['search_barcode'] = $searchPattern;
                    $params['search_desc'] = $searchPattern;
                } else {
                    $query .= " AND (
                        p.name LIKE :search_name OR
                        p.sku LIKE :search_sku OR
                        p.barcode LIKE :search_barcode OR
                        p.description LIKE :search_desc
                    )";
                    $params['search_name'] = $searchPattern;
                    $params['search_sku'] = $searchPattern;
                    $params['search_barcode'] = $searchPattern;
                    $params['search_desc'] = $searchPattern;
                }
            }

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

            // Filtro por empresa
            if (!empty($empresaFiltro) && is_numeric($empresaFiltro)) {
                $stmtCheckEmpresasProdutos = $this->db->query("SHOW TABLES LIKE 'empresas_produtos'");
                if ($stmtCheckEmpresasProdutos->rowCount() > 0) {
                    $query .= " AND EXISTS (
                        SELECT 1
                        FROM empresas_produtos ep
                        WHERE ep.produto_id = p.id
                        AND ep.empresa_id = :empresa_filtro
                    )";
                    $params['empresa_filtro'] = (int) $empresaFiltro;
                }
            }

            $query .= " ORDER BY p.name ASC";

            $stmt = $this->db->prepare($query);
            $stmt->execute($params);
            $produtos = $stmt->fetchAll(\PDO::FETCH_ASSOC);

            // Renderizar HTML da tabela
            $html = '';
            if (!empty($produtos)) {
                $html .= '<div class="table-responsive">';
                $html .= '<table class="table table-hover mb-0">';
                $html .= '<thead>';
                $html .= '<tr>';
                $html .= '<th width="60">ID</th>';
                $html .= '<th>Nome</th>';
                $html .= '<th>SKU/Código</th>';
                $html .= '<th>Grupo</th>';
                $html .= '<th>Estoque</th>';
                $html .= '<th>Preço</th>';
                $html .= '</tr>';
                $html .= '</thead>';
                $html .= '<tbody>';

                foreach ($produtos as $produto) {
                    $html .= '<tr style="cursor: pointer;" data-item-id="' . $produto['id'] . '"';
                    $html .= ' data-item-name="' . htmlspecialchars($produto['name'], ENT_QUOTES) . '"';
                    $html .= ' data-item-sku="' . htmlspecialchars($produto['sku'] ?? '-', ENT_QUOTES) . '"';
                    $html .= ' data-item-type="' . htmlspecialchars($produto['type'] ?? '', ENT_QUOTES) . '"';
                    $html .= ' data-item-price="' . number_format($produto['price'] ?? 0, 2, ',', '.') . '"';
                    $html .= ' onclick="abrirOpcoesItem(event)">';
                    $html .= '<td>' . $produto['id'] . '</td>';
                    $html .= '<td>';
                    $html .= '<strong>' . htmlspecialchars($produto['name']) . '</strong>';
                    if (!empty($produto['description'])) {
                        $desc = htmlspecialchars(substr($produto['description'], 0, 50));
                        $html .= '<br><small class="text-muted">' . $desc;
                        if (strlen($produto['description']) > 50) {
                            $html .= '...';
                        }
                        $html .= '</small>';
                    }
                    $html .= '</td>';
                    $html .= '<td>' . htmlspecialchars($produto['sku'] ?? '-') . '</td>';
                    $html .= '<td>' . htmlspecialchars($produto['grupo_name'] ?? '-') . '</td>';
                    $html .= '<td>';
                    $stock = $produto['stock_quantity'] ?? 0;
                    if ($produto['type'] === 'servico') {
                        $html .= '<span class="badge bg-info">N/A</span>';
                    } else {
                        $badgeClass = $stock < 0 ? 'bg-danger' : ($stock == 0 ? 'bg-warning' : 'bg-success');
                        $html .= '<span class="badge ' . $badgeClass . '">' . number_format($stock, 2, ',', '.') . '</span>';
                    }
                    $html .= '</td>';
                    $html .= '<td>R$ ' . number_format($produto['price'] ?? 0, 2, ',', '.') . '</td>';
                    $html .= '</tr>';
                }

                $html .= '</tbody>';
                $html .= '</table>';
                $html .= '</div>';
            } else {
                $basePath = UrlHelper::basePath();
                $criarUrl = $basePath . '/itens/criar';
                $html .= '<div class="text-center py-5">';
                $html .= '<i class="bi bi-box-seam" style="font-size: 4rem; color: var(--text-secondary);"></i>';
                $html .= '<p class="text-muted mt-3">Nenhum item encontrado</p>';
                $html .= '<a href="' . htmlspecialchars($criarUrl) . '" class="btn btn-primary mt-2">';
                $html .= '<i class="bi bi-plus-circle me-2"></i> Cadastrar Primeiro Item';
                $html .= '</a>';
                $html .= '</div>';
            }

            $this->response->json([
                'success' => true,
                'html' => $html,
                'count' => count($produtos)
            ]);

        } catch (Exception $e) {
            error_log("Erro ao buscar produtos: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());
            $this->response->json([
                'success' => false,
                'message' => 'Erro ao buscar produtos: ' . $e->getMessage()
            ]);
        }
    }

    /**
     * Exibe formulário de criação
     */
    public function create(): void
    {
        // Verificar permissão de criação
        if (!$this->canCreate('produtos')) {
            $this->response->forbidden('Você não tem permissão para criar produtos.');
            return;
        }

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

            $gruposItens = $this->getGruposItens();
            $subgruposItens = $this->getSubgruposItens();
            $tabelasPreco = $this->getTabelasPreco();
            $gruposTributacao = $this->getGruposTributacao();

            // Buscar produtos para o kit (igual na venda)
            $produtos = [];
            if ($companyId) {
                $stmt = $this->db->prepare("
                    SELECT id, name, sku, price, stock_quantity
                    FROM produtos
                    WHERE company_id = ? AND is_active = 1
                    ORDER BY name ASC
                ");
                $stmt->execute([$companyId]);
                $produtos = $stmt->fetchAll();
            }

            // Buscar locais de estoque
            $locaisEstoque = [];
            if ($companyId) {
                $stmt = $this->db->prepare("
                    SELECT id, name, tipo
                    FROM locais_estoque
                    WHERE company_id = ? AND is_active = 1
                    ORDER BY name ASC
                ");
                $stmt->execute([$companyId]);
                $locaisEstoque = $stmt->fetchAll();
            }

            // Buscar empresas para vincular
            $todasEmpresas = $this->getTodasEmpresas();

            // Determinar qual view usar baseado na rota
            $routePath = $this->request->path();
            $isItens = strpos($routePath, '/itens') !== false;
            $viewName = $isItens ? 'itens/create' : 'produtos/create';

            $this->view($viewName, [
                'produto' => [],
                'gruposItens' => $gruposItens,
                'subgruposItens' => $subgruposItens,
                'tabelasPreco' => $tabelasPreco,
                'gruposTributacao' => $gruposTributacao,
                'produtos' => $produtos,
                'kitItens' => [],
                'locaisEstoque' => $locaisEstoque,
                'todasEmpresas' => $todasEmpresas ?: [],
                'empresasVinculadas' => [],
                'pageTitle' => $isItens ? 'Novo Item' : 'Novo Produto',
                'activeMenu' => $isItens ? 'itens' : 'produtos'
            ]);
        } catch (Exception $e) {
            error_log("Erro ao exibir formulário de criação: " . $e->getMessage() . "\n" . $e->getTraceAsString());
            $this->error('Erro ao carregar formulário');
        }
    }

    /**
     * Salva novo produto
     */
    public function store(): void
    {
        // Verificar permissão de criação
        if (!$this->canCreate('produtos')) {
            $this->response->forbidden('Você não tem permissão para criar produtos.');
            return;
        }

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

            $stockQuantity = (float) ($this->request->post('stock_quantity') ?: 0);

            $stockAddress = $this->sanitizeString($this->request->post('stock_address'));
            // Agora recebe ID do local, não mais texto
            $stockEntryLocation = $this->request->post('stock_entry_location') ? (int) $this->request->post('stock_entry_location') : null;
            $stockExitLocation = $this->request->post('stock_exit_location') ? (int) $this->request->post('stock_exit_location') : null;
            $quantidadeEmbalagem = $this->request->post('quantidade_embalagem') ? (int) $this->request->post('quantidade_embalagem') : 1;

            $height = $this->sanitizeDecimal($this->request->post('height_cm'));
            $width = $this->sanitizeDecimal($this->request->post('width_cm'));
            $length = $this->sanitizeDecimal($this->request->post('length_cm'));
            $weight = $this->sanitizeDecimal($this->request->post('weight'));

            $data = [
                'company_id' => $companyId,
                'name' => $this->request->post('name'),
                'description' => $this->request->post('description'),
                'barcode' => $this->request->post('barcode'),
                'category_id' => $this->request->post('category_id') ?: null,
                'grupo_id' => $this->request->post('grupo_id') ?: null,
                'subgrupo_id' => $this->request->post('subgrupo_id') ?: null,
                'grupo_tributacao_id' => $this->request->post('grupo_tributacao_id') ?: null,
                'type' => $this->request->post('type'),
                'price' => $this->request->post('price') ?: 0.00,
                'cost_price' => $this->request->post('cost_price') ?: 0.00,
                'purchase_price' => $this->request->post('purchase_price') ?: 0.00,
                'profit_margin' => $this->request->post('profit_margin') ?: 0.00,
                'comissao' => $this->sanitizeDecimal($this->request->post('comissao')) ?: null,
                'stock_quantity' => 0, // Não salva quantidade aqui, vai para movimentação
                'min_stock' => $this->request->post('min_stock') ?: 0,
                'max_stock' => $this->request->post('max_stock') ?: 0,
                'stock_address' => $stockAddress,
                'stock_entry_location' => $stockEntryLocation,
                'stock_exit_location' => $stockExitLocation,
                'quantidade_embalagem' => $quantidadeEmbalagem,
                'weight' => $weight ?? 0.00,
                'height_cm' => $height,
                'width_cm' => $width,
                'length_cm' => $length,
                'dimensions' => $this->buildDimensions($height, $width, $length),
                'image' => $this->request->post('image'),
                'is_active' => $this->request->post('is_active') ? 1 : 0,
                'consumo_proprio' => $this->request->post('consumo_proprio') ? 1 : 0,
                'balanca' => $this->request->post('balanca') ? 1 : 0,
                'fracionado' => $this->request->post('fracionado') ? 1 : 0,
            ];

            $errors = $this->validate([
                'name' => 'required|min:2',
                'type' => 'required|in:produto,servico',
                'price' => 'required|numeric|min:0',
            ]);

            if (!empty($errors)) {
                $this->error('Dados inválidos', $errors);
                return;
            }

            $this->db->beginTransaction();

            // Verificar se coluna comissao existe
            $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE 'comissao'");
            $colunaComissaoExiste = $stmtCheck->rowCount() > 0;

            // Verificar se colunas ANVISA existem
            $camposAnvisa = ['anvisa', 'validade_anvisa', 'classificacao_risco', 'codigo_simpro', 'codigo_sus'];
            $camposAnvisaExistentes = [];
            foreach ($camposAnvisa as $campo) {
                try {
                    $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE '{$campo}'");
                    if ($stmtCheck->rowCount() > 0) {
                        $camposAnvisaExistentes[] = $campo;
                    }
                } catch (Exception $e) {
                    // Campo não existe, ignorar
                }
            }

            $colunasComissao = $colunaComissaoExiste ? ', comissao' : '';
            $valoresComissao = $colunaComissaoExiste ? ', :comissao' : '';

            $colunasAnvisa = '';
            $valoresAnvisa = '';
            if (!empty($camposAnvisaExistentes)) {
                $colunasAnvisa = ', ' . implode(', ', $camposAnvisaExistentes);
                $valoresAnvisa = ', :' . implode(', :', $camposAnvisaExistentes);
            }

            // Preparar dados para execução
            $dataToExecute = $data;

            // Adicionar campos ANVISA se existirem
            foreach ($camposAnvisaExistentes as $campo) {
                if ($campo === 'validade_anvisa') {
                    $valor = $this->request->post($campo);
                    $dataToExecute[$campo] = !empty($valor) ? $valor : null;
                } else {
                    $valor = $this->request->post($campo);
                    $dataToExecute[$campo] = !empty($valor) ? trim($valor) : null;
                }
            }

            // Remover comissao do array se a coluna não existir
            if (!$colunaComissaoExiste && isset($dataToExecute['comissao'])) {
                unset($dataToExecute['comissao']);
            }

            // Garantir que campos opcionais sejam null se vazios
            $optionalFields = ['description', 'barcode', 'stock_address', 'stock_entry_location', 'stock_exit_location', 'image', 'dimensions'];
            foreach ($optionalFields as $field) {
                if (isset($dataToExecute[$field]) && $dataToExecute[$field] === '') {
                    $dataToExecute[$field] = null;
                }
            }

            // Garantir que campos numéricos opcionais sejam null se não informados
            $numericOptionalFields = ['height_cm', 'width_cm', 'length_cm'];
            foreach ($numericOptionalFields as $field) {
                if (isset($dataToExecute[$field]) && ($dataToExecute[$field] === '' || $dataToExecute[$field] === null)) {
                    $dataToExecute[$field] = null;
                }
            }

            // Verificar se colunas ncm e unit existem
            $stmtCheckNcm = $this->db->query("SHOW COLUMNS FROM produtos LIKE 'ncm'");
            $colunaNcmExiste = $stmtCheckNcm->rowCount() > 0;

            $stmtCheckUnit = $this->db->query("SHOW COLUMNS FROM produtos LIKE 'unit'");
            $colunaUnitExiste = $stmtCheckUnit->rowCount() > 0;

            $colunasNcmUnit = '';
            $valoresNcmUnit = '';
            if ($colunaNcmExiste) {
                $colunasNcmUnit .= ', ncm';
                $valoresNcmUnit .= ', :ncm';
            }
            if ($colunaUnitExiste) {
                $colunasNcmUnit .= ', unit';
                $valoresNcmUnit .= ', :unit';
            }

            // Adicionar ncm e unit ao dataToExecute se as colunas existirem
            if ($colunaNcmExiste) {
                if (isset($dataToExecute['ncm'])) {
                    $dataToExecute['ncm'] = !empty($dataToExecute['ncm']) ? trim($dataToExecute['ncm']) : null;
                } else {
                    $dataToExecute['ncm'] = null;
                }
            } elseif (isset($dataToExecute['ncm'])) {
                unset($dataToExecute['ncm']);
            }

            if ($colunaUnitExiste) {
                if (isset($dataToExecute['unit'])) {
                    $dataToExecute['unit'] = !empty($dataToExecute['unit']) ? trim($dataToExecute['unit']) : null;
                } else {
                    $dataToExecute['unit'] = null;
                }
            } elseif (isset($dataToExecute['unit'])) {
                unset($dataToExecute['unit']);
            }

            $stmt = $this->db->prepare("
                INSERT INTO produtos (
                    company_id, name, description, barcode, category_id, grupo_id, subgrupo_id, grupo_tributacao_id, type,
                    price, cost_price, purchase_price, profit_margin, stock_quantity, min_stock, max_stock,
                    stock_address, stock_entry_location, stock_exit_location, quantidade_embalagem,
                    weight, height_cm, width_cm, length_cm,
                    dimensions, image, is_active, consumo_proprio, balanca, fracionado{$colunasComissao}{$colunasAnvisa}{$colunasNcmUnit}, created_at, updated_at
                ) VALUES (
                    :company_id, :name, :description, :barcode, :category_id, :grupo_id, :subgrupo_id, :grupo_tributacao_id, :type,
                    :price, :cost_price, :purchase_price, :profit_margin, :stock_quantity, :min_stock, :max_stock,
                    :stock_address, :stock_entry_location, :stock_exit_location, :quantidade_embalagem,
                    :weight, :height_cm, :width_cm, :length_cm,
                    :dimensions, :image, :is_active, :consumo_proprio, :balanca, :fracionado{$valoresComissao}{$valoresAnvisa}{$valoresNcmUnit}, NOW(), NOW()
                )
            ");

            // Extrair todos os placeholders do SQL
            preg_match_all('/:(\w+)/', $stmt->queryString, $matches);
            $placeholdersInQuery = array_unique($matches[1] ?? []);

            // Garantir que todos os placeholders tenham valores
            foreach ($placeholdersInQuery as $placeholder) {
                if (!array_key_exists($placeholder, $dataToExecute)) {
                    $dataToExecute[$placeholder] = null;
                }
            }

            // Remover campos que não estão no INSERT (mas manter os que estão nos placeholders)
            $allowedKeys = [
                'company_id',
                'name',
                'description',
                'barcode',
                'category_id',
                'grupo_id',
                'subgrupo_id',
                'grupo_tributacao_id',
                'type',
                'price',
                'cost_price',
                'purchase_price',
                'profit_margin',
                'stock_quantity',
                'min_stock',
                'max_stock',
                'stock_address',
                'stock_entry_location',
                'stock_exit_location',
                'quantidade_embalagem',
                'weight',
                'height_cm',
                'width_cm',
                'length_cm',
                'dimensions',
                'image',
                'is_active',
                'consumo_proprio',
                'balanca',
                'fracionado',
                'comissao',
                'ncm',
                'unit'
            ];
            // Adicionar campos ANVISA se existirem
            foreach ($camposAnvisaExistentes as $campo) {
                $allowedKeys[] = $campo;
            }

            // Filtrar apenas os campos permitidos E os placeholders necessários
            $finalData = [];
            foreach ($placeholdersInQuery as $placeholder) {
                if (isset($dataToExecute[$placeholder])) {
                    $finalData[$placeholder] = $dataToExecute[$placeholder];
                } elseif (in_array($placeholder, $allowedKeys)) {
                    $finalData[$placeholder] = null;
                }
            }
            $dataToExecute = $finalData;

            $stmt->execute($dataToExecute);
            $produtoId = (int) $this->db->lastInsertId();

            // Gerar SKU automaticamente baseado no ID
            $sku = 'PROD' . str_pad($produtoId, 4, '0', STR_PAD_LEFT);
            $stmtSku = $this->db->prepare("UPDATE produtos SET sku = :sku WHERE id = :id");
            $stmtSku->execute(['sku' => $sku, 'id' => $produtoId]);

            // Se houver quantidade inicial, criar movimentação de entrada
            if ($stockQuantity > 0 && $data['type'] === 'produto') {
                try {
                    $stmtMov = $this->db->prepare("
                        INSERT INTO estoque_movimentos (
                            company_id, product_id, type, quantity,
                            reference_type, reference_id, notes, created_at
                        ) VALUES (
                            :company_id, :product_id, 'entrada', :quantity,
                            'produto', :reference_id, 'Estoque inicial do produto', NOW()
                        )
                    ");
                    $stmtMov->execute([
                        'company_id' => $companyId,
                        'product_id' => $produtoId,
                        'quantity' => $stockQuantity,
                        'reference_id' => $produtoId
                    ]);
                } catch (\Exception $e) {
                    // Se a tabela usar item_id em vez de product_id, tenta assim
                    try {
                        $stmtMov = $this->db->prepare("
                            INSERT INTO estoque_movimentos (
                                company_id, item_id, type, quantity,
                                reference_type, reference_id, notes, created_at
                            ) VALUES (
                                :company_id, :item_id, 'entrada', :quantity,
                                'produto', :reference_id, 'Estoque inicial do produto', NOW()
                            )
                        ");
                        $stmtMov->execute([
                            'company_id' => $companyId,
                            'item_id' => $produtoId,
                            'quantity' => $stockQuantity,
                            'reference_id' => $produtoId
                        ]);
                    } catch (\Exception $e2) {
                        // Ignora erro, não quebra criação do produto
                        error_log("Erro ao criar movimentação de estoque: " . $e2->getMessage());
                    }
                }
            }

            // Salvar itens do kit se houver
            $kitItens = $this->request->post('kit_itens', []);
            if (!empty($kitItens) && is_array($kitItens)) {
                $this->salvarItensKit($companyId, $produtoId, $kitItens);
            }

            // Salvar ingredientes da formulação se houver
            $formulacaoItens = $this->request->post('formulacao_itens', []);
            if (!empty($formulacaoItens) && is_array($formulacaoItens)) {
                $this->salvarFormulacao($companyId, $produtoId, $formulacaoItens);
            }

            // Salvar todos os dados da aba Preços e Custos na tabela produto_preco
            try {
                // Salvar preços por quantidade
                $precos = $this->request->post('precos', []);
                if (!empty($precos) && is_array($precos)) {
                    $this->salvarPrecosPorQuantidade($companyId, $produtoId, $precos);
                }

                // Salvar tabelas de preço
                $tabelas = $this->request->post('tabelas', []);
                if (!empty($tabelas) && is_array($tabelas)) {
                    $this->salvarTabelasPreco($companyId, $produtoId, $tabelas);
                }
            } catch (Exception $e) {
                error_log("Erro ao processar dados da aba Preços e Custos: " . $e->getMessage());
                // Continua mesmo se houver erro
            }

            // Salvar empresas vinculadas
            $empresasVinculadas = $this->request->post('empresas_vinculadas');
            $empresasIds = [];
            if (!empty($empresasVinculadas)) {
                $decoded = json_decode($empresasVinculadas, true);
                if (is_array($decoded)) {
                    $empresasIds = $decoded;
                }
            }
            $this->salvarEmpresasVinculadas($produtoId, $empresasIds);

            $this->logActivity('create', 'produtos', $produtoId, $data);

            $this->db->commit();

            $this->success('Produto criado com sucesso', [
                'id' => $produtoId,
                'redirect' => $this->getRouteBase()
            ]);

        } catch (Exception $e) {
            $this->db->rollBack();
            $errorMessage = $e->getMessage();
            error_log("Erro ao criar produto: " . $errorMessage);
            error_log("Stack trace: " . $e->getTraceAsString());
            if ($e instanceof \PDOException) {
                error_log("SQL State: " . $e->getCode());
                error_log("SQL Error Info: " . print_r($e->errorInfo ?? [], true));
                $errorMessage = "Erro no banco de dados: " . ($e->errorInfo[2] ?? $errorMessage);
            }
            $this->error('Erro ao cadastrar produto', ['exception' => $errorMessage, 'details' => $e->getTraceAsString()]);
        }
    }

    /**
     * Exibe formulário de edição
     */
    public function edit(): void
    {
        // Verificar permissão de edição
        if (!$this->canEdit('produtos')) {
            $this->response->forbidden('Você não tem permissão para editar produtos.');
            return;
        }

        $id = (int) $this->request->get('id');
        $produto = $this->getProduto($id);

        if (!$produto) {
            $_SESSION['error_message'] = 'Produto não encontrado';
            header('Location: ' . url($this->getRouteBase()));
            exit;
        }

        $companyId = $this->getCompanyId();

        $gruposItens = $this->getGruposItens();
        $subgruposItens = $this->getSubgruposItens();
        $tabelasPreco = $this->getTabelasPreco();
        $gruposTributacao = $this->getGruposTributacao();

        // Buscar produtos para o kit (igual na venda)
        $produtos = [];
        if ($companyId) {
            $stmt = $this->db->prepare("
                SELECT
                    p.id,
                    p.name,
                    p.sku,
                    COALESCE(
                        (SELECT pp.valor FROM produto_preco pp
                         WHERE pp.produto_id = p.id
                         AND pp.company_id = p.company_id
                         AND pp.ativo = 1
                         ORDER BY pp.tabela_preco_id ASC, pp.ordem ASC
                         LIMIT 1),
                        0
                    ) as price,
                    p.stock_quantity
                FROM produtos p
                WHERE p.company_id = ? AND p.is_active = 1
                ORDER BY p.name ASC
            ");
            $stmt->execute([$companyId]);
            $produtos = $stmt->fetchAll();
        }

        // Buscar locais de estoque
        $locaisEstoque = [];
        if ($companyId) {
            $stmt = $this->db->prepare("
                SELECT id, name, tipo
                FROM locais_estoque
                WHERE company_id = ? AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute([$companyId]);
            $locaisEstoque = $stmt->fetchAll();
        }

        // Buscar itens do kit
        $kitItens = $this->carregarItensKit($companyId, $id);

        // Buscar ingredientes da formulação
        $formulacaoItens = $this->carregarFormulacao($id);

        // Buscar TODOS os registros de produto_preco para debug
        $todosPrecos = $this->carregarTodosPrecos($companyId, $id);
        error_log("Todos os preços do produto {$id}: " . json_encode($todosPrecos, JSON_UNESCAPED_UNICODE));

        // Buscar preços por quantidade
        $precosPorQuantidade = $this->carregarPrecosPorQuantidade($companyId, $id);

        // Buscar tabelas de preço
        $tabelasPrecoProduto = $this->carregarTabelasPreco($companyId, $id);

        // Log detalhado para debug
        $this->logDebug("=== DEBUG TABELAS PRECO (edit method) ===");
        $this->logDebug("Produto ID: {$id}");
        $this->logDebug("Company ID: {$companyId}");
        $this->logDebug("Tabelas encontradas: " . count($tabelasPrecoProduto));
        $this->logDebug("Dados das tabelas: " . json_encode($tabelasPrecoProduto, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
        $this->logDebug("===========================");

        // Buscar empresas vinculadas
        $todasEmpresas = $this->getTodasEmpresas();
        $empresasVinculadas = $this->getEmpresasVinculadas($id);

        // Determinar qual view usar baseado na rota
        $routePath = $this->request->path();
        $isItens = strpos($routePath, '/itens') !== false;
        $viewName = $isItens ? 'itens/edit' : 'produtos/edit';

        $this->view($viewName, [
            'produto' => $produto,
            'gruposItens' => $gruposItens ?: [],
            'subgruposItens' => $subgruposItens ?: [],
            'tabelasPreco' => $tabelasPreco ?: [],
            'gruposTributacao' => $gruposTributacao ?: [],
            'produtos' => $produtos,
            'kitItens' => $kitItens ?: [],
            'precosPorQuantidade' => $precosPorQuantidade ?: [],
            'tabelasPrecoProduto' => $tabelasPrecoProduto ?: [],
            'locaisEstoque' => $locaisEstoque ?: [],
            'todasEmpresas' => $todasEmpresas ?: [],
            'empresasVinculadas' => $empresasVinculadas ?: [],
            'pageTitle' => ($isItens ? 'Editar Item' : 'Editar Produto') . ': ' . $produto['name'],
            'activeMenu' => $isItens ? 'itens' : 'produtos'
        ]);
    }

    /**
     * Atualiza um produto
     */
    public function update(): void
    {
        // Verificar permissão de edição
        if (!$this->canEdit('produtos')) {
            $this->response->forbidden('Você não tem permissão para editar produtos.');
            return;
        }

        try {
            $this->logDebug("=== INÍCIO UPDATE PRODUTO ===");
            $id = (int) $this->request->post('id');
            $this->logDebug("ID recebido: {$id}");

            if (!$id) {
                $this->logDebug("ERRO: ID não informado");
                $this->error('ID do produto não informado');
                return;
            }

            $this->logDebug("Buscando produto ID: {$id}");
            $produto = $this->getProduto($id);

            if (!$produto) {
                $this->logDebug("ERRO: Produto não encontrado para ID: {$id}");
                $this->error('Produto não encontrado');
                return;
            }

            $this->logDebug("Produto encontrado: " . $produto['name']);

            if (!$this->db) {
                $this->logDebug("ERRO: Conexão com banco de dados não disponível");
                $this->error('Erro de conexão com banco de dados');
                return;
            }

            $this->logDebug("Conexão com banco OK");

            $grupoTributacaoPost = $this->request->post('grupo_tributacao_id');

            // Log para debug
            $this->logDebug("=== UPDATE PRODUTO DEBUG ===");
            $this->logDebug("grupo_tributacao_id recebido (raw): " . var_export($grupoTributacaoPost, true));
            $this->logDebug("Tipo do valor: " . gettype($grupoTributacaoPost));
            $this->logDebug("Todos os POST: " . json_encode($_POST, JSON_UNESCAPED_UNICODE));

            // Verificar se o campo está presente no POST
            if (!isset($_POST['grupo_tributacao_id'])) {
                $this->logDebug("⚠️ ATENÇÃO: grupo_tributacao_id NÃO está presente no POST!");
            } else {
                $this->logDebug("✓ grupo_tributacao_id está presente no POST: " . var_export($_POST['grupo_tributacao_id'], true));
            }

            $stockAddress = $this->sanitizeString($this->request->post('stock_address'));
            // Agora recebe ID do local, não mais texto
            $stockEntryLocation = $this->request->post('stock_entry_location') ? (int) $this->request->post('stock_entry_location') : null;
            $stockExitLocation = $this->request->post('stock_exit_location') ? (int) $this->request->post('stock_exit_location') : null;
            $quantidadeEmbalagem = $this->request->post('quantidade_embalagem') ? (int) $this->request->post('quantidade_embalagem') : 1;

            $height = $this->sanitizeDecimal($this->request->post('height_cm'));
            $width = $this->sanitizeDecimal($this->request->post('width_cm'));
            $length = $this->sanitizeDecimal($this->request->post('length_cm'));
            $weight = $this->sanitizeDecimal($this->request->post('weight'));

            $data = [
                'name' => $this->request->post('name'),
                'description' => $this->request->post('description'),
                'barcode' => $this->request->post('barcode'),
                'category_id' => $this->request->post('category_id') ?: null,
                'grupo_id' => $this->request->post('grupo_id') ?: null,
                'subgrupo_id' => $this->request->post('subgrupo_id') ?: null,
                'grupo_tributacao_id' => (!empty($grupoTributacaoPost) && $grupoTributacaoPost !== '' && $grupoTributacaoPost !== '0') ? (int) $grupoTributacaoPost : null,
                'type' => $this->request->post('type'),
                'price' => $this->request->post('price') ?: 0.00,
                'cost_price' => $this->request->post('cost_price') ?: 0.00,
                'purchase_price' => $this->request->post('purchase_price') ?: 0.00,
                'profit_margin' => $this->request->post('profit_margin') ?: 0.00,
                'comissao' => $this->sanitizeDecimal($this->request->post('comissao')) ?: null,
                'stock_quantity' => $this->request->post('stock_quantity') ?: 0,
                'min_stock' => $this->request->post('min_stock') ?: 0,
                'max_stock' => $this->request->post('max_stock') ?: 0,
                'stock_address' => $stockAddress,
                'stock_entry_location' => $stockEntryLocation,
                'stock_exit_location' => $stockExitLocation,
                'quantidade_embalagem' => $quantidadeEmbalagem,
                'weight' => $weight ?? 0.00,
                'height_cm' => $height,
                'width_cm' => $width,
                'length_cm' => $length,
                'dimensions' => $this->buildDimensions($height, $width, $length),
                'image' => $this->request->post('image'),
                'is_active' => $this->request->post('is_active') ? 1 : 0,
                'consumo_proprio' => $this->request->post('consumo_proprio') ? 1 : 0,
                'balanca' => $this->request->post('balanca') ? 1 : 0,
                'fracionado' => $this->request->post('fracionado') ? 1 : 0,
                'id' => $id
            ];

            $this->logDebug("grupo_tributacao_id processado: " . var_export($data['grupo_tributacao_id'], true));

            $this->logDebug("Iniciando validação...");
            $errors = $this->validate([
                'name' => 'required|min:2',
                'type' => 'required|in:produto,servico',
                'price' => 'required|numeric|min:0',
            ]);

            if (!empty($errors)) {
                $this->logDebug("ERRO DE VALIDAÇÃO: " . json_encode($errors, JSON_UNESCAPED_UNICODE));
                $this->error('Dados inválidos', $errors);
                return;
            }

            $this->logDebug("Validação passou com sucesso");

            // Verifica e corrige FK ANTES de iniciar transação
            $this->verificarEFixarFK();

            $this->db->beginTransaction();
            $data['company_id'] = $this->getCompanyId();

            if (!$data['company_id']) {
                $this->db->rollBack();
                $this->error('Company ID não encontrado');
                return;
            }

            // Verificar se coluna comissao existe
            $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE 'comissao'");
            $colunaComissaoExiste = $stmtCheck->rowCount() > 0;

            // Verificar se colunas ANVISA existem
            $camposAnvisa = ['anvisa', 'validade_anvisa', 'classificacao_risco', 'codigo_simpro', 'codigo_sus'];
            $camposAnvisaExistentes = [];
            foreach ($camposAnvisa as $campo) {
                try {
                    $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE '{$campo}'");
                    if ($stmtCheck->rowCount() > 0) {
                        $camposAnvisaExistentes[] = $campo;
                    }
                } catch (Exception $e) {
                    // Campo não existe, ignorar
                }
            }

            $colunaComissaoUpdate = $colunaComissaoExiste ? ', comissao = :comissao' : '';

            $colunasAnvisaUpdate = '';
            if (!empty($camposAnvisaExistentes)) {
                $setsAnvisa = [];
                foreach ($camposAnvisaExistentes as $campo) {
                    $setsAnvisa[] = $campo . ' = :' . $campo;
                }
                $colunasAnvisaUpdate = ', ' . implode(', ', $setsAnvisa);
            }

            // Preparar dados para execução
            $dataToExecute = $data;

            // Adicionar campos ANVISA se existirem
            foreach ($camposAnvisaExistentes as $campo) {
                if ($campo === 'validade_anvisa') {
                    $valor = $this->request->post($campo);
                    $dataToExecute[$campo] = !empty($valor) ? $valor : null;
                } else {
                    $valor = $this->request->post($campo);
                    $dataToExecute[$campo] = !empty($valor) ? trim($valor) : null;
                }
            }

            // Remover comissao do array se a coluna não existir (ANTES de qualquer processamento)
            if (!$colunaComissaoExiste) {
                unset($dataToExecute['comissao']);
            } else {
                // Se a coluna existe mas o valor não está no array, adicionar como null
                if (!isset($dataToExecute['comissao'])) {
                    $dataToExecute['comissao'] = null;
                }
            }

            // Garantir que campos opcionais sejam null se vazios
            $optionalFields = ['description', 'barcode', 'stock_address', 'stock_entry_location', 'stock_exit_location', 'image', 'dimensions'];
            foreach ($optionalFields as $field) {
                if (isset($dataToExecute[$field]) && $dataToExecute[$field] === '') {
                    $dataToExecute[$field] = null;
                }
            }

            // Garantir que campos numéricos opcionais sejam null se não informados
            $numericOptionalFields = ['height_cm', 'width_cm', 'length_cm'];
            foreach ($numericOptionalFields as $field) {
                if (isset($dataToExecute[$field]) && ($dataToExecute[$field] === '' || $dataToExecute[$field] === null)) {
                    $dataToExecute[$field] = null;
                }
            }

            // Logs DEPOIS de processar
            $this->logDebug("Coluna comissao existe: " . ($colunaComissaoExiste ? 'SIM' : 'NÃO'));
            $this->logDebug("Comissao no array: " . (isset($dataToExecute['comissao']) ? var_export($dataToExecute['comissao'], true) : 'NÃO EXISTE'));
            $this->logDebug("grupo_tributacao_id no array: " . (isset($dataToExecute['grupo_tributacao_id']) ? var_export($dataToExecute['grupo_tributacao_id'], true) : 'NÃO EXISTE'));
            $this->logDebug("Total de parâmetros no array: " . count($dataToExecute));
            $this->logDebug("Chaves do array: " . implode(', ', array_keys($dataToExecute)));

            // Construir a query para debug
            $query = "
                UPDATE produtos SET
                    name = :name,
                    description = :description,
                    barcode = :barcode,
                    category_id = :category_id,
                    grupo_id = :grupo_id,
                    subgrupo_id = :subgrupo_id,
                    grupo_tributacao_id = :grupo_tributacao_id,
                    type = :type,
                    price = :price,
                    cost_price = :cost_price,
                    purchase_price = :purchase_price,
                    profit_margin = :profit_margin,
                    stock_quantity = :stock_quantity,
                    min_stock = :min_stock,
                    max_stock = :max_stock,
                    stock_address = :stock_address,
                    stock_entry_location = :stock_entry_location,
                    stock_exit_location = :stock_exit_location,
                    quantidade_embalagem = :quantidade_embalagem,
                    weight = :weight,
                    height_cm = :height_cm,
                    width_cm = :width_cm,
                    length_cm = :length_cm,
                    dimensions = :dimensions,
                    image = :image,
                    is_active = :is_active,
                    consumo_proprio = :consumo_proprio,
                    balanca = :balanca,
                    fracionado = :fracionado{$colunaComissaoUpdate}{$colunasAnvisaUpdate},
                    updated_at = NOW()
                WHERE id = :id AND company_id = :company_id
            ";

            // Extrair todos os placeholders da query
            preg_match_all('/:(\w+)/', $query, $matches);
            $placeholdersInQuery = $matches[1] ?? [];
            $this->logDebug("Placeholders na query: " . implode(', ', $placeholdersInQuery));

            // Verificar quais placeholders estão faltando no array
            $missingParams = array_diff($placeholdersInQuery, array_keys($dataToExecute));
            if (!empty($missingParams)) {
                $this->logDebug("ERRO: Parâmetros faltando no array: " . implode(', ', $missingParams));
            }

            // Verificar quais chaves do array não estão na query
            $extraParams = array_diff(array_keys($dataToExecute), $placeholdersInQuery);
            if (!empty($extraParams)) {
                $this->logDebug("Aviso: Parâmetros extras no array (serão removidos): " . implode(', ', $extraParams));
                // Remover parâmetros extras do array para evitar erro do PDO
                // MAS NÃO remover grupo_tributacao_id se estiver na query
                foreach ($extraParams as $param) {
                    if ($param !== 'grupo_tributacao_id' || !in_array('grupo_tributacao_id', $placeholdersInQuery)) {
                        unset($dataToExecute[$param]);
                    }
                }
            }

            // Garantir que grupo_tributacao_id esteja no array se estiver na query
            if (in_array('grupo_tributacao_id', $placeholdersInQuery) && !isset($dataToExecute['grupo_tributacao_id'])) {
                $this->logDebug("ATENÇÃO: grupo_tributacao_id está na query mas não está no array! Adicionando como null.");
                $dataToExecute['grupo_tributacao_id'] = null;
            }

            $stmt = $this->db->prepare($query);

            // Verificar novamente antes de executar
            $this->logDebug("Executando UPDATE com " . count($dataToExecute) . " parâmetros");
            $this->logDebug("Chaves finais do array: " . implode(', ', array_keys($dataToExecute)));
            $this->logDebug("grupo_tributacao_id no array final: " . var_export($dataToExecute['grupo_tributacao_id'] ?? 'NÃO EXISTE', true));

            try {
                $stmt->execute($dataToExecute);
            } catch (\PDOException $e) {
                $this->logDebug("ERRO ao executar: " . $e->getMessage());
                $this->logDebug("Query: " . $query);
                $this->logDebug("Parâmetros: " . json_encode($dataToExecute, JSON_UNESCAPED_UNICODE));
                throw $e;
            }

            $rowsAffected = $stmt->rowCount();
            $this->logDebug("UPDATE executado. Linhas afetadas: {$rowsAffected}. grupo_tributacao_id: " . var_export($data['grupo_tributacao_id'], true));

            if ($rowsAffected === 0) {
                $this->db->rollBack();
                $this->logDebug("ATENÇÃO: Nenhuma linha foi afetada no UPDATE. ID: {$id}, Company ID: {$data['company_id']}");
                $this->error('Produto não encontrado ou sem permissão para editar');
                return;
            }

            // Salvar/atualizar itens do kit se houver
            try {
                $kitItens = $this->request->post('kit_itens', []);
                if (!empty($kitItens) && is_array($kitItens)) {
                    $this->salvarItensKit($data['company_id'], $id, $kitItens);
                } else {
                    // Se não houver itens, remover todos os itens do kit existentes
                    try {
                        $stmtCheck = $this->db->query("SHOW TABLES LIKE 'produtos_kit'");
                        if ($stmtCheck->rowCount() > 0) {
                            $stmtDelete = $this->db->prepare("
                                DELETE FROM produtos_kit
                                WHERE company_id = ? AND produto_id = ?
                            ");
                            $stmtDelete->execute([$data['company_id'], $id]);
                        }
                    } catch (Exception $e) {
                        // Ignora erro se tabela não existir
                    }
                }
            } catch (Exception $e) {
                error_log("Erro ao processar itens do kit: " . $e->getMessage());
                error_log("Stack trace: " . $e->getTraceAsString());
                // Continua mesmo se houver erro nos itens do kit
            }

            // Salvar/atualizar ingredientes da formulação se houver
            try {
                $formulacaoItens = $this->request->post('formulacao_itens', []);
                if (!empty($formulacaoItens) && is_array($formulacaoItens)) {
                    $this->salvarFormulacao($data['company_id'], $id, $formulacaoItens);
                } else {
                    // Se não houver itens, remover todos os ingredientes existentes
                    try {
                        $stmtCheck = $this->db->query("SHOW TABLES LIKE 'produto_formulacao'");
                        if ($stmtCheck->rowCount() > 0) {
                            $stmtDelete = $this->db->prepare("
                                DELETE FROM produto_formulacao
                                WHERE produto_id = ?
                            ");
                            $stmtDelete->execute([$id]);
                        }
                    } catch (Exception $e) {
                        // Ignora erro se tabela não existir
                    }
                }
            } catch (Exception $e) {
                error_log("Erro ao processar formulação: " . $e->getMessage());
                error_log("Stack trace: " . $e->getTraceAsString());
                // Continua mesmo se houver erro na formulação
            }

            // Salvar todos os dados da aba Preços e Custos na tabela produto_preco
            try {
                // LOG: Verificar o que está chegando no POST
                $logFile = ROOT_PATH . '/storage/logs/produto_preco-' . date('Y-m-d') . '.log';
                $logMsg = "\n" . str_repeat('=', 80) . "\n";
                $logMsg .= "[UPDATE PRODUTO] Produto ID: {$id}, Company ID: {$data['company_id']}\n";
                $logMsg .= "POST completo (tabelas): " . print_r($_POST['tabelas'] ?? 'NÃO EXISTE', true) . "\n";
                $logMsg .= "POST completo (precos): " . print_r($_POST['precos'] ?? 'NÃO EXISTE', true) . "\n";
                error_log($logMsg, 3, $logFile);

                // Primeiro, remover todos os preços existentes para este produto
                $stmtCheck = $this->db->query("SHOW TABLES LIKE 'produto_preco'");
                if ($stmtCheck->rowCount() > 0) {
                    $stmtDelete = $this->db->prepare("
                        DELETE FROM produto_preco
                        WHERE company_id = ? AND produto_id = ?
                    ");
                    $stmtDelete->execute([$data['company_id'], $id]);
                    error_log("DELETE executado: removidos registros antigos de produto_preco\n", 3, $logFile);
                }

                // Salvar preços por quantidade
                $precos = $this->request->post('precos', []);
                error_log("Preços recebidos: " . print_r($precos, true) . "\n", 3, $logFile);
                if (!empty($precos) && is_array($precos)) {
                    $this->salvarPrecosPorQuantidade($data['company_id'], $id, $precos);
                } else {
                    error_log("AVISO: Array de preços está vazio ou não é array\n", 3, $logFile);
                }

                // Salvar tabelas de preço
                $tabelas = $this->request->post('tabelas', []);
                error_log("Tabelas recebidas: " . print_r($tabelas, true) . "\n", 3, $logFile);
                error_log("Tipo de tabelas: " . gettype($tabelas) . "\n", 3, $logFile);
                error_log("Tabelas está vazio? " . (empty($tabelas) ? 'SIM' : 'NÃO') . "\n", 3, $logFile);
                error_log("Tabelas é array? " . (is_array($tabelas) ? 'SIM' : 'NÃO') . "\n", 3, $logFile);

                if (!empty($tabelas) && is_array($tabelas)) {
                    error_log("Chamando salvarTabelasPreco com " . count($tabelas) . " tabela(s)\n", 3, $logFile);
                    $this->salvarTabelasPreco($data['company_id'], $id, $tabelas);
                    error_log("salvarTabelasPreco concluído\n", 3, $logFile);
                } else {
                    error_log("ERRO: Array de tabelas está vazio ou não é array! Não vai salvar nada.\n", 3, $logFile);
                }

                error_log(str_repeat('=', 80) . "\n", 3, $logFile);
            } catch (Exception $e) {
                $logFile = ROOT_PATH . '/storage/logs/produto_preco-' . date('Y-m-d') . '.log';
                error_log("ERRO FATAL ao processar dados da aba Preços e Custos: " . $e->getMessage() . "\n", 3, $logFile);
                error_log("Stack trace: " . $e->getTraceAsString() . "\n", 3, $logFile);
                error_log("Erro ao processar dados da aba Preços e Custos: " . $e->getMessage());
                // Continua mesmo se houver erro
            }

            // Salvar empresas vinculadas
            $empresasVinculadas = $this->request->post('empresas_vinculadas');
            $empresasIds = [];
            if (!empty($empresasVinculadas)) {
                $decoded = json_decode($empresasVinculadas, true);
                if (is_array($decoded)) {
                    $empresasIds = $decoded;
                }
            }
            $this->salvarEmpresasVinculadas($id, $empresasIds);

            // Log de atividade (pode falhar silenciosamente se a tabela não existir)
            try {
                $this->logActivity('update', 'produtos', $id, $data);
            } catch (Exception $e) {
                error_log("Erro ao registrar log de atividade: " . $e->getMessage());
                // Continua mesmo se o log falhar
            }

            $this->db->commit();
            $this->logDebug("UPDATE concluído com sucesso!");

            $this->success('Produto atualizado com sucesso', [
                'redirect' => $this->getRouteBase()
            ]);

        } catch (\PDOException $e) {
            if ($this->db && $this->db->inTransaction()) {
                $this->db->rollBack();
            }

            $errorMsg = $e->getMessage();

            $this->logDebug("=== ERRO PDO AO ATUALIZAR PRODUTO ===");
            $this->logDebug("Mensagem: " . $errorMsg);
            $this->logDebug("Código SQL: " . $e->getCode());
            $this->logDebug("ID do produto: " . ($id ?? 'não definido'));

            // Erro de foreign key - grupo_tributacao_id apontando para tabela errada
            if (
                strpos($errorMsg, "Cannot add or update a child row") !== false &&
                (strpos($errorMsg, "grupo_tributacao_id") !== false || strpos($errorMsg, "produtos_ibfk_2") !== false || strpos($errorMsg, "categorias") !== false)
            ) {

                $this->logDebug("ERRO DE FOREIGN KEY DETECTADO: " . $errorMsg);

                // CORREÇÃO AUTOMÁTICA: Remove FK errada e cria a correta
                try {
                    // 1. Remove FK incorreta
                    $this->db->exec("ALTER TABLE produtos DROP FOREIGN KEY produtos_ibfk_2");
                    $this->logDebug("✓ FK produtos_ibfk_2 removida");

                    // 2. Verifica se tabela impostos existe e qual o tipo da coluna id
                    $checkImpostos = $this->db->query("SHOW TABLES LIKE 'impostos'");
                    if ($checkImpostos->rowCount() > 0) {
                        // 3. Verifica tipo de dados da coluna id em impostos
                        $checkIdType = $this->db->query("
                            SELECT COLUMN_TYPE
                            FROM INFORMATION_SCHEMA.COLUMNS
                            WHERE TABLE_SCHEMA = DATABASE()
                            AND TABLE_NAME = 'impostos'
                            AND COLUMN_NAME = 'id'
                        ");
                        $idTypeInfo = $checkIdType->fetch();
                        $this->logDebug("Tipo de impostos.id: " . ($idTypeInfo['COLUMN_TYPE'] ?? 'não encontrado'));

                        // 4. Verifica tipo de dados de grupo_tributacao_id em produtos
                        $checkProdType = $this->db->query("
                            SELECT COLUMN_TYPE
                            FROM INFORMATION_SCHEMA.COLUMNS
                            WHERE TABLE_SCHEMA = DATABASE()
                            AND TABLE_NAME = 'produtos'
                            AND COLUMN_NAME = 'grupo_tributacao_id'
                        ");
                        $prodTypeInfo = $checkProdType->fetch();
                        $this->logDebug("Tipo de produtos.grupo_tributacao_id: " . ($prodTypeInfo['COLUMN_TYPE'] ?? 'não encontrado'));

                        // 5. Remove FK antiga se existir com outro nome
                        try {
                            $this->db->exec("ALTER TABLE produtos DROP FOREIGN KEY fk_produtos_grupo_tributacao");
                        } catch (\PDOException $e3) {
                            // Ignora se não existir
                        }

                        // 6. Se tipos não batem, ajusta grupo_tributacao_id para BIGINT
                        if (
                            $idTypeInfo && strpos($idTypeInfo['COLUMN_TYPE'], 'bigint') !== false &&
                            $prodTypeInfo && strpos($prodTypeInfo['COLUMN_TYPE'], 'int') !== false &&
                            strpos($prodTypeInfo['COLUMN_TYPE'], 'bigint') === false
                        ) {
                            $this->db->exec("ALTER TABLE produtos MODIFY COLUMN grupo_tributacao_id BIGINT(20) UNSIGNED NULL");
                            $this->logDebug("✓ Tipo de grupo_tributacao_id alterado para BIGINT");
                        }

                        // 7. Cria FK correta
                        $this->db->exec("
                            ALTER TABLE produtos
                            ADD CONSTRAINT fk_produtos_grupo_tributacao
                            FOREIGN KEY (grupo_tributacao_id)
                            REFERENCES impostos(id)
                            ON DELETE SET NULL
                            ON UPDATE CASCADE
                        ");
                        $this->logDebug("✓ FK correta criada apontando para impostos");

                        // 8. Reexecuta o UPDATE
                        $this->db->beginTransaction();
                        // Verificar campos ANVISA para o UPDATE de correção
                        $camposAnvisa = ['anvisa', 'validade_anvisa', 'classificacao_risco', 'codigo_simpro', 'codigo_sus'];
                        $camposAnvisaExistentes = [];
                        foreach ($camposAnvisa as $campo) {
                            try {
                                $stmtCheck = $this->db->query("SHOW COLUMNS FROM produtos LIKE '{$campo}'");
                                if ($stmtCheck->rowCount() > 0) {
                                    $camposAnvisaExistentes[] = $campo;
                                }
                            } catch (Exception $e) {
                                // Campo não existe, ignorar
                            }
                        }
                        $colunasAnvisaUpdateCorrecao = '';
                        if (!empty($camposAnvisaExistentes)) {
                            $setsAnvisa = [];
                            foreach ($camposAnvisaExistentes as $campo) {
                                $setsAnvisa[] = $campo . ' = :' . $campo;
                            }
                            $colunasAnvisaUpdateCorrecao = ', ' . implode(', ', $setsAnvisa);
                        }

                        $stmt = $this->db->prepare("
                            UPDATE produtos SET
                                name = :name, description = :description, barcode = :barcode,
                                category_id = :category_id, grupo_id = :grupo_id, subgrupo_id = :subgrupo_id,
                                grupo_tributacao_id = :grupo_tributacao_id, type = :type,
                                price = :price, cost_price = :cost_price, purchase_price = :purchase_price,
                                profit_margin = :profit_margin, stock_quantity = :stock_quantity,
                                min_stock = :min_stock, max_stock = :max_stock,
                                stock_address = :stock_address, stock_entry_location = :stock_entry_location,
                                stock_exit_location = :stock_exit_location, quantidade_embalagem = :quantidade_embalagem, weight = :weight,
                                height_cm = :height_cm, width_cm = :width_cm, length_cm = :length_cm,
                                dimensions = :dimensions, image = :image, is_active = :is_active,
                                consumo_proprio = :consumo_proprio, balanca = :balanca, fracionado = :fracionado{$colunasAnvisaUpdateCorrecao},
                                updated_at = NOW()
                            WHERE id = :id AND company_id = :company_id
                        ");
                        $stmt->execute($data);
                        $this->logActivity('update', 'produtos', $id, $data);
                        $this->db->commit();
                        $this->logDebug("✓ UPDATE concluído após correção automática");

                        $this->success('Produto atualizado com sucesso', ['redirect' => '/produtos']);
                        return;
                    }
                } catch (\PDOException $e2) {
                    $this->logDebug("Erro na correção automática: " . $e2->getMessage());
                }

                $this->error('Erro: A Foreign Key de grupo_tributacao_id está apontando para a tabela errada (categorias). Tente acessar: http://' . $_SERVER['HTTP_HOST'] . '/database/fix_grupo_tributacao_id.php para corrigir.');
                return;
            }

            // Erro de coluna inexistente
            if (strpos($errorMsg, "Unknown column") !== false) {
                $this->error('Erro: Coluna não encontrada no banco de dados. Verifique as migrações.');
                return;
            }

            // Outros erros
            $this->error('Erro ao atualizar produto: ' . $errorMsg);

        } catch (\Exception $e) {
            if ($this->db && $this->db->inTransaction()) {
                $this->db->rollBack();
            }

            error_log("=== ERRO GENÉRICO AO ATUALIZAR PRODUTO ===");
            error_log("Mensagem: " . $e->getMessage());
            error_log("Arquivo: " . $e->getFile());
            error_log("Linha: " . $e->getLine());
            error_log("Stack trace: " . $e->getTraceAsString());
            error_log("POST data: " . json_encode($_POST));

            $this->error('Erro ao atualizar produto: ' . $e->getMessage());
        } catch (\Throwable $e) {
            if ($this->db && $this->db->inTransaction()) {
                $this->db->rollBack();
            }

            error_log("=== ERRO FATAL AO ATUALIZAR PRODUTO ===");
            error_log("Mensagem: " . $e->getMessage());
            error_log("Arquivo: " . $e->getFile());
            error_log("Linha: " . $e->getLine());
            error_log("Stack trace: " . $e->getTraceAsString());

            $this->error('Erro fatal ao atualizar produto: ' . $e->getMessage());
        }
    }

    /**
     * Exclui um produto
     */
    public function buscarProdutos(): void
    {
        try {
            $termo = trim((string) $this->request->get('q', ''));
            $companyId = $this->getCompanyId();

            if (!$companyId) {
                $this->error('Company ID não encontrado. Faça login novamente.', [], 401);
                return;
            }

            $consulta = "%{$termo}%";
            $stmt = $this->db->prepare("
                SELECT
                    p.id,
                    p.name,
                    p.sku,
                    COALESCE(
                        (SELECT pp.valor FROM produto_preco pp
                         WHERE pp.produto_id = p.id
                         AND pp.company_id = p.company_id
                         AND pp.ativo = 1
                         ORDER BY pp.tabela_preco_id ASC, pp.ordem ASC
                         LIMIT 1),
                        0
                    ) as price,
                    p.stock_quantity
                FROM produtos p
                WHERE p.company_id = ?
                  AND p.is_active = 1
                  AND (p.name LIKE ? OR p.sku LIKE ? OR p.barcode LIKE ?)
                ORDER BY p.name ASC
                LIMIT 50
            ");
            $stmt->execute([$companyId, $consulta, $consulta, $consulta]);
            $produtos = $stmt->fetchAll();

            $this->success('Produtos encontrados', ['data' => $produtos]);

        } catch (Exception $e) {
            error_log("Erro ao buscar produtos: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());
            $this->error('Erro ao buscar produtos: ' . $e->getMessage());
        }
    }

    public function delete(): void
    {
        // Verificar permissão de exclusão
        if (!$this->canDelete('produtos')) {
            $this->response->forbidden('Você não tem permissão para excluir produtos.');
            return;
        }

        try {
            $id = (int) $this->request->post('id');
            $produto = $this->getProduto($id);

            if (!$produto) {
                $this->error('Produto não encontrado');
                return;
            }

            // Verifica se há vendas vinculadas
            // Verificar se a tabela existe antes de consultar
            try {
                $stmtCheck = $this->db->query("SHOW TABLES LIKE 'vendas_itens'");
                if ($stmtCheck->rowCount() > 0) {
                    $stmt = $this->db->prepare("
                        SELECT COUNT(*) FROM vendas_itens
                        WHERE product_id = :id
                    ");
                    $stmt->execute(['id' => $id]);
                    $vendasCount = $stmt->fetchColumn();
                } else {
                    // Tabela não existe, considerar como 0 vendas
                    $vendasCount = 0;
                }
            } catch (Exception $e) {
                // Em caso de erro, considerar como 0 vendas para não bloquear a exclusão
                error_log("Aviso: Erro ao verificar vendas vinculadas: " . $e->getMessage());
                $vendasCount = 0;
            }

            if ($vendasCount > 0) {
                $this->error("Não é possível excluir este produto. Existem {$vendasCount} venda(s) vinculada(s).");
                return;
            }

            $this->db->beginTransaction();

            $stmt = $this->db->prepare("DELETE FROM produtos WHERE id = :id AND company_id = :company_id");
            $stmt->execute(['id' => $id, 'company_id' => $this->getCompanyId()]);

            $this->logActivity('delete', 'produtos', $id, $produto);

            $this->db->commit();

            $this->success('Produto excluído com sucesso');

        } catch (Exception $e) {
            // Verificar se há transação ativa antes de fazer rollback
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            error_log("Erro ao excluir produto: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());
            $this->error('Erro ao excluir produto');
        }
    }

    /**
     * Busca um produto por ID
     */
    private function getProduto(int $id): ?array
    {
        $stmt = $this->db->prepare("
            SELECT
                p.*,
                c.name as category_name
            FROM produtos p
            LEFT JOIN categorias c ON p.category_id = c.id
            WHERE p.id = :id AND p.company_id = :company_id
        ");
        $stmt->execute([
            'id' => $id,
            'company_id' => $this->getCompanyId()
        ]);

        return $stmt->fetch() ?: null;
    }

    /**
     * Busca categorias para select
     */
    private function getCategorias(): array
    {
        $stmt = $this->db->prepare("
            SELECT id, name, type
            FROM categorias
            WHERE company_id = :company_id AND is_active = 1
            ORDER BY sort_order ASC, name ASC
        ");
        $stmt->execute(['company_id' => $this->getCompanyId()]);

        return $stmt->fetchAll();
    }

    /**
     * Busca catálogo de tabelas de preço para select
     */
    private function getTabelasPreco(): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT id, nome, descricao
                FROM tabela_preco
                WHERE company_id = :company_id
                  AND ativo = 1
                ORDER BY ordem ASC, nome ASC
            ");
            $stmt->execute(['company_id' => $this->getCompanyId()]);

            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Aviso: Erro ao buscar tabela_preco: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Busca grupos de tributação (impostos) para select
     */
    private function getGruposTributacao(): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT id, nome, ncm, cst_csosn, icms, cst_pis, pis, cst_cofins, cofins, cst_ipi, ipi
                FROM impostos
                WHERE company_id = :company_id AND ativo = 'Sim'
                ORDER BY nome ASC
            ");
            $stmt->execute(['company_id' => $this->getCompanyId()]);

            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Aviso: Erro ao buscar impostos: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Busca grupos de itens para select
     */
    private function getGruposItens(): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT id, nome, subtipo, descricao
                FROM grupos_pessoas
                WHERE company_id = :company_id AND tipo = 'itens' AND ativo = 1
                ORDER BY ordem ASC, nome ASC
            ");
            $stmt->execute(['company_id' => $this->getCompanyId()]);

            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Aviso: Erro ao buscar grupos de itens: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Busca subgrupos de itens para select
     */
    private function getSubgruposItens(): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT sp.id, sp.nome, sp.grupo_id, gp.nome as grupo_nome
                FROM subgrupos_pessoas sp
                INNER JOIN grupos_pessoas gp ON sp.grupo_id = gp.id
                WHERE sp.company_id = :company_id AND gp.tipo = 'itens' AND sp.ativo = 1
                ORDER BY sp.ordem ASC, sp.nome ASC
            ");
            $stmt->execute(['company_id' => $this->getCompanyId()]);

            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Aviso: Erro ao buscar subgrupos de itens: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Busca fornecedores verificando se coluna tipo_fornecedor existe
     */
    private function getFornecedores(int $companyId): array
    {
        if (!$this->db) {
            return [];
        }

        // Tenta primeiro com tipo_fornecedor, se falhar usa fallback
        try {
            $stmt = $this->db->prepare("
                SELECT id, name, trade_name, document
                FROM pessoas
                WHERE company_id = :company_id
                AND tipo_fornecedor = 1
                AND is_active = 1
                ORDER BY name ASC
            ");
            $stmt->execute(['company_id' => $companyId]);
            return $stmt->fetchAll() ?: [];
        } catch (\Exception $e) {
            // Se falhar (coluna não existe), usa fallback com type
            try {
                $stmt = $this->db->prepare("
                    SELECT id, name, trade_name, document
                    FROM pessoas
                    WHERE company_id = :company_id
                    AND type IN ('fornecedor', 'ambos')
                    AND is_active = 1
                    ORDER BY name ASC
                ");
                $stmt->execute(['company_id' => $companyId]);
                return $stmt->fetchAll() ?: [];
            } catch (\Exception $e2) {
                // Erro ao buscar fornecedores - retorna array vazio
                return [];
            }
        }
    }

    /**
     * Salva os itens do kit
     */
    private function salvarItensKit(int $companyId, int $produtoId, array $kitItens): void
    {
        try {
            // Verificar se a tabela existe
            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'produtos_kit'");
            if ($stmtCheck->rowCount() === 0) {
                return; // Tabela não existe, apenas retorna
            }

            // Primeiro, remover todos os itens do kit existentes
            $stmtDelete = $this->db->prepare("
                DELETE FROM produtos_kit
                WHERE company_id = ? AND produto_id = ?
            ");
            $stmtDelete->execute([$companyId, $produtoId]);

            // Se não houver itens para adicionar, apenas retorna
            if (empty($kitItens) || !is_array($kitItens)) {
                return;
            }

            // Inserir os novos itens do kit
            $stmtInsert = $this->db->prepare("
                INSERT INTO produtos_kit (
                    company_id, produto_id, produto_kit_id, quantidade, created_at, updated_at
                ) VALUES (
                    ?, ?, ?, ?, NOW(), NOW()
                )
            ");

            foreach ($kitItens as $item) {
                if (empty($item['produto_id']) || empty($item['quantidade'])) {
                    continue;
                }

                $produtoKitId = (int) $item['produto_id'];
                $quantidade = (float) $item['quantidade'];

                if ($produtoKitId <= 0 || $quantidade <= 0) {
                    continue;
                }

                // Não permitir que o produto seja parte do seu próprio kit
                if ($produtoKitId == $produtoId) {
                    continue;
                }

                $stmtInsert->execute([$companyId, $produtoId, $produtoKitId, $quantidade]);
            }
        } catch (Exception $e) {
            error_log("Erro ao salvar itens do kit: " . $e->getMessage());
            // Não lança exceção para não quebrar o fluxo principal
        }
    }

    /**
     * Carrega os itens do kit
     */
    private function carregarItensKit(int $companyId, int $produtoId): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT
                    pk.id,
                    pk.produto_kit_id as produto_id,
                    pk.quantidade,
                    p.name as produto_nome,
                    p.sku as produto_sku,
                    COALESCE(
                        (SELECT pp.valor FROM produto_preco pp
                         WHERE pp.produto_id = p.id
                         AND pp.company_id = p.company_id
                         AND pp.ativo = 1
                         ORDER BY pp.tabela_preco_id ASC, pp.ordem ASC
                         LIMIT 1),
                        0
                    ) as produto_preco
                FROM produtos_kit pk
                INNER JOIN produtos p ON pk.produto_kit_id = p.id
                WHERE pk.company_id = :company_id
                  AND pk.produto_id = :produto_id
                ORDER BY pk.id ASC
            ");

            $stmt->execute([
                'company_id' => $companyId,
                'produto_id' => $produtoId
            ]);

            return $stmt->fetchAll() ?: [];
        } catch (Exception $e) {
            error_log("Erro ao carregar itens do kit: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Salva os ingredientes da formulação
     */
    private function salvarFormulacao(int $companyId, int $produtoId, array $formulacaoItens): void
    {
        // Nota: companyId é passado mas não usado na tabela produto_formulacao
        // A relação é feita através do produto_id que já tem company_id
        try {
            // Verificar se a tabela existe
            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'produto_formulacao'");
            if ($stmtCheck->rowCount() === 0) {
                return; // Tabela não existe, apenas retorna
            }

            // Primeiro, remover todos os ingredientes existentes
            $stmtDelete = $this->db->prepare("
                DELETE FROM produto_formulacao
                WHERE produto_id = ?
            ");
            $stmtDelete->execute([$produtoId]);

            // Se não houver itens para adicionar, apenas retorna
            if (empty($formulacaoItens) || !is_array($formulacaoItens)) {
                return;
            }

            // Inserir os novos ingredientes
            $stmtInsert = $this->db->prepare("
                INSERT INTO produto_formulacao (
                    produto_id, ingrediente_id, quantidade, unidade, observacoes, ordem, created_at, updated_at
                ) VALUES (
                    ?, ?, ?, ?, ?, ?, NOW(), NOW()
                )
            ");

            $ordem = 0;
            foreach ($formulacaoItens as $item) {
                if (empty($item['ingrediente_id']) || empty($item['quantidade'])) {
                    continue;
                }

                $ingredienteId = (int) $item['ingrediente_id'];
                $quantidade = (float) $item['quantidade'];
                $unidade = $item['unidade'] ?? 'UN';
                $observacoes = $item['observacoes'] ?? null;

                if ($ingredienteId <= 0 || $quantidade <= 0) {
                    continue;
                }

                // Não permitir que o produto seja ingrediente de si mesmo
                if ($ingredienteId == $produtoId) {
                    continue;
                }

                $ordem++;
                $stmtInsert->execute([$produtoId, $ingredienteId, $quantidade, $unidade, $observacoes, $ordem]);
            }
        } catch (Exception $e) {
            error_log("Erro ao salvar formulação: " . $e->getMessage());
            // Não lança exceção para não quebrar o fluxo principal
        }
    }

    /**
     * Carrega os ingredientes da formulação
     */
    private function carregarFormulacao(int $produtoId): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT
                    pf.id,
                    pf.ingrediente_id,
                    pf.quantidade,
                    pf.unidade,
                    pf.observacoes,
                    pf.ordem,
                    p.name as ingrediente_nome,
                    p.sku as ingrediente_sku
                FROM produto_formulacao pf
                INNER JOIN produtos p ON pf.ingrediente_id = p.id
                WHERE pf.produto_id = :produto_id
                ORDER BY pf.ordem ASC, pf.id ASC
            ");

            $stmt->execute([
                'produto_id' => $produtoId
            ]);

            return $stmt->fetchAll() ?: [];
        } catch (Exception $e) {
            error_log("Erro ao carregar formulação: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Carrega preços por quantidade da tabela produto_preco
     * Filtra registros que não começam com "Tabela:"
     */
    /**
     * Carrega TODOS os registros de produto_preco para debug
     */
    private function carregarTodosPrecos(int $companyId, int $produtoId): array
    {
        try {
            $stmt = $this->db->prepare("
                SELECT
                    id,
                    descricao,
                    quantidade_min,
                    valor,
                    desconto_percentual,
                    ativo,
                    ordem,
                    compra,
                    custo,
                    margem_lucro,
                    tabela_preco_id
                FROM produto_preco
                WHERE company_id = :company_id
                  AND produto_id = :produto_id
                ORDER BY ordem ASC, id ASC
            ");

            $stmt->execute([
                'company_id' => $companyId,
                'produto_id' => $produtoId
            ]);

            return $stmt->fetchAll() ?: [];
        } catch (Exception $e) {
            error_log("Erro ao carregar todos os preços: " . $e->getMessage());
            return [];
        }
    }

    private function carregarPrecosPorQuantidade(int $companyId, int $produtoId): array
    {
        try {
            // Buscar todos os registros que NÃO são tabelas de preço
            // Isso inclui registros com descricao NULL, vazia, ou que não começam com "Tabela:"
            // Também exclui registros que têm tabela_preco_id preenchido (esses são tabelas de preço)
            $stmt = $this->db->prepare("
                SELECT
                    id,
                    descricao,
                    quantidade_min,
                    valor,
                    desconto_percentual,
                    ativo,
                    ordem,
                    compra,
                    custo,
                    margem_lucro
                FROM produto_preco
                WHERE company_id = :company_id
                  AND produto_id = :produto_id
                  AND (
                    (descricao IS NULL OR descricao = '' OR descricao NOT LIKE 'Tabela:%')
                    AND (tabela_preco_id IS NULL OR tabela_preco_id = 0)
                  )
                ORDER BY ordem ASC, quantidade_min ASC
            ");

            $stmt->execute([
                'company_id' => $companyId,
                'produto_id' => $produtoId
            ]);

            $resultados = $stmt->fetchAll() ?: [];

            // Log para debug
            error_log("Preços por quantidade carregados para produto {$produtoId}: " . count($resultados));
            if (count($resultados) > 0) {
                error_log("Dados dos preços: " . json_encode($resultados, JSON_UNESCAPED_UNICODE));
            }

            return $resultados;
        } catch (Exception $e) {
            error_log("Erro ao carregar preços por quantidade: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Carrega tabelas de preço da tabela produto_preco
     * Filtra registros que começam com "Tabela:"
     */
    private function carregarTabelasPreco(int $companyId, int $produtoId): array
    {
        try {
            $colunasProdutoPreco = $this->produtoPrecoColumns();
            $temCompra = in_array('compra', $colunasProdutoPreco, true);
            $temCusto = in_array('custo', $colunasProdutoPreco, true);
            // Verificar tanto tabela_preco_id quanto tabela_preco (retrocompatibilidade)
            $temTabelaPrecoId = in_array('tabela_preco_id', $colunasProdutoPreco, true);
            $temTabelaPreco = in_array('tabela_preco', $colunasProdutoPreco, true);
            $temMargemLucro = in_array('margem_lucro', $colunasProdutoPreco, true);
            $temDescontoPercentual = in_array('desconto_percentual', $colunasProdutoPreco, true);

            $selectCampos = [
                'pp.id',
                'pp.descricao as nome',
                'pp.valor as venda',
            ];

            // Usar margem_lucro se existir, senão desconto_percentual
            if ($temMargemLucro) {
                $selectCampos[] = 'pp.margem_lucro as margem';
            } elseif ($temDescontoPercentual) {
                $selectCampos[] = 'pp.desconto_percentual as margem';
            }

            $selectCampos[] = 'pp.quantidade_min';
            $selectCampos[] = 'pp.ativo';
            $selectCampos[] = 'pp.ordem';

            if ($temCompra) {
                $selectCampos[] = 'pp.compra';
            }

            if ($temCusto) {
                $selectCampos[] = 'pp.custo';
            }

            if ($temTabelaPrecoId) {
                $selectCampos[] = 'pp.tabela_preco_id as tabela_preco';
                $selectCampos[] = 'tp.nome as tabela_preco_nome';
            } elseif ($temTabelaPreco) {
                $selectCampos[] = 'pp.tabela_preco';
                $selectCampos[] = 'tp.nome as tabela_preco_nome';
            }

            if ($temTabelaPrecoId) {
                $joinTabelaPreco = 'LEFT JOIN tabela_preco tp ON tp.id = pp.tabela_preco_id';
                // Buscar registros que têm descrição começando com "Tabela:" OU têm tabela_preco_id preenchido
                $condicaoTabela = "(pp.descricao LIKE 'Tabela:%' OR pp.descricao LIKE 'Tabela: %' OR (pp.tabela_preco_id IS NOT NULL AND pp.tabela_preco_id > 0))";
            } elseif ($temTabelaPreco) {
                $joinTabelaPreco = 'LEFT JOIN tabela_preco tp ON tp.id = pp.tabela_preco';
                $condicaoTabela = "(pp.descricao LIKE 'Tabela:%' OR pp.descricao LIKE 'Tabela: %' OR (pp.tabela_preco IS NOT NULL AND pp.tabela_preco > 0))";
            } else {
                $joinTabelaPreco = '';
                // Buscar apenas por descrição começando com "Tabela:"
                $condicaoTabela = "(pp.descricao LIKE 'Tabela:%' OR pp.descricao LIKE 'Tabela: %')";
            }

            $stmt = $this->db->prepare("
                SELECT
                    " . implode(",\n                    ", $selectCampos) . "
                FROM produto_preco pp
                {$joinTabelaPreco}
                WHERE pp.company_id = :company_id
                  AND pp.produto_id = :produto_id
                  AND {$condicaoTabela}
                ORDER BY pp.ordem ASC, pp.descricao ASC
            ");

            $stmt->execute([
                'company_id' => $companyId,
                'produto_id' => $produtoId
            ]);

            $resultados = $stmt->fetchAll() ?: [];

            // Inicializar array de tabelas
            $tabelas = [];

            // Log para debug - SEMPRE escrever
            $this->logDebug("=== carregarTabelasPreco DEBUG ===");
            $this->logDebug("Produto ID: {$produtoId}, Company ID: {$companyId}");
            $this->logDebug("Query executada. Resultados encontrados: " . count($resultados));
            $this->logDebug("Condição usada: {$condicaoTabela}");
            if (count($resultados) > 0) {
                $this->logDebug("Dados brutos das tabelas: " . json_encode($resultados, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
            } else {
                // Tentar buscar TODOS os registros para debug
                $stmtDebug = $this->db->prepare("
                    SELECT id, descricao, tabela_preco_id, valor, compra, custo, margem_lucro
                    FROM produto_preco
                    WHERE company_id = :company_id AND produto_id = :produto_id
                ");
                $stmtDebug->execute(['company_id' => $companyId, 'produto_id' => $produtoId]);
                $todosRegistros = $stmtDebug->fetchAll() ?: [];
                $this->logDebug("⚠️ Nenhuma tabela encontrada com a condição. Todos os registros de produto_preco para este produto: " . json_encode($todosRegistros, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
            }
            foreach ($resultados as $row) {
                $nomeTabela = ($temTabelaPrecoId || $temTabelaPreco) ? ($row['tabela_preco_nome'] ?? null) : null;
                // Remover prefixo "Tabela:" ou "Tabela: " da descrição
                $nomeDescricao = preg_replace('/^Tabela:\s*/i', '', $row['nome'] ?? '');
                $nomeFinal = trim($nomeTabela ?: $nomeDescricao);

                // Se ainda estiver vazio, usar a descrição original (sem o prefixo)
                if (empty($nomeFinal)) {
                    $nomeFinal = trim(preg_replace('/^Tabela:\s*/i', '', $row['nome'] ?? ''));
                }

                // Se ainda estiver vazio, usar um nome padrão
                if (empty($nomeFinal)) {
                    $nomeFinal = 'Tabela Sem Nome';
                }

                $tabelaData = [
                    'id' => $row['id'],
                    'nome' => $nomeFinal,
                    'tabela_preco_id' => ($temTabelaPrecoId || $temTabelaPreco) ? ($row['tabela_preco'] ?? null) : null,
                    'compra' => $temCompra ? (float) ($row['compra'] ?? 0) : 0,
                    'custo' => $temCusto ? (float) ($row['custo'] ?? 0) : 0,
                    'margem' => $row['margem'] ?? 0,
                    'venda' => $row['venda'],
                    'ativo' => $row['ativo'],
                    'ordem' => $row['ordem']
                ];
                $tabelas[] = $tabelaData;
                $this->logDebug("Tabela processada: " . json_encode($tabelaData, JSON_UNESCAPED_UNICODE));
            }

            $this->logDebug("Total de tabelas retornadas: " . count($tabelas));
            $this->logDebug("===================================");
            return $tabelas;
        } catch (Exception $e) {
            error_log("Erro ao carregar tabelas de preço: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Salva preços por quantidade na tabela produto_preco
     *
     * Compatível com estruturas antigas (sem desconto_percentual)
     * e novas (com margem_lucro ou desconto_percentual).
     */
    private function salvarPrecosPorQuantidade(int $companyId, int $produtoId, array $precos): void
    {
        try {
            // Arquivo de log dedicado para debug de produto_preco
            $logFile = ROOT_PATH . '/storage/logs/produto_preco-' . date('Y-m-d') . '.log';

            // Verificar se a tabela existe
            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'produto_preco'");
            if ($stmtCheck->rowCount() === 0) {
                error_log("Aviso: Tabela produto_preco não existe. Execute a migration: migration_create_produto_preco.sql");
                return;
            }

            // Se não houver preços para adicionar, apenas retorna
            if (empty($precos) || !is_array($precos)) {
                return;
            }

            // Descobrir colunas disponíveis (reutiliza lógica de produtoPrecoColumns)
            $colunasProdutoPreco   = $this->produtoPrecoColumns();
            $temMargemLucro        = in_array('margem_lucro', $colunasProdutoPreco, true);
            $temDescontoPercentual = in_array('desconto_percentual', $colunasProdutoPreco, true);

            // Buscar a ordem atual
            $stmtOrdem = $this->db->prepare("
                SELECT COALESCE(MAX(ordem), -1) as max_ordem
                FROM produto_preco
                WHERE company_id = ? AND produto_id = ?
            ");
            $stmtOrdem->execute([$companyId, $produtoId]);
            $result      = $stmtOrdem->fetch();
            $ordemInicial = ($result['max_ordem'] ?? -1) + 1;

            // Montar colunas e placeholders dinamicamente
            $colunasInsert = [
                'company_id',
                'produto_id',
                'descricao',
                'quantidade_min',
                'valor',
            ];
            $placeholders = ['?', '?', '?', '?', '?'];

            // Se existir margem_lucro, usá-la para preços por quantidade
            if ($temMargemLucro) {
                $colunasInsert[] = 'margem_lucro';
                $placeholders[]  = '?';
            } elseif ($temDescontoPercentual) {
                // fallback para esquemas que usam desconto_percentual
                $colunasInsert[] = 'desconto_percentual';
                $placeholders[]  = '?';
            }

            // Sempre usamos ativo=1, ordem (parâmetro), created_at/updated_at
            $colunasInsert[] = 'ordem';
            $placeholders[]  = '?';

            $sqlInsert = "
                INSERT INTO produto_preco (" . implode(', ', $colunasInsert) . ", ativo, created_at, updated_at)
                VALUES (" . implode(', ', $placeholders) . ", 1, NOW(), NOW())
            ";

            $stmtInsert = $this->db->prepare($sqlInsert);

            // Log básico para debug
            $msg = sprintf(
                "[%s] DEBUG produto_preco::salvarPrecosPorQuantidade - company_id=%d, produto_id=%d, precos=%s\n",
                date('Y-m-d H:i:s'),
                $companyId,
                $produtoId,
                json_encode($precos, JSON_UNESCAPED_UNICODE)
            );
            error_log($msg, 3, $logFile);

            $ordem = $ordemInicial;
            foreach ($precos as $preco) {
                if (empty($preco['descricao']) || $preco['valor'] === '' || $preco['valor'] === null) {
                    continue;
                }

                $descricao     = trim((string) $preco['descricao']);
                $quantidadeMin = (int) ($preco['quantidade_min'] ?? 1);

                // Valor pode vir já como número ou string formatada simples (10.50, 10, 10,50)
                $valorBruto = (string) ($preco['valor'] ?? '0');
                $valorLimpo = str_replace([' ', 'R$', '€', '£'], '', $valorBruto);
                $valorLimpo = str_replace('.', '', $valorLimpo);
                $valorLimpo = str_replace(',', '.', $valorLimpo);
                $valor      = (float) $valorLimpo;

                if ($quantidadeMin <= 0 || $valor <= 0) {
                    continue;
                }

                $valores = [
                    $companyId,
                    $produtoId,
                    $descricao,
                    $quantidadeMin,
                    $valor,
                ];

                // Margem / desconto se a coluna existir
                if ($temMargemLucro || $temDescontoPercentual) {
                    $margemBruta = $preco['desconto_percentual'] ?? $preco['margem'] ?? null;
                    $margemStr   = $margemBruta !== null ? (string) $margemBruta : '0';
                    $margemStr   = str_replace('.', '', $margemStr);
                    $margemStr   = str_replace(',', '.', $margemStr);
                    $margem      = (float) $margemStr;
                    $valores[]   = $margem > 0 ? $margem : 0;
                }

                $valores[] = $ordem++;

                // Log dos valores a serem inseridos
                $msgInsert = sprintf(
                    "[%s] DEBUG produto_preco::salvarPrecosPorQuantidade - INSERT valores=%s\n",
                    date('Y-m-d H:i:s'),
                    json_encode($valores, JSON_UNESCAPED_UNICODE)
                );
                error_log($msgInsert, 3, $logFile);

                $stmtInsert->execute($valores);
            }
        } catch (Exception $e) {
            $msgError = sprintf(
                "[%s] ERRO produto_preco::salvarPrecosPorQuantidade - %s\n",
                date('Y-m-d H:i:s'),
                $e->getMessage()
            );
            error_log($msgError, 3, $logFile);
            // Não lança exceção para não quebrar o fluxo principal
        }
    }

    /**
     * Salva tabelas de preço na tabela produto_preco
     * Estrutura EXATA da tabela informada:
     * id, company_id, produto_id, tabela_preco_id, descricao, quantidade_min, valor,
     * desconto_percentual, margem_lucro, ativo, ordem, created_at, updated_at, compra, custo, tabela_preco
     */
    private function salvarTabelasPreco(int $companyId, int $produtoId, array $tabelas): void
    {
        try {
            // Arquivo de log dedicado para debug de produto_preco
            $logFile = ROOT_PATH . '/storage/logs/produto_preco-' . date('Y-m-d') . '.log';

            // Verificar se a tabela existe
            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'produto_preco'");
            if ($stmtCheck->rowCount() === 0) {
                error_log("Aviso: Tabela produto_preco não existe. Execute a migration: migration_create_produto_preco.sql");
                return;
            }

            if (empty($tabelas) || !is_array($tabelas)) {
                return;
            }

            // Buscar a ordem atual
            $stmtOrdem = $this->db->prepare("
                SELECT COALESCE(MAX(ordem), -1) as max_ordem
                FROM produto_preco
                WHERE company_id = ? AND produto_id = ?
            ");
            $stmtOrdem->execute([$companyId, $produtoId]);
            $result       = $stmtOrdem->fetch();
            $ordemInicial = ($result['max_ordem'] ?? -1) + 1;

            // INSERT alinhado exatamente com a estrutura da tabela
            $sqlInsert = "
                INSERT INTO produto_preco (
                    company_id,
                    produto_id,
                    tabela_preco_id,
                    descricao,
                    quantidade_min,
                    valor,
                    desconto_percentual,
                    margem_lucro,
                    ativo,
                    ordem,
                    created_at,
                    updated_at,
                    compra,
                    custo,
                    tabela_preco
                ) VALUES (
                    ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, NOW(), NOW(), ?, ?, ?
                )
            ";

            // Normalizador simples para valores monetários (ex: "R$ 1,00")
            $normalizarMoney = static function ($valorBruto) {
                $str = (string) ($valorBruto ?? '0');
                $str = str_replace(['R$', '€', '£'], '', $str);
                $str = str_replace(' ', '', $str);
                $str = str_replace('.', '', $str);
                $str = str_replace(',', '.', $str);
                return (float) $str;
            };

            $stmtInsert = $this->db->prepare($sqlInsert);

            // Log de entrada
            $msgInicio = sprintf(
                "[%s] DEBUG produto_preco::salvarTabelasPreco - company_id=%d, produto_id=%d, tabelas=%s\n",
                date('Y-m-d H:i:s'),
                $companyId,
                $produtoId,
                json_encode($tabelas, JSON_UNESCAPED_UNICODE)
            );
            error_log($msgInicio, 3, $logFile);

            $ordem = $ordemInicial;
            foreach ($tabelas as $tabela) {
                if (empty($tabela['nome']) && empty($tabela['tabela_preco_id'])) {
                    continue;
                }

                $nome          = trim((string) ($tabela['nome'] ?? ''));
                $tabelaPrecoId = isset($tabela['tabela_preco_id']) ? (int) $tabela['tabela_preco_id'] : null;
                $compra        = $normalizarMoney($tabela['compra'] ?? 0);
                $custo         = $normalizarMoney($tabela['custo'] ?? 0);
                $venda         = $normalizarMoney($tabela['venda'] ?? 0);

                // Margem pode vir como "1,00" / "1.00" / número
                $margemBruta = $tabela['margem'] ?? 0;
                $margemStr   = (string) $margemBruta;
                $margemStr   = str_replace('.', '', $margemStr);
                $margemStr   = str_replace(',', '.', $margemStr);
                $margem      = (float) $margemStr;

                if ($venda <= 0) {
                    // Sem valor de venda não faz sentido gravar tabela
                    continue;
                }

                $descricao       = 'Tabela: ' . ($nome !== '' ? $nome : ('ID ' . ($tabelaPrecoId ?? '')));
                $quantidadeMin   = 1;
                $descontoPercent = null; // não usamos aqui, deixamos NULL
                $valoresInsert   = [
                    $companyId,
                    $produtoId,
                    $tabelaPrecoId,
                    $descricao,
                    $quantidadeMin,
                    $venda,
                    $descontoPercent,
                    $margem,
                    $ordem,
                    $compra,
                    $custo,
                    // coluna tabela_preco (texto ou id); usamos o ID se existir
                    $tabelaPrecoId ?? $nome,
                ];

                // Log dos valores que serão inseridos
                $msgInsert = sprintf(
                    "[%s] DEBUG produto_preco::salvarTabelasPreco - INSERT valores=%s\n",
                    date('Y-m-d H:i:s'),
                    json_encode($valoresInsert, JSON_UNESCAPED_UNICODE)
                );
                error_log($msgInsert, 3, $logFile);

                try {
                    $stmtInsert->execute($valoresInsert);
                    $lastInsertId = $this->db->lastInsertId();
                    $msgSucesso = sprintf(
                        "[%s] ✓ SUCESSO produto_preco::salvarTabelasPreco - Registro inserido com ID: %s\n",
                        date('Y-m-d H:i:s'),
                        $lastInsertId
                    );
                    error_log($msgSucesso, 3, $logFile);
                } catch (\PDOException $eInsert) {
                    $msgErroInsert = sprintf(
                        "[%s] ✗ ERRO produto_preco::salvarTabelasPreco - Falha no INSERT: %s\n",
                        date('Y-m-d H:i:s'),
                        $eInsert->getMessage()
                    );
                    error_log($msgErroInsert, 3, $logFile);
                    error_log("SQL State: " . $eInsert->getCode() . "\n", 3, $logFile);
                    error_log("Error Info: " . print_r($eInsert->errorInfo ?? [], true) . "\n", 3, $logFile);
                    throw $eInsert;
                }

                $ordem++;
            }

            $msgFim = sprintf(
                "[%s] DEBUG produto_preco::salvarTabelasPreco - FIM - Processadas %d tabela(s)\n",
                date('Y-m-d H:i:s'),
                count($tabelas)
            );
            error_log($msgFim, 3, $logFile);
        } catch (Exception $e) {
            $msgError = sprintf(
                "[%s] ERRO FATAL produto_preco::salvarTabelasPreco - %s\n",
                date('Y-m-d H:i:s'),
                $e->getMessage()
            );
            error_log($msgError, 3, $logFile);
            error_log("Stack trace: " . $e->getTraceAsString() . "\n", 3, $logFile);
        }
    }

    /**
     * Retorna as colunas existentes na tabela produto_preco para evitar erros de referência
     */
    private function produtoPrecoColumns(): array
    {
        static $cache = null;

        if ($cache !== null) {
            return $cache;
        }

        try {
            $stmt = $this->db->query("SHOW COLUMNS FROM produto_preco");
            $colunas = $stmt->fetchAll(\PDO::FETCH_ASSOC);
            $cache = array_values(array_filter(array_map(static function ($coluna) {
                return $coluna['Field'] ?? null;
            }, $colunas)));
        } catch (Exception $e) {
            error_log("Aviso: Não foi possível ler colunas de produto_preco: " . $e->getMessage());
            $cache = [];
        }

        return $cache;
    }

    /**
     * Normaliza o nome da tabela de preço para comparação case-insensitive
     */
    private function normalizarNomeTabela(?string $nome): string
    {
        $nome = trim((string) $nome);
        if ($nome === '') {
            return '';
        }

        return function_exists('mb_strtolower') ? mb_strtolower($nome, 'UTF-8') : strtolower($nome);
    }

    /**
     * Busca todas as empresas
     */
    private function getTodasEmpresas(): array
    {
        try {
            // Verificar se a tabela empresas existe
            $stmt = $this->db->query("SHOW TABLES LIKE 'empresas'");
            if ($stmt->rowCount() === 0) {
                return [];
            }

            $stmt = $this->db->prepare("
                SELECT id, razao_social, nome_fantasia, cnpj
                FROM empresas
                ORDER BY razao_social ASC
            ");
            $stmt->execute();
            return $stmt->fetchAll();
        } catch (Exception $e) {
            error_log("Erro ao buscar empresas: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Busca empresas vinculadas a um produto
     */
    private function getEmpresasVinculadas(int $produtoId): array
    {
        try {
            // Verificar se a tabela empresas_produtos existe
            $stmt = $this->db->query("SHOW TABLES LIKE 'empresas_produtos'");
            if ($stmt->rowCount() === 0) {
                return [];
            }

            $stmt = $this->db->prepare("
                SELECT ep.empresa_id
                FROM empresas_produtos ep
                WHERE ep.produto_id = :produto_id
            ");
            $stmt->execute(['produto_id' => $produtoId]);
            $result = $stmt->fetchAll();

            // Retornar apenas os IDs das empresas
            return array_column($result, 'empresa_id');
        } catch (Exception $e) {
            error_log("Erro ao buscar empresas vinculadas: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Salva empresas vinculadas a um produto
     */
    private function salvarEmpresasVinculadas(int $produtoId, array $empresaIds): void
    {
        try {
            // Verificar se a tabela empresas_produtos existe
            $stmt = $this->db->query("SHOW TABLES LIKE 'empresas_produtos'");
            if ($stmt->rowCount() === 0) {
                return;
            }

            // Remover todas as vinculações existentes
            $stmt = $this->db->prepare("DELETE FROM empresas_produtos WHERE produto_id = :produto_id");
            $stmt->execute(['produto_id' => $produtoId]);

            // Inserir novas vinculações
            if (!empty($empresaIds)) {
                $stmt = $this->db->prepare("INSERT INTO empresas_produtos (empresa_id, produto_id) VALUES (:empresa_id, :produto_id)");
                foreach ($empresaIds as $empresaId) {
                    $empresaId = (int) $empresaId;
                    if ($empresaId > 0) {
                        $stmt->execute([
                            'empresa_id' => $empresaId,
                            'produto_id' => $produtoId
                        ]);
                    }
                }
            }
        } catch (Exception $e) {
            error_log("Erro ao salvar empresas vinculadas: " . $e->getMessage());
        }
    }

    /**
     * Busca posições de um local de estoque (API)
     */
    public function buscarPosicoesEstoque(): void
    {
        try {
            $localEstoqueId = (int) $this->request->get('local_estoque_id');

            if (!$localEstoqueId) {
                $this->response->json([
                    'success' => false,
                    'message' => 'ID do local de estoque não informado',
                    'data' => []
                ]);
                return;
            }

            $companyId = $this->getCompanyId();
            if (!$companyId) {
                $this->response->json([
                    'success' => false,
                    'message' => 'Empresa não identificada',
                    'data' => []
                ]);
                return;
            }

            // Verificar se a tabela existe
            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'local_estoque_posicoes'");
            if ($stmtCheck->rowCount() === 0) {
                $this->response->json([
                    'success' => true,
                    'message' => 'Tabela de posições não existe',
                    'data' => []
                ]);
                return;
            }

            // Buscar posições do local de estoque
            // Verificar se a coluna company_id existe na tabela
            $stmtCheckCol = $this->db->query("SHOW COLUMNS FROM local_estoque_posicoes LIKE 'company_id'");
            $temCompanyId = $stmtCheckCol->rowCount() > 0;

            if ($temCompanyId) {
                $stmt = $this->db->prepare("
                    SELECT id, posicao, ordem
                    FROM local_estoque_posicoes
                    WHERE local_estoque_id = :local_estoque_id
                      AND company_id = :company_id
                    ORDER BY ordem ASC, id ASC
                ");
                $stmt->execute([
                    'local_estoque_id' => $localEstoqueId,
                    'company_id' => $companyId
                ]);
            } else {
                // Se não tem company_id, buscar apenas por local_estoque_id
                $stmt = $this->db->prepare("
                    SELECT id, posicao, ordem
                    FROM local_estoque_posicoes
                    WHERE local_estoque_id = :local_estoque_id
                    ORDER BY ordem ASC, id ASC
                ");
                $stmt->execute([
                    'local_estoque_id' => $localEstoqueId
                ]);
            }

            $posicoes = $stmt->fetchAll() ?: [];

            // Log para debug
            $this->logDebug("=== buscarPosicoesEstoque ===");
            $this->logDebug("Local Estoque ID: {$localEstoqueId}");
            $this->logDebug("Company ID: {$companyId}");
            $this->logDebug("Posições encontradas: " . count($posicoes));
            if (count($posicoes) > 0) {
                $this->logDebug("Dados das posições: " . json_encode($posicoes, JSON_UNESCAPED_UNICODE));
            } else {
                // Verificar se o local de estoque existe
                $stmtCheckLocal = $this->db->prepare("SELECT id, name FROM locais_estoque WHERE id = :id");
                $stmtCheckLocal->execute(['id' => $localEstoqueId]);
                $localExiste = $stmtCheckLocal->fetch();
                $this->logDebug("Local de estoque existe? " . ($localExiste ? 'Sim - ' . ($localExiste['name'] ?? '') : 'Não'));
            }
            $this->logDebug("==============================");

            $this->response->json([
                'success' => true,
                'message' => 'Posições carregadas com sucesso',
                'data' => $posicoes
            ]);
        } catch (Exception $e) {
            error_log("Erro ao buscar posições de estoque: " . $e->getMessage());
            $this->response->json([
                'success' => false,
                'message' => 'Erro ao buscar posições: ' . $e->getMessage(),
                'data' => []
            ]);
        }
    }

    /**
     * Busca extrato de produto (movimentações dos últimos 2 meses)
     */
    public function extratoProduto(): void
    {
        try {
            $companyId = $this->getCompanyId();
            $itemId = (int) $this->request->get('id', 0);

            if ($itemId <= 0) {
                $this->response->json([
                    'success' => false,
                    'message' => 'ID do item inválido'
                ]);
                return;
            }

            // Calcular datas dos últimos 2 meses
            $dataAtual = new \DateTime();
            $mesAtualInicio = clone $dataAtual;
            $mesAtualInicio->modify('first day of this month')->setTime(0, 0, 0);
            $mesAtualFim = clone $dataAtual;
            $mesAtualFim->modify('last day of this month')->setTime(23, 59, 59);

            $mesAnteriorInicio = clone $mesAtualInicio;
            $mesAnteriorInicio->modify('-1 month');
            $mesAnteriorFim = clone $mesAtualInicio;
            $mesAnteriorFim->modify('-1 second');

            // Verificar se as tabelas existem
            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'compra_itens'");
            $temCompraItens = $stmtCheck->rowCount() > 0;

            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'vendas_itens'");
            $temVendasItens = $stmtCheck->rowCount() > 0;

            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'compras'");
            $temCompras = $stmtCheck->rowCount() > 0;

            $stmtCheck = $this->db->query("SHOW TABLES LIKE 'vendas'");
            $temVendas = $stmtCheck->rowCount() > 0;

            // Buscar dados do mês atual
            $mesAtual = $this->buscarDadosMes($itemId, $companyId, $mesAtualInicio, $mesAtualFim, $temCompraItens, $temVendasItens, $temCompras, $temVendas);

            // Buscar dados do mês anterior
            $mesAnterior = $this->buscarDadosMes($itemId, $companyId, $mesAnteriorInicio, $mesAnteriorFim, $temCompraItens, $temVendasItens, $temCompras, $temVendas);

            // Buscar informações do produto
            $stmt = $this->db->prepare("
                SELECT id, name, sku, type
                FROM produtos
                WHERE id = :id AND company_id = :company_id
            ");
            $stmt->execute(['id' => $itemId, 'company_id' => $companyId]);
            $produto = $stmt->fetch();

            if (!$produto) {
                $this->response->json([
                    'success' => false,
                    'message' => 'Produto não encontrado'
                ]);
                return;
            }

            $this->response->json([
                'success' => true,
                'data' => [
                    'produto' => $produto,
                    'mes_atual' => $mesAtual,
                    'mes_anterior' => $mesAnterior,
                    'periodo_atual' => [
                        'inicio' => $mesAtualInicio->format('Y-m-d'),
                        'fim' => $mesAtualFim->format('Y-m-d')
                    ],
                    'periodo_anterior' => [
                        'inicio' => $mesAnteriorInicio->format('Y-m-d'),
                        'fim' => $mesAnteriorFim->format('Y-m-d')
                    ]
                ]
            ]);

        } catch (Exception $e) {
            error_log("Erro ao buscar extrato de produto: " . $e->getMessage());
            $this->response->json([
                'success' => false,
                'message' => 'Erro ao buscar extrato: ' . $e->getMessage()
            ]);
        }
    }

    /**
     * Busca dados de um mês específico
     */
    private function buscarDadosMes(int $itemId, int $companyId, \DateTime $inicio, \DateTime $fim, bool $temCompraItens, bool $temVendasItens, bool $temCompras, bool $temVendas): array
    {
        $dados = [
            'quantidade_comprada' => 0,
            'quantidade_vendida' => 0,
            'custo_medio' => 0,
            'preco_medio' => 0,
            'primeiro_custo' => null,
            'ultimo_custo' => null,
            'primeiro_preco' => null,
            'ultimo_preco' => null,
            'total_comprado' => 0,
            'total_vendido' => 0
        ];

        // Buscar compras
        if ($temCompraItens && $temCompras) {
            try {
                // Verificar se a coluna item_id existe
                $stmtCheck = $this->db->query("SHOW COLUMNS FROM compra_itens LIKE 'item_id'");
                $temItemId = $stmtCheck->rowCount() > 0;

                if ($temItemId) {
                    $sql = "
                        SELECT
                            ci.quantity,
                            ci.unit_price,
                            c.data_compra
                        FROM compra_itens ci
                        INNER JOIN compras c ON ci.compra_id = c.id
                        WHERE ci.item_id = :item_id
                        AND c.company_id = :company_id
                        AND c.data_compra >= :inicio
                        AND c.data_compra <= :fim
                        ORDER BY c.data_compra ASC, c.id ASC
                    ";
                } else {
                    // Tentar com product_id
                    $stmtCheck = $this->db->query("SHOW COLUMNS FROM compra_itens LIKE 'product_id'");
                    if ($stmtCheck->rowCount() > 0) {
                        $sql = "
                            SELECT
                                ci.quantity,
                                ci.unit_price,
                                c.data_compra
                            FROM compra_itens ci
                            INNER JOIN compras c ON ci.compra_id = c.id
                            WHERE ci.product_id = :item_id
                            AND c.company_id = :company_id
                            AND c.data_compra >= :inicio
                            AND c.data_compra <= :fim
                            ORDER BY c.data_compra ASC, c.id ASC
                        ";
                    } else {
                        throw new Exception("Tabela compra_itens não tem item_id nem product_id");
                    }
                }

                $stmt = $this->db->prepare($sql);
                $stmt->execute([
                    'item_id' => $itemId,
                    'company_id' => $companyId,
                    'inicio' => $inicio->format('Y-m-d H:i:s'),
                    'fim' => $fim->format('Y-m-d H:i:s')
                ]);
                $compras = $stmt->fetchAll();

                if (!empty($compras)) {
                    $totalQuantidade = 0;
                    $totalValor = 0;
                    $primeiroCusto = null;
                    $ultimoCusto = null;

                    foreach ($compras as $compra) {
                        $qtd = (float) ($compra['quantity'] ?? 0);
                        $preco = (float) ($compra['unit_price'] ?? 0);

                        if ($qtd > 0 && $preco > 0) {
                            $totalQuantidade += $qtd;
                            $totalValor += ($qtd * $preco);

                            if ($primeiroCusto === null) {
                                $primeiroCusto = $preco;
                            }
                            $ultimoCusto = $preco;
                        }
                    }

                    $dados['quantidade_comprada'] = $totalQuantidade;
                    $dados['total_comprado'] = $totalValor;
                    $dados['custo_medio'] = $totalQuantidade > 0 ? ($totalValor / $totalQuantidade) : 0;
                    $dados['primeiro_custo'] = $primeiroCusto;
                    $dados['ultimo_custo'] = $ultimoCusto;
                }
            } catch (Exception $e) {
                error_log("Erro ao buscar compras no extrato: " . $e->getMessage());
            }
        }

        // Buscar vendas
        if ($temVendasItens && $temVendas) {
            try {
                $sql = "
                    SELECT
                        vi.quantity,
                        vi.unit_price,
                        v.created_at as data_venda
                    FROM vendas_itens vi
                    INNER JOIN vendas v ON vi.venda_id = v.id
                    WHERE vi.product_id = :item_id
                    AND vi.company_id = :company_id
                    AND v.created_at >= :inicio
                    AND v.created_at <= :fim
                    ORDER BY v.created_at ASC, v.id ASC
                ";

                $stmt = $this->db->prepare($sql);
                $stmt->execute([
                    'item_id' => $itemId,
                    'company_id' => $companyId,
                    'inicio' => $inicio->format('Y-m-d H:i:s'),
                    'fim' => $fim->format('Y-m-d H:i:s')
                ]);
                $vendas = $stmt->fetchAll();

                if (!empty($vendas)) {
                    $totalQuantidade = 0;
                    $totalValor = 0;
                    $primeiroPreco = null;
                    $ultimoPreco = null;

                    foreach ($vendas as $venda) {
                        $qtd = (float) ($venda['quantity'] ?? 0);
                        $preco = (float) ($venda['unit_price'] ?? 0);

                        if ($qtd > 0 && $preco > 0) {
                            $totalQuantidade += $qtd;
                            $totalValor += ($qtd * $preco);

                            if ($primeiroPreco === null) {
                                $primeiroPreco = $preco;
                            }
                            $ultimoPreco = $preco;
                        }
                    }

                    $dados['quantidade_vendida'] = $totalQuantidade;
                    $dados['total_vendido'] = $totalValor;
                    $dados['preco_medio'] = $totalQuantidade > 0 ? ($totalValor / $totalQuantidade) : 0;
                    $dados['primeiro_preco'] = $primeiroPreco;
                    $dados['ultimo_preco'] = $ultimoPreco;
                }
            } catch (Exception $e) {
                error_log("Erro ao buscar vendas no extrato: " . $e->getMessage());
            }
        }

        return $dados;
    }
}
