<?php
namespace App\Controllers;

/**
 * Módulo de Inventário do Leitor Fire
 * Gerencia sessões de contagem de estoque via scanner de código de barras.
 * Dados armazenados em JSON local (não altera o banco durante a contagem).
 */
class LeitorInventarioController
{
    private static function dir(): string
    {
        $dir = dirname(__DIR__, 2) . '/storage/inventario';
        if (!is_dir($dir)) @mkdir($dir, 0775, true);
        return $dir;
    }

    // ── Sessão ativa ─────────────────────────────────────────────────────────

    private static function arquivoAtiva(int $empresa): string
    {
        return self::dir() . "/ativa_{$empresa}.json";
    }

    private static function lerSessaoAtiva(int $empresa): ?array
    {
        $path = self::arquivoAtiva($empresa);
        if (!file_exists($path)) return null;
        $data = json_decode(file_get_contents($path), true);
        if (!$data || ($data['status'] ?? '') !== 'aberta') return null;
        // Verifica se o arquivo da sessão ainda existe
        $sessPath = self::dir() . '/' . ($data['arquivo'] ?? '');
        if (!file_exists($sessPath)) { @unlink($path); return null; }
        return json_decode(file_get_contents($sessPath), true);
    }

    private static function salvarSessao(array $sessao): void
    {
        $empresa  = (int)($sessao['empresa'] ?? 0);
        $arquivo  = $sessao['arquivo'];
        $sessPath = self::dir() . '/' . $arquivo;
        file_put_contents($sessPath, json_encode($sessao, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), LOCK_EX);
        // Atualiza ponteiro de sessão ativa
        file_put_contents(self::arquivoAtiva($empresa), json_encode([
            'status'  => $sessao['status'],
            'arquivo' => $arquivo,
            'id'      => $sessao['id'],
        ]), LOCK_EX);
    }

    private static function listarSessoes(int $empresa): array
    {
        $dir = self::dir();
        $files = glob("{$dir}/sess_{$empresa}_*.json") ?: [];
        $sessoes = [];
        foreach (array_reverse($files) as $f) {
            $s = json_decode(file_get_contents($f), true);
            if ($s) $sessoes[] = [
                'id'          => $s['id'],
                'data_inicio' => $s['data_inicio'],
                'data_fim'    => $s['data_fim'] ?? null,
                'status'      => $s['status'],
                'operador'    => $s['operador'],
                'total_itens' => count($s['itens'] ?? []),
                'divergencias'=> count(array_filter($s['itens'] ?? [], fn($i) => ($i['qtd_contada'] ?? -1) !== ($i['qtd_sistema'] ?? -2))),
                'arquivo'     => basename($f),
            ];
            if (count($sessoes) >= 20) break;
        }
        return $sessoes;
    }

    // ── GET /api/leitor/inventario/sessao ─────────────────────────────────────
    // GET: retorna sessão ativa (ou null) + lista de sessões recentes
    // POST action=nova: cria nova sessão
    // POST action=retomar: retoma sessão ativa

    public function sessaoApi(): void
    {
        header('Content-Type: application/json; charset=utf-8');
        if (empty($_SESSION['leitor_ok'])) { http_response_code(401); echo json_encode(['erro' => 'Nao autenticado']); exit; }
        if (!in_array('inventario', $_SESSION['leitor_perms'] ?? [], true)) { http_response_code(403); echo json_encode(['erro' => 'Sem permissao para inventario']); exit; }

        $empresa  = (int)($_SESSION['leitor_empresa'] ?? 0);
        $operador = $_SESSION['leitor_usuario'] ?? 'SEM_USUARIO';

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $acao = $_POST['acao'] ?? 'nova';

            if ($acao === 'nova') {
                // Encerra sessão ativa se houver (sem aplicar ajustes)
                $ativa = self::lerSessaoAtiva($empresa);
                if ($ativa) {
                    $ativa['status']   = 'cancelada';
                    $ativa['data_fim'] = date('Y-m-d H:i:s');
                    self::salvarSessao($ativa);
                }
                $ts      = date('YmdHis');
                $id      = "INV-{$empresa}-{$ts}";
                $arquivo = "sess_{$empresa}_{$ts}.json";
                $sessao  = [
                    'id'          => $id,
                    'arquivo'     => $arquivo,
                    'empresa'     => $empresa,
                    'operador'    => $operador,
                    'data_inicio' => date('Y-m-d H:i:s'),
                    'data_fim'    => null,
                    'status'      => 'aberta',
                    'itens'       => [],
                ];
                self::salvarSessao($sessao);
                echo json_encode(['sessao' => $sessao]);
                exit;
            }
        }

        // GET — retorna sessão ativa e lista de sessões
        $ativa   = self::lerSessaoAtiva($empresa);
        $sessoes = self::listarSessoes($empresa);
        echo json_encode(['ativa' => $ativa, 'sessoes' => $sessoes], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        exit;
    }

