<?php

namespace App\Controllers;

use App\Core\Database;
use App\Core\View;
use App\Repositories\ProdutosRepository;

class ProdutosController
{
    private function repo(): ProdutosRepository
    {
        return new ProdutosRepository(Database::conectar());
    }

    private function config(): array
    {
        $path = dirname(__DIR__, 2) . '/config/database.php';
        return file_exists($path) ? (require $path) : [];
    }

    private function guardaConexao(): void
    {
        if (!Database::estaConfigurado()) { header('Location: /configurar'); exit; }
    }

    // ── Filtros SEM consulta ao banco — só session + GET ─────────────────────
    private function filtrosSemDB(): array
    {
        $hoje    = date('Y-m-d');
        $sessAno = isset($_SESSION['filtro_ano']) ? (int)$_SESSION['filtro_ano'] : null;
        $sessMes = isset($_SESSION['filtro_mes']) && (int)$_SESSION['filtro_mes'] > 0
                   ? (int)$_SESSION['filtro_mes'] : null;

        if ($sessAno && $sessMes) {
            $defaultIni = sprintf('%04d-%02d-01', $sessAno, $sessMes);
            $fimDoMes   = date('Y-m-t', strtotime($defaultIni));
            $defaultFim = min($fimDoMes, $hoje);
            if ($defaultIni > $hoje) { $defaultIni = $defaultFim = $hoje; }
        } elseif ($sessAno) {
            $defaultIni = sprintf('%04d-01-01', $sessAno);
            $defaultFim = min(sprintf('%04d-12-31', $sessAno), $hoje);
        } else {
            $defaultIni = date('Y-01-01');
            $defaultFim = $hoje;
        }

        $dataIni = $_GET['data_ini'] ?? $defaultIni;
        $dataFim = $_GET['data_fim'] ?? $defaultFim;
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataIni)) $dataIni = $defaultIni;
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataFim))  $dataFim = $defaultFim;
        if ($dataFim < $dataIni) $dataFim = $dataIni;

        return compact('dataIni', 'dataFim');
    }

    private function parseDatas(): array
    {
        $hoje    = date('Y-m-d');
        $default = date('Y-01-01');
        $dataIni = $_GET['data_ini'] ?? $default;
        $dataFim = $_GET['data_fim'] ?? $hoje;
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataIni)) $dataIni = $default;
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $dataFim))  $dataFim = $hoje;
        if ($dataFim < $dataIni) $dataFim = $dataIni;
        return [$dataIni, $dataFim];
    }

    // ════════════════════════════════════════════════════════════════════════
    //  PÁGINAS — shell instantâneo, sem queries no render
    // ════════════════════════════════════════════════════════════════════════

    public function curvaAbc(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();
        $actionUrl = '/produtos/curva-abc';

        View::render('produtos/curva-abc', [
            'titulo'   => 'Curva ABC — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'actionUrl'=> $actionUrl,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    public function semMovimento(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();
        $actionUrl = '/produtos/sem-movimento';
        $diasSemVenda = isset($_GET['dias']) && ctype_digit($_GET['dias']) ? (int)$_GET['dias'] : 90;

        View::render('produtos/sem-movimento', [
            'titulo'      => 'Produtos Sem Movimento — Premium Express Gestão',
            'config'      => $config,
            'conexao'     => ['success' => true, 'mensagem' => ''],
            'segmento'    => \App\Core\Lojas::resolverSegmento($config),
            'filtros'     => $filtros,
            'actionUrl'   => $actionUrl,
            'diasSemVenda'=> $diasSemVenda,
            'erros'       => [],
            'ano'         => date('Y'),
        ]);
    }

    public function precos(): void
    {
        $this->guardaConexao();
        $config  = $this->config();
        $filtros = $this->filtrosSemDB();
        $actionUrl = '/produtos/precos';
        $busca = trim($_GET['busca'] ?? '');

        View::render('produtos/precos', [
            'titulo'   => 'Histórico de Preços — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $filtros,
            'actionUrl'=> $actionUrl,
            'busca'    => $busca,
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    public function catalogo(): void
    {
        $this->guardaConexao();
        $config = $this->config();
        View::render('produtos/catalogo', [
            'titulo'   => 'Catálogo de Produtos — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $this->filtrosSemDB(),
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    private function renderProdutos(string $viewName, string $titulo): void
    {
        $this->guardaConexao();
        $config = $this->config();
        View::render($viewName, [
            'titulo'   => $titulo . ' — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'filtros'  => $this->filtrosSemDB(),
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    // GET /produtos/mais-vendidos — Top por Faturamento
    public function maisVendidos(): void   { $this->renderProdutos('produtos/mais-vendidos',   'Mais Vendidos'); }
    // GET /produtos/top-quantidade — Top por Quantidade vendida
    public function topQuantidade(): void  { $this->renderProdutos('produtos/top-quantidade',  'Top por Quantidade'); }
    // GET /produtos/margem-negativa — Produtos vendendo abaixo do custo
    public function margemNegativa(): void { $this->renderProdutos('produtos/margem-negativa', 'Margem Negativa'); }

    // Compat: /produtos/ranking continua funcionando
    public function ranking(): void { $this->renderProdutos('produtos/mais-vendidos', 'Mais Vendidos'); }

    /** GET /api/produtos/top-qtd?data_ini&data_fim&limite */
    public function topQtdApi(): void
    {
        header('Content-Type: application/json; charset=utf-8');
        [$ini, $fim] = $this->parseDatas();
        $limite = max(5, min(100, (int)($_GET['limite'] ?? 20)));
        try { echo json_encode(['ok'=>true,'rows'=>$this->repo()->topPorQuantidade($ini,$fim,$limite)]); }
        catch (\Throwable $e) { http_response_code(500); echo json_encode(['ok'=>false,'erro'=>$e->getMessage()]); }
    }

    /** GET /api/produtos/top-fat?data_ini&data_fim&limite */
    public function topFatApi(): void
    {
        header('Content-Type: application/json; charset=utf-8');
        [$ini, $fim] = $this->parseDatas();
        $limite = max(5, min(100, (int)($_GET['limite'] ?? 20)));
        try { echo json_encode(['ok'=>true,'rows'=>$this->repo()->topPorFaturamento($ini,$fim,$limite)]); }
        catch (\Throwable $e) { http_response_code(500); echo json_encode(['ok'=>false,'erro'=>$e->getMessage()]); }
    }

    /** GET /api/produtos/margem-negativa?data_ini&data_fim&limite */
    public function margemNegativaApi(): void
    {
        header('Content-Type: application/json; charset=utf-8');
        [$ini, $fim] = $this->parseDatas();
        $limite = max(5, min(200, (int)($_GET['limite'] ?? 30)));
        try {
            $res = $this->repo()->margemNegativa($ini, $fim, $limite);
            echo json_encode(['ok'=>true, 'sem_custo'=>$res['sem_custo'] ?? false, 'rows'=>$res['rows'] ?? []]);
        } catch (\Throwable $e) { http_response_code(500); echo json_encode(['ok'=>false,'erro'=>$e->getMessage()]); }
    }

    // GET /produtos/saude — Saúde do Cadastro + Produtos com Prejuízo
    public function saude(): void
    {
        $this->guardaConexao();
        $config = $this->config();
        View::render('produtos/saude', [
            'titulo'   => 'Saúde do Cadastro — Premium Express Gestão',
            'config'   => $config,
            'conexao'  => ['success' => true, 'mensagem' => ''],
            'segmento' => \App\Core\Lojas::resolverSegmento($config),
            'erros'    => [],
            'ano'      => date('Y'),
        ]);
    }

    /** GET /api/produtos/saude-kpis */
    public function saudeKpisApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            echo json_encode(['kpis' => $this->repo()->saudeKpis()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/produtos/saude-lista?tipo= */
    public function saudeListaApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $tipo = preg_replace('/[^a-z_]/', '', strtolower($_GET['tipo'] ?? 'sem_custo'));
            echo json_encode(['linhas' => $this->repo()->saudeLista($tipo)], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    // ════════════════════════════════════════════════════════════════════════
    //  APIs JSON — dados carregados pelo browser após o shell aparecer
    // ════════════════════════════════════════════════════════════════════════

    /** GET /api/produtos/kpis?data_ini=&data_fim= */
    public function kpisApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo = $this->repo();
            [$dataIni, $dataFim] = $this->parseDatas();
            $kpis = $repo->kpis($dataIni, $dataFim);
            echo json_encode(['kpis' => $kpis], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/produtos/curva-abc?data_ini=&data_fim= */
    public function curvaAbcApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo = $this->repo();
            [$dataIni, $dataFim] = $this->parseDatas();
            // Analisa TODOS os produtos vendidos: assim os % e classes A/B/C são
            // calculados sobre o faturamento TOTAL real (não sobre um top-N truncado).
            $linhas = $repo->curvaAbc($dataIni, $dataFim, 20000);
            echo json_encode(['linhas' => $linhas], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/produtos/sem-movimento?dias=90 */
    public function semMovimentoApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo = $this->repo();
            $dias = isset($_GET['dias']) && ctype_digit($_GET['dias']) ? (int)$_GET['dias'] : 90;
            $ultima = $repo->ultimaData();
            $linhas = $repo->semMovimento($ultima, $dias);
            echo json_encode(['linhas' => $linhas, 'dias' => $dias], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/produtos/precos?busca= */
    public function precosApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $repo  = $this->repo();
            $busca = trim($_GET['busca'] ?? '');
            $linhas = $busca ? $repo->historicoPrecos($busca) : [];
            echo json_encode(['linhas' => $linhas], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/produtos/catalogo-kpis */
    public function catalogoKpisApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $kpis = $this->repo()->catalogoKpis();
            echo json_encode(['kpis' => $kpis], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/produtos/marcas */
    public function marcasApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            echo json_encode(['marcas' => $this->repo()->marcas()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/produtos/catalogo?pagina=1&busca=&marca=&foto=1 */
    public function catalogoApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $pagina = max(1, (int)($_GET['pagina'] ?? 1));
            $busca  = trim($_GET['busca'] ?? '');
            $marca  = trim($_GET['marca'] ?? '');
            $foto   = ($_GET['foto'] ?? '0') === '1';
            $result = $this->repo()->catalogo($pagina, 24, $busca, $marca, $foto);
            echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/produtos/foto/{cod_item} */
    public function fotoApi(): void
    {
        $this->guardaConexao();
        $codItem = trim($_GET['cod'] ?? '');
        if ($codItem === '') { http_response_code(404); exit; }

        try {
            $blob = $this->repo()->fotoProduto($codItem);
            if ($blob === null) { http_response_code(404); exit; }

            // Detecta formato pela assinatura dos bytes
            $mime = 'image/jpeg';
            if (strlen($blob) > 2) {
                $sig = substr($blob, 0, 4);
                if (substr($sig, 0, 2) === 'BM') {
                    // BMP → converte para PNG via GD
                    $img = @imagecreatefromstring($blob);
                    if ($img) {
                        ob_start();
                        imagepng($img);
                        $blob = ob_get_clean();
                        imagedestroy($img);
                        $mime = 'image/png';
                    }
                } elseif (substr($sig, 0, 4) === "\x89PNG") {
                    $mime = 'image/png';
                } elseif (substr($sig, 0, 4) === 'GIF8') {
                    $mime = 'image/gif';
                }
            }

            header('Content-Type: ' . $mime);
            header('Cache-Control: public, max-age=86400');
            header('Content-Length: ' . strlen($blob));
            echo $blob;
        } catch (\Throwable $e) {
            http_response_code(500);
        }
        exit;
    }

    /** GET /api/produtos/detalhe?cod= */
    public function detalheApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        $codItem = trim($_GET['cod'] ?? '');
        if ($codItem === '') {
            http_response_code(400);
            echo json_encode(['erro' => 'Codigo nao informado']);
            exit;
        }
        // Rejeita URLs de QR Code e qualquer valor que nao seja codigo de produto/barras valido
        if (str_contains($codItem, '://') || str_contains($codItem, ' ') || strlen($codItem) > 60) {
            http_response_code(404);
            echo json_encode(['erro' => 'Produto nao encontrado']);
            exit;
        }
        try {
            $repo = $this->repo();

            // Se parecer código de barras (só dígitos, 8+ caracteres), busca na tabela BARRAS primeiro
            if (preg_match('/^\d{8,}$/', $codItem)) {
                $barras = $repo->buscarPorCodBarras($codItem);
                if (!empty($barras['COD_ITEM'])) {
                    $codItem = $barras['COD_ITEM'];
                } elseif (strlen($codItem) > 11) {
                    // Codigo de barras longo nao encontrado na tabela BARRAS
                    // Nao passa para produtoDetalhe (causaria -303 overflow em COD_ITEM numerico)
                    http_response_code(404);
                    echo json_encode(['erro' => 'Produto nao encontrado']);
                    exit;
                }
            }

            $data = $repo->produtoDetalhe($codItem);
            if (!$data) {
                http_response_code(404);
                echo json_encode(['erro' => 'Produto não encontrado']);
                exit;
            }
            echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** POST /api/produtos/atualizar-preco  body: cod=&empresa=&preco= */
    public function atualizarPrecoApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $codItem    = trim($_POST['cod']     ?? '');
            $codEmpresa = (int)($_POST['empresa'] ?? 0);
            $novoPreco  = (float)str_replace(',', '.', $_POST['preco'] ?? '');

            if ($codItem === '' || $codEmpresa <= 0 || $novoPreco <= 0) {
                http_response_code(400);
                echo json_encode(['erro' => 'Parâmetros inválidos']);
                exit;
            }

            if (!$this->temPermissao('alterar_preco')) {
                http_response_code(403);
                echo json_encode(['erro' => 'Sem permissão para alterar preços']); exit;
            }
            $ok = $this->repo()->atualizarPreco($codItem, $codEmpresa, $novoPreco);
            if ($ok) {
                \App\Controllers\LeitorController::registrarAudit(
                    'atualizar_preco_venda',
                    $codItem,
                    ['preco_venda' => $novoPreco],
                    $codEmpresa
                );
            }
            echo json_encode(['ok' => $ok], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** GET /api/produtos/buscar-barras?cod= */
    public function buscarBarrasApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        $cod = trim($_GET['cod'] ?? '');
        if ($cod === '') {
            http_response_code(400);
            echo json_encode(['erro' => 'Código não informado']);
            exit;
        }
        try {
            $r = $this->repo()->buscarPorCodBarras($cod);
            echo json_encode($r ?: ['nao_encontrado' => true], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable) {
            // Overflow numerico ou outro erro de banco = produto nao encontrado
            echo json_encode(['nao_encontrado' => true], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** POST /api/produtos/atualizar-foto  multipart: cod + foto (file) ou foto_base64 */
    public function atualizarFotoApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        try {
            $codItem = trim($_POST['cod'] ?? '');
            if ($codItem === '') {
                http_response_code(400);
                echo json_encode(['erro' => 'Código não informado']);
                exit;
            }

            $blob = null;

            // Opção 1: upload de arquivo
            if (!empty($_FILES['foto']['tmp_name'])) {
                $blob = file_get_contents($_FILES['foto']['tmp_name']);
            }
            // Opção 2: base64 da câmera (data:image/jpeg;base64,...)
            elseif (!empty($_POST['foto_base64'])) {
                $b64 = $_POST['foto_base64'];
                if (str_contains($b64, ',')) {
                    $b64 = substr($b64, strpos($b64, ',') + 1);
                }
                $blob = base64_decode($b64);
            }

            if (!$blob) {
                http_response_code(400);
                echo json_encode(['erro' => 'Nenhuma imagem recebida']);
                exit;
            }

            // Converte para JPEG se necessário (GD)
            if (substr($blob, 0, 2) !== "\xFF\xD8") {
                $img = @imagecreatefromstring($blob);
                if ($img) {
                    ob_start();
                    imagejpeg($img, null, 90);
                    $blob = ob_get_clean();
                    imagedestroy($img);
                }
            }

            $ok = $this->repo()->atualizarFoto($codItem, $blob);
            echo json_encode(['ok' => $ok], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    private function temPermissao(string $perm): bool
    {
        $perms = $_SESSION['leitor_perms'] ?? [];
        return in_array($perm, $perms, true);
    }

    /** POST /api/produtos/ajustar-estoque  body: cod, empresa, qtd, tipo(ajuste|entrada|saida) */
    public function ajustarEstoqueApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        if (!$this->temPermissao('alterar_estoque')) {
            http_response_code(403);
            echo json_encode(['erro' => 'Sem permissão para ajustar estoque']); exit;
        }
        try {
            $cod     = trim($_POST['cod']     ?? '');
            $empresa = (int)($_POST['empresa'] ?? 0);
            $qtdRaw  = str_replace(',', '.', trim($_POST['qtd'] ?? ''));
            $qtd     = (float)$qtdRaw;
            $tipo    = trim($_POST['tipo']    ?? 'ajuste');
            if ($cod === '' || $empresa === 0 || !in_array($tipo, ['ajuste','entrada','saida'])) {
                http_response_code(400);
                echo json_encode(['erro' => 'Parâmetros inválidos']); exit;
            }
            $result = $this->repo()->ajustarEstoque($cod, $empresa, $qtd, $tipo);
            if (!empty($result['ok'])) {
                \App\Controllers\LeitorController::registrarAudit(
                    'ajuste_estoque',
                    $cod,
                    ['tipo' => $tipo, 'qtd' => $qtd, 'qtd_nova' => $result['qtd_nova'] ?? null],
                    $empresa
                );
            }
            echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** POST /api/produtos/atualizar-campos  body: cod, ncm, estoq_minimo, estoque_maximo, peso, qtd_embalagem */
    public function atualizarCamposApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        if (!$this->temPermissao('alterar_dados')) {
            http_response_code(403);
            echo json_encode(['erro' => 'Sem permissão para editar dados do produto']); exit;
        }
        try {
            $cod = trim($_POST['cod'] ?? '');
            if ($cod === '') { http_response_code(400); echo json_encode(['erro' => 'Código não informado']); exit; }
            $campos = [];
            foreach (['DESCRICAO','APELIDO','NCM','ESTOQ_MINIMO','ESTOQUE_MAXIMO','PESO','QTD_EMBALAGEM','COD_UNIDADE'] as $f) {
                $key = strtolower($f);
                if (isset($_POST[$key])) {
                    $val = trim($_POST[$key]);
                    // Descrição/Apelido não podem ser apagados (campos de nome no ERP) — ignora se vazios
                    if (in_array($f,['DESCRICAO','APELIDO'],true) && $val === '') continue;
                    $campos[$f] = $val === '' ? null : (in_array($f,['NCM','COD_UNIDADE','DESCRICAO','APELIDO']) ? $val : (float)str_replace(',','.',$val));
                }
            }
            $ok = $this->repo()->atualizarCamposProduto($cod, $campos);
            if ($ok) {
                \App\Controllers\LeitorController::registrarAudit(
                    'atualizar_campos',
                    $cod,
                    $campos
                );
            }
            echo json_encode(['ok' => $ok], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }

    /** POST /api/produtos/atualizar-preco-atacado  body: cod, empresa, preco */
    public function atualizarPrecoAtacadoApi(): void
    {
        $this->guardaConexao();
        header('Content-Type: application/json; charset=utf-8');
        if (!$this->temPermissao('alterar_preco')) {
            http_response_code(403);
            echo json_encode(['erro' => 'Sem permissão para alterar preços']); exit;
        }
        try {
            $cod     = trim($_POST['cod']     ?? '');
            $empresa = (int)($_POST['empresa'] ?? 0);
            $preco   = (float)str_replace(',', '.', trim($_POST['preco'] ?? ''));
            if ($cod === '' || $empresa === 0 || $preco <= 0) {
                http_response_code(400); echo json_encode(['erro' => 'Parâmetros inválidos']); exit;
            }
            $ok = $this->repo()->atualizarPrecoAtacado($cod, $empresa, $preco);
            if ($ok) {
                \App\Controllers\LeitorController::registrarAudit(
                    'atualizar_preco_atacado',
                    $cod,
                    ['preco_atacado' => $preco],
                    $empresa
                );
            }
            echo json_encode(['ok' => $ok], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        }
        exit;
    }
}