    // ── POST /api/leitor/inventario/lancar ────────────────────────────────────
    // Registra/atualiza contagem de um produto na sessão ativa

    public function lancarApi(): void
    {
        header('Content-Type: application/json; charset=utf-8');
        if (empty($_SESSION['leitor_ok'])) { http_response_code(401); echo json_encode(['erro' => 'Nao autenticado']); exit; }
        if (!in_array('inventario', $_SESSION['leitor_perms'] ?? [], true)) { http_response_code(403); echo json_encode(['erro' => 'Sem permissao']); exit; }

        $empresa = (int)($_SESSION['leitor_empresa'] ?? 0);
        $sessao  = self::lerSessaoAtiva($empresa);
        if (!$sessao) { http_response_code(400); echo json_encode(['erro' => 'Nenhuma sessao de inventario ativa. Inicie uma nova.']); exit; }

        $codItem   = trim($_POST['cod_item'] ?? '');
        $qtdStr    = trim($_POST['qtd'] ?? '');
        $modo      = $_POST['modo'] ?? 'substituir'; // substituir | somar

        if ($codItem === '' || $qtdStr === '') { http_response_code(400); echo json_encode(['erro' => 'Codigo e quantidade sao obrigatorios']); exit; }
        if (!is_numeric($qtdStr)) { http_response_code(400); echo json_encode(['erro' => 'Quantidade invalida']); exit; }
        $qtd = (float)$qtdStr;

        session_write_close();

        // Busca produto no banco
        $produto = null;
        try {
            $pdo = \App\Core\Database::conectar();
            $st = $pdo->prepare(
                "SELECT FIRST 1
                    TRIM(i.COD_ITEM)                AS COD_ITEM,
                    TRIM(i.DESCRICAO)               AS DESCRICAO,
                    TRIM(COALESCE(i.UNIDADE,'UN'))  AS UNIDADE,
                    COALESCE(ie.QTD, 0)             AS QTD_SISTEMA
                 FROM ITENS i
                 LEFT JOIN ITENS_ESTOQUE ie ON ie.COD_ITEM = i.COD_ITEM
                                           AND ie.COD_EMPRESA = ?
                 WHERE i.COD_ITEM = ?"
            );
            $st->execute([$empresa, $codItem]);
            $produto = $st->fetch(\PDO::FETCH_ASSOC);

            // Tenta por código de barras se não achou — usa o MESMO resolvedor do scanner
            // (match exato do EAN completo + variações; nunca chuta produto ambíguo).
            if (!$produto) {
                $barras = (new \App\Repositories\ProdutosRepository($pdo))->buscarPorCodBarras($codItem);
                if (!empty($barras['COD_ITEM'])) {
                    $st->execute([$empresa, $barras['COD_ITEM']]);
                    $produto = $st->fetch(\PDO::FETCH_ASSOC);
                }
            }
        } catch (\Throwable $e) {
            http_response_code(500);
            echo json_encode(['erro' => $e->getMessage()]);
            exit;
        }

        if (!$produto) { http_response_code(404); echo json_encode(['erro' => 'Produto nao encontrado']); exit; }

        // Atualiza ou insere item na sessão
        $codReal = $produto['COD_ITEM'];
        $idx = null;
        foreach ($sessao['itens'] as $k => $it) {
            if ($it['cod_item'] === $codReal) { $idx = $k; break; }
        }

        $qtdFinal = $qtd;
        if ($idx !== null && $modo === 'somar') {
            $qtdFinal = ($sessao['itens'][$idx]['qtd_contada'] ?? 0) + $qtd;
        }

        $item = [
            'cod_item'    => $codReal,
            'descricao'   => $produto['DESCRICAO'],
            'unidade'     => $produto['UNIDADE'],
            'qtd_sistema' => (float)$produto['QTD_SISTEMA'],
            'qtd_contada' => $qtdFinal,
            'divergencia' => $qtdFinal - (float)$produto['QTD_SISTEMA'],
            'ts'          => date('Y-m-d H:i:s'),
        ];

        if ($idx !== null) {
            $sessao['itens'][$idx] = $item;
        } else {
            $sessao['itens'][] = $item;
        }

        self::salvarSessao($sessao);
        echo json_encode(['ok' => true, 'item' => $item, 'total' => count($sessao['itens'])], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        exit;
    }

    // ── GET /api/leitor/inventario/resumo ─────────────────────────────────────

    public function resumoApi(): void
    {
        header('Content-Type: application/json; charset=utf-8');
        if (empty($_SESSION['leitor_ok'])) { http_response_code(401); echo json_encode(['erro' => 'Nao autenticado']); exit; }
        if (!in_array('inventario', $_SESSION['leitor_perms'] ?? [], true)) { http_response_code(403); echo json_encode(['erro' => 'Sem permissao']); exit; }

        $empresa = (int)($_SESSION['leitor_empresa'] ?? 0);
        $sessao  = self::lerSessaoAtiva($empresa);
        if (!$sessao) { echo json_encode(['sessao' => null]); exit; }

        $itens = $sessao['itens'] ?? [];
        $divs  = array_filter($itens, fn($i) => abs($i['divergencia'] ?? 0) > 0.001);

        echo json_encode([
            'sessao'      => [
                'id'          => $sessao['id'],
                'data_inicio' => $sessao['data_inicio'],
                'operador'    => $sessao['operador'],
                'status'      => $sessao['status'],
            ],
            'itens'       => array_values(array_reverse($itens)),
            'total_itens' => count($itens),
            'divergencias'=> count($divs),
        ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        exit;
    }

    // ── POST /api/leitor/inventario/remover ───────────────────────────────────

    public function removerApi(): void
    {
        header('Content-Type: application/json; charset=utf-8');
        if (empty($_SESSION['leitor_ok'])) { http_response_code(401); echo json_encode(['erro' => 'Nao autenticado']); exit; }
        if (!in_array('inventario', $_SESSION['leitor_perms'] ?? [], true)) { http_response_code(403); echo json_encode(['erro' => 'Sem permissao']); exit; }

        $empresa = (int)($_SESSION['leitor_empresa'] ?? 0);
        $sessao  = self::lerSessaoAtiva($empresa);
        if (!$sessao) { http_response_code(400); echo json_encode(['erro' => 'Sem sessao ativa']); exit; }

        $codItem = trim($_POST['cod_item'] ?? '');
        $sessao['itens'] = array_values(array_filter($sessao['itens'], fn($i) => $i['cod_item'] !== $codItem));
        self::salvarSessao($sessao);
        echo json_encode(['ok' => true, 'total' => count($sessao['itens'])]);
        exit;
    }

    // ── POST /api/leitor/inventario/encerrar ──────────────────────────────────

    public function encerrarApi(): void
    {
        header('Content-Type: application/json; charset=utf-8');
        if (empty($_SESSION['leitor_ok'])) { http_response_code(401); echo json_encode(['erro' => 'Nao autenticado']); exit; }
        if (!in_array('inventario', $_SESSION['leitor_perms'] ?? [], true)) { http_response_code(403); echo json_encode(['erro' => 'Sem permissao']); exit; }

        $empresa  = (int)($_SESSION['leitor_empresa'] ?? 0);
        $operador = $_SESSION['leitor_usuario'] ?? '';
        $sessao   = self::lerSessaoAtiva($empresa);
        if (!$sessao) { http_response_code(400); echo json_encode(['erro' => 'Sem sessao ativa']); exit; }

        $aplicar = !empty($_POST['aplicar']) && in_array('inventario_encerrar', $_SESSION['leitor_perms'] ?? [], true);

        if ($aplicar) {
            session_write_close();
            try {
                $pdo = \App\Core\Database::conectar();
                foreach ($sessao['itens'] as $item) {
                    if (abs($item['divergencia'] ?? 0) < 0.001) continue;
                    // Usa o mesmo mecanismo de ajuste de estoque já existente
                    $st = $pdo->prepare(
                        "UPDATE ITENS_ESTOQUE SET QTD = ?
                         WHERE COD_ITEM = ? AND COD_EMPRESA = ?"
                    );
                    $st->execute([$item['qtd_contada'], $item['cod_item'], $empresa]);

                    LeitorController::registrarAudit('ajuste_estoque', $item['cod_item'], [
                        'tipo'     => 'inventario',
                        'sessao'   => $sessao['id'],
                        'qtd_ant'  => $item['qtd_sistema'],
                        'qtd_nova' => $item['qtd_contada'],
                    ], $empresa);
                }
                $sessao['ajustes_aplicados'] = true;
            } catch (\Throwable $e) {
                echo json_encode(['erro' => 'Erro ao aplicar: ' . $e->getMessage()]);
                exit;
            }
        }

        $sessao['status']   = 'encerrada';
        $sessao['data_fim'] = date('Y-m-d H:i:s');
        $sessao['encerrado_por'] = $operador;
        self::salvarSessao($sessao);

        // Remove ponteiro de ativa
        @unlink(self::arquivoAtiva($empresa));

        $itens = $sessao['itens'] ?? [];
        $divs  = array_filter($itens, fn($i) => abs($i['divergencia'] ?? 0) > 0.001);
        echo json_encode([
            'ok'           => true,
            'aplicado'     => $aplicar,
            'total_itens'  => count($itens),
            'divergencias' => count($divs),
            'id'           => $sessao['id'],
        ], JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
        exit;
    }
}
