<?php
declare(strict_types=1);

require_once 'auth.php';
require_once 'conexao.php';

date_default_timezone_set('America/Sao_Paulo');

if ($mysqli instanceof mysqli) {
    $mysqli->set_charset('utf8mb4');
}

if (session_status() !== PHP_SESSION_ACTIVE) {
    session_start();
}

function e(mixed $value): string
{
    return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}

function cleanText(string $value): string
{
    return trim(preg_replace('/\s+/', ' ', $value) ?? $value);
}

function cleanCode(string $value): string
{
    return trim(preg_replace('/[^A-Za-z0-9\-_\.]/', '', $value) ?? '');
}

function lowerText(string $value): string
{
    return function_exists('mb_strtolower')
        ? mb_strtolower($value, 'UTF-8')
        : strtolower($value);
}

function columnExists(mysqli $mysqli, string $table, string $column): bool
{
    $stmt = $mysqli->prepare("\n        SELECT COUNT(*) AS total\n        FROM INFORMATION_SCHEMA.COLUMNS\n        WHERE TABLE_SCHEMA = DATABASE()\n          AND TABLE_NAME = ?\n          AND COLUMN_NAME = ?\n    ");

    if (!$stmt) {
        return false;
    }

    $stmt->bind_param('ss', $table, $column);
    $stmt->execute();
    $row = $stmt->get_result()->fetch_assoc();
    $stmt->close();

    return (int) ($row['total'] ?? 0) > 0;
}

function isAjax(): bool
{
    return ($_POST['ajax'] ?? '') === '1'
        || strtolower((string) ($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '')) === 'xmlhttprequest';
}

function respond(bool $ok, string $message, array $extra = []): never
{
    if (isAjax()) {
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(
            array_merge(['ok' => $ok, 'message' => $message], $extra),
            JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
        );
        exit;
    }

    $_SESSION['almox_flash'] = [
        'type' => $ok ? 'success' : 'error',
        'message' => $message,
    ];

    header('Location: almoxarifado.php');
    exit;
}

function stockStatus(int $quantity, int $minimum): array
{
    if ($quantity <= 0) {
        return ['code' => 'empty', 'label' => 'Sem estoque', 'icon' => 'bi-x-octagon-fill'];
    }

    if ($quantity <= $minimum) {
        return ['code' => 'critical', 'label' => 'Crítico', 'icon' => 'bi-exclamation-octagon-fill'];
    }

    if ($quantity <= ($minimum + 5)) {
        return ['code' => 'low', 'label' => 'Baixo', 'icon' => 'bi-exclamation-triangle-fill'];
    }

    return ['code' => 'healthy', 'label' => 'Saudável', 'icon' => 'bi-check-circle-fill'];
}

/* --------------------------------------------------------------------------
   EVOLUÇÃO AUTOMÁTICA DO BANCO
   -------------------------------------------------------------------------- */

if (!columnExists($mysqli, 'almoxarifado', 'codigo_barras')) {
    $mysqli->query("\n        ALTER TABLE almoxarifado\n        ADD COLUMN codigo_barras VARCHAR(120) NULL AFTER modelo\n    ");
}

if (!columnExists($mysqli, 'almoxarifado', 'atualizado_em')) {
    $mysqli->query("\n        ALTER TABLE almoxarifado\n        ADD COLUMN atualizado_em TIMESTAMP NOT NULL\n        DEFAULT CURRENT_TIMESTAMP\n        ON UPDATE CURRENT_TIMESTAMP\n    ");
}

$mysqli->query("\n    CREATE TABLE IF NOT EXISTS almoxarifado_movimentacoes (\n        id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,\n        item_id INT NOT NULL,\n        tipo ENUM('ENTRADA', 'SAIDA') NOT NULL,\n        quantidade INT NOT NULL,\n        estoque_anterior INT NOT NULL DEFAULT 0,\n        estoque_posterior INT NOT NULL DEFAULT 0,\n        responsavel VARCHAR(160) NOT NULL,\n        origem_destino VARCHAR(190) NOT NULL,\n        documento VARCHAR(100) NULL,\n        observacao VARCHAR(255) NULL,\n        usuario_sistema VARCHAR(120) NULL,\n        criado_em TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n        INDEX idx_mov_item (item_id),\n        INDEX idx_mov_tipo (tipo),\n        INDEX idx_mov_data (criado_em)\n    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4\n");

$currentUser = cleanText((string) ($_SESSION['usuario'] ?? 'Servidor da TI'));

/* --------------------------------------------------------------------------
   AÇÕES
   -------------------------------------------------------------------------- */

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

    if ($action === 'cadastrar') {
        $name = cleanText((string) ($_POST['nome'] ?? ''));
        $category = cleanText((string) ($_POST['categoria'] ?? ''));
        $brand = cleanText((string) ($_POST['marca'] ?? ''));
        $model = cleanText((string) ($_POST['modelo'] ?? ''));
        $barcode = cleanCode((string) ($_POST['codigo_barras'] ?? ''));
        $quantity = max(0, (int) ($_POST['quantidade'] ?? 0));
        $minimum = max(0, (int) ($_POST['minimo'] ?? 0));
        $location = cleanText((string) ($_POST['localizacao'] ?? ''));
        $responsible = cleanText((string) ($_POST['responsavel'] ?? ''));
        $origin = cleanText((string) ($_POST['origem_destino'] ?? ''));
        $document = cleanText((string) ($_POST['documento'] ?? ''));
        $notes = cleanText((string) ($_POST['observacao'] ?? ''));

        if ($name === '' || $category === '') {
            respond(false, 'Informe o nome e a categoria do produto.');
        }

        if ($quantity > 0 && ($responsible === '' || $origin === '')) {
            respond(false, 'Para cadastrar com quantidade inicial, informe o responsável e a origem.');
        }

        try {
            $mysqli->begin_transaction();

            if ($barcode !== '') {
                $stmt = $mysqli->prepare('SELECT id FROM almoxarifado WHERE codigo_barras = ? LIMIT 1');
                if (!$stmt) {
                    throw new RuntimeException('Falha ao validar o código.');
                }
                $stmt->bind_param('s', $barcode);
                $stmt->execute();
                $duplicate = $stmt->get_result()->fetch_assoc();
                $stmt->close();

                if ($duplicate) {
                    throw new DomainException('Este código de barras já pertence a outro produto.');
                }
            }

            $stmt = $mysqli->prepare("\n                INSERT INTO almoxarifado\n                    (nome, categoria, marca, modelo, codigo_barras, quantidade, minimo, localizacao)\n                VALUES (?, ?, ?, ?, NULLIF(?, ''), ?, ?, ?)\n            ");

            if (!$stmt) {
                throw new RuntimeException('Falha ao preparar o cadastro.');
            }

            $stmt->bind_param(
                'sssssiis',
                $name,
                $category,
                $brand,
                $model,
                $barcode,
                $quantity,
                $minimum,
                $location
            );
            $stmt->execute();
            $itemId = (int) $stmt->insert_id;
            $stmt->close();

            $movementId = null;

            if ($quantity > 0) {
                $type = 'ENTRADA';
                $previous = 0;
                $after = $quantity;

                $stmt = $mysqli->prepare("\n                    INSERT INTO almoxarifado_movimentacoes\n                        (item_id, tipo, quantidade, estoque_anterior, estoque_posterior,\n                         responsavel, origem_destino, documento, observacao, usuario_sistema)\n                    VALUES (?, ?, ?, ?, ?, ?, ?, NULLIF(?, ''), NULLIF(?, ''), ?)\n                ");

                if (!$stmt) {
                    throw new RuntimeException('Falha ao registrar a entrada inicial.');
                }

                $stmt->bind_param(
                    'isiiisssss',
                    $itemId,
                    $type,
                    $quantity,
                    $previous,
                    $after,
                    $responsible,
                    $origin,
                    $document,
                    $notes,
                    $currentUser
                );
                $stmt->execute();
                $movementId = (int) $stmt->insert_id;
                $stmt->close();
            }

            $mysqli->commit();

            respond(true, 'Produto cadastrado com sucesso.', [
                'receipt_id' => $movementId,
                'reload' => true,
            ]);
        } catch (DomainException $error) {
            $mysqli->rollback();
            respond(false, $error->getMessage());
        } catch (Throwable $error) {
            $mysqli->rollback();
            respond(false, 'Não foi possível cadastrar o produto.');
        }
    }

    if ($action === 'movimentar') {
        $itemId = (int) ($_POST['item_id'] ?? 0);
        $type = strtoupper(cleanText((string) ($_POST['tipo'] ?? '')));
        $quantity = max(0, (int) ($_POST['quantidade'] ?? 0));
        $responsible = cleanText((string) ($_POST['responsavel'] ?? ''));
        $originDestination = cleanText((string) ($_POST['origem_destino'] ?? ''));
        $document = cleanText((string) ($_POST['documento'] ?? ''));
        $notes = cleanText((string) ($_POST['observacao'] ?? ''));

        if ($itemId <= 0 || !in_array($type, ['ENTRADA', 'SAIDA'], true)) {
            respond(false, 'Movimentação inválida.');
        }

        if ($quantity <= 0) {
            respond(false, 'Informe uma quantidade maior que zero.');
        }

        if ($responsible === '' || $originDestination === '') {
            respond(false, 'Informe o responsável e a origem ou destino do material.');
        }

        try {
            $mysqli->begin_transaction();

            $stmt = $mysqli->prepare("\n                SELECT id, nome, quantidade\n                FROM almoxarifado\n                WHERE id = ?\n                FOR UPDATE\n            ");

            if (!$stmt) {
                throw new RuntimeException('Falha ao consultar o produto.');
            }

            $stmt->bind_param('i', $itemId);
            $stmt->execute();
            $item = $stmt->get_result()->fetch_assoc();
            $stmt->close();

            if (!$item) {
                throw new DomainException('Produto não encontrado.');
            }

            $previous = (int) $item['quantidade'];

            if ($type === 'SAIDA' && $previous < $quantity) {
                throw new DomainException("Estoque insuficiente. Disponível: {$previous} unidade(s).");
            }

            $after = $type === 'ENTRADA'
                ? $previous + $quantity
                : $previous - $quantity;

            $stmt = $mysqli->prepare('UPDATE almoxarifado SET quantidade = ? WHERE id = ?');
            if (!$stmt) {
                throw new RuntimeException('Falha ao atualizar o estoque.');
            }
            $stmt->bind_param('ii', $after, $itemId);
            $stmt->execute();
            $stmt->close();

            $stmt = $mysqli->prepare("\n                INSERT INTO almoxarifado_movimentacoes\n                    (item_id, tipo, quantidade, estoque_anterior, estoque_posterior,\n                     responsavel, origem_destino, documento, observacao, usuario_sistema)\n                VALUES (?, ?, ?, ?, ?, ?, ?, NULLIF(?, ''), NULLIF(?, ''), ?)\n            ");

            if (!$stmt) {
                throw new RuntimeException('Falha ao registrar a movimentação.');
            }

            $stmt->bind_param(
                'isiiisssss',
                $itemId,
                $type,
                $quantity,
                $previous,
                $after,
                $responsible,
                $originDestination,
                $document,
                $notes,
                $currentUser
            );
            $stmt->execute();
            $movementId = (int) $stmt->insert_id;
            $stmt->close();

            $mysqli->commit();

            respond(true, ($type === 'ENTRADA' ? 'Entrada' : 'Saída') . " registrada. Saldo atual: {$after} unidade(s).", [
                'receipt_id' => $movementId,
                'stock' => $after,
                'item_id' => $itemId,
                'type' => $type,
            ]);
        } catch (DomainException $error) {
            $mysqli->rollback();
            respond(false, $error->getMessage());
        } catch (Throwable $error) {
            $mysqli->rollback();
            respond(false, 'Não foi possível concluir a movimentação.');
        }
    }

    if ($action === 'editar') {
        $itemId = (int) ($_POST['item_id'] ?? 0);
        $name = cleanText((string) ($_POST['nome'] ?? ''));
        $category = cleanText((string) ($_POST['categoria'] ?? ''));
        $brand = cleanText((string) ($_POST['marca'] ?? ''));
        $model = cleanText((string) ($_POST['modelo'] ?? ''));
        $barcode = cleanCode((string) ($_POST['codigo_barras'] ?? ''));
        $minimum = max(0, (int) ($_POST['minimo'] ?? 0));
        $location = cleanText((string) ($_POST['localizacao'] ?? ''));

        if ($itemId <= 0 || $name === '' || $category === '') {
            respond(false, 'Dados inválidos para atualização.');
        }

        if ($barcode !== '') {
            $stmt = $mysqli->prepare("\n                SELECT id\n                FROM almoxarifado\n                WHERE codigo_barras = ?\n                  AND id <> ?\n                LIMIT 1\n            ");

            if (!$stmt) {
                respond(false, 'Não foi possível validar o código.');
            }

            $stmt->bind_param('si', $barcode, $itemId);
            $stmt->execute();
            $duplicate = $stmt->get_result()->fetch_assoc();
            $stmt->close();

            if ($duplicate) {
                respond(false, 'O código de barras já pertence a outro produto.');
            }
        }

        $stmt = $mysqli->prepare("\n            UPDATE almoxarifado\n            SET nome = ?,\n                categoria = ?,\n                marca = ?,\n                modelo = ?,\n                codigo_barras = NULLIF(?, ''),\n                minimo = ?,\n                localizacao = ?\n            WHERE id = ?\n        ");

        if (!$stmt) {
            respond(false, 'Não foi possível preparar a atualização.');
        }

        $stmt->bind_param(
            'sssssisi',
            $name,
            $category,
            $brand,
            $model,
            $barcode,
            $minimum,
            $location,
            $itemId
        );
        $stmt->execute();
        $stmt->close();

        respond(true, 'Produto atualizado com sucesso.', ['reload' => true]);
    }

    respond(false, 'Ação não reconhecida.');
}

/* --------------------------------------------------------------------------
   CONSULTAS E INDICADORES
   -------------------------------------------------------------------------- */

$items = [];
$result = $mysqli->query("\n    SELECT\n        a.*,\n        COALESCE(c.saidas_30_dias, 0) AS saidas_30_dias,\n        u.criado_em AS ultima_movimentacao_em\n    FROM almoxarifado a\n    LEFT JOIN (\n        SELECT item_id, SUM(quantidade) AS saidas_30_dias\n        FROM almoxarifado_movimentacoes\n        WHERE tipo = 'SAIDA'\n          AND criado_em >= DATE_SUB(NOW(), INTERVAL 30 DAY)\n        GROUP BY item_id\n    ) c ON c.item_id = a.id\n    LEFT JOIN almoxarifado_movimentacoes u\n      ON u.id = (\n          SELECT MAX(m2.id)\n          FROM almoxarifado_movimentacoes m2\n          WHERE m2.item_id = a.id\n      )\n    ORDER BY a.quantidade ASC, a.nome ASC\n");

if ($result) {
    while ($row = $result->fetch_assoc()) {
        $items[] = $row;
    }
    $result->free();
}

$movements = [];
$resultMov = $mysqli->query("\n    SELECT m.*, a.nome, a.categoria, a.marca, a.modelo, a.codigo_barras\n    FROM almoxarifado_movimentacoes m\n    INNER JOIN almoxarifado a ON a.id = m.item_id\n    ORDER BY m.criado_em DESC, m.id DESC\n    LIMIT 150\n");

if ($resultMov) {
    $movements = $resultMov->fetch_all(MYSQLI_ASSOC);
    $resultMov->free();
}

$totalProducts = count($items);
$totalUnits = 0;
$healthy = 0;
$low = 0;
$critical = 0;
$empty = 0;
$entriesToday = 0;
$exitsToday = 0;
$categories = [];

foreach ($items as $item) {
    $quantity = (int) $item['quantidade'];
    $minimum = (int) $item['minimo'];
    $status = stockStatus($quantity, $minimum);

    $totalUnits += $quantity;

    if ($status['code'] === 'healthy') {
        $healthy++;
    } elseif ($status['code'] === 'low') {
        $low++;
    } elseif ($status['code'] === 'critical') {
        $critical++;
    } else {
        $empty++;
    }

    $category = trim((string) $item['categoria']);
    if ($category !== '') {
        $categories[$category] = true;
    }
}

foreach ($movements as $movement) {
    $timestamp = strtotime((string) $movement['criado_em']);

    if ($timestamp !== false && date('Y-m-d', $timestamp) === date('Y-m-d')) {
        if ($movement['tipo'] === 'ENTRADA') {
            $entriesToday += (int) $movement['quantidade'];
        } else {
            $exitsToday += (int) $movement['quantidade'];
        }
    }
}

ksort($categories, SORT_NATURAL | SORT_FLAG_CASE);

$flash = $_SESSION['almox_flash'] ?? null;
unset($_SESSION['almox_flash']);

$currentHour = (int) date('H');
$greeting = match (true) {
    $currentHour >= 5 && $currentHour < 12 => 'Bom dia',
    $currentHour >= 12 && $currentHour < 18 => 'Boa tarde',
    default => 'Boa noite',
};

$itemsJson = json_encode(
    array_map(
        static fn(array $item): array => [
            'id' => (int) $item['id'],
            'nome' => (string) $item['nome'],
            'categoria' => (string) $item['categoria'],
            'marca' => (string) ($item['marca'] ?? ''),
            'modelo' => (string) ($item['modelo'] ?? ''),
            'codigo_barras' => (string) ($item['codigo_barras'] ?? ''),
            'quantidade' => (int) $item['quantidade'],
            'minimo' => (int) $item['minimo'],
            'localizacao' => (string) ($item['localizacao'] ?? ''),
        ],
        $items
    ),
    JSON_UNESCAPED_UNICODE |
    JSON_UNESCAPED_SLASHES |
    JSON_HEX_TAG |
    JSON_HEX_APOS |
    JSON_HEX_QUOT |
    JSON_HEX_AMP
);
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
    <meta name="theme-color" content="#08396f">
    <title>Almoxarifado Inteligente | Manutenção TI</title>

    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">

    <style>
        :root{
            --primary:#08396f;--primary-dark:#05294f;--primary-light:#145b9f;
            --green:#087f5b;--green-soft:#e8f8f1;--yellow:#c97800;--yellow-soft:#fff6e3;
            --red:#bd263d;--red-soft:#fff0f3;--blue-soft:#eaf4fc;
            --bg:#edf3f8;--surface:#fff;--surface-soft:#f6f9fc;
            --text:#152236;--muted:#617086;--light:#8795a8;--border:#dce5ee;--border-soft:#e9eff5;
            --shadow-sm:0 10px 28px rgba(8,57,111,.06);
            --shadow-md:0 22px 58px rgba(8,57,111,.11);
            --shadow-lg:0 36px 95px rgba(5,41,79,.18);
        }
        *{box-sizing:border-box}
        html{min-height:100%;scroll-behavior:smooth}
        body{margin:0;min-height:100vh;overflow-x:hidden;font-family:"Inter",system-ui,sans-serif;color:var(--text);background:radial-gradient(circle at 7% 5%,rgba(20,91,159,.13),transparent 28rem),radial-gradient(circle at 96% 90%,rgba(8,127,91,.09),transparent 30rem),linear-gradient(145deg,#f8fafc,var(--bg) 55%,#e8f0f6)}
        a{text-decoration:none}button,input,select,textarea{font:inherit}
        .top-strip{position:fixed;inset:0 0 auto;z-index:1100;height:6px;background:linear-gradient(90deg,var(--primary) 0 58%,var(--green) 58% 88%,#e8ad16 88%)}
        .bg-grid{position:fixed;inset:0;z-index:0;pointer-events:none;background-image:linear-gradient(rgba(8,57,111,.026) 1px,transparent 1px),linear-gradient(90deg,rgba(8,57,111,.026) 1px,transparent 1px);background-size:54px 54px;mask-image:linear-gradient(to bottom,#000,transparent 94%)}
        .orb{position:fixed;z-index:0;width:450px;height:450px;border-radius:50%;pointer-events:none;animation:orbFloat 11s ease-in-out infinite}
        .orb.one{top:-230px;left:-170px;background:radial-gradient(circle at 68% 70%,rgba(20,91,159,.12),transparent 63%)}
        .orb.two{right:-260px;bottom:-260px;width:560px;height:560px;background:radial-gradient(circle at 30% 28%,rgba(8,127,91,.1),transparent 63%);animation-delay:2s}
        @keyframes orbFloat{50%{transform:translateY(-18px) rotate(5deg)}}
        .app{position:relative;z-index:2;padding-top:6px}
        .header{position:relative;overflow:hidden;margin:19px 19px 0;padding:20px 22px;border:1px solid rgba(255,255,255,.18);border-radius:27px;color:#fff;background:radial-gradient(circle at 82% 0,rgba(255,255,255,.12),transparent 22rem),radial-gradient(circle at 0 100%,rgba(8,127,91,.25),transparent 24rem),linear-gradient(135deg,var(--primary-dark),var(--primary) 56%,#07537c);box-shadow:var(--shadow-lg),inset 0 1px 0 rgba(255,255,255,.12)}
        .header:before{content:"";position:absolute;top:-205px;right:-110px;width:420px;height:420px;border:40px solid rgba(255,255,255,.035);border-radius:50%;box-shadow:0 0 0 42px rgba(255,255,255,.018),0 0 0 84px rgba(255,255,255,.012);animation:spin 30s linear infinite}
        @keyframes spin{to{transform:rotate(360deg)}}
        .header-content{position:relative;z-index:2;display:flex;align-items:center;justify-content:space-between;gap:24px}
        .brand{min-width:0;display:flex;align-items:center;gap:15px}
        .logo{width:70px;height:70px;flex:0 0 70px;display:grid;place-items:center;padding:5px;border-radius:21px;background:linear-gradient(145deg,#fff,#dceaf5);box-shadow:0 18px 36px rgba(0,0,0,.18);animation:logoFloat 6s ease-in-out infinite}
        @keyframes logoFloat{0%,100%{transform:perspective(700px) rotateX(4deg) rotateY(-5deg)}50%{transform:perspective(700px) translateY(-5px) rotateY(3deg)}}
        .logo-inner{width:100%;height:100%;display:grid;place-items:center;overflow:hidden;border:1px solid rgba(8,57,111,.08);border-radius:17px;background:#fff}
        .logo-inner img{max-width:56px;max-height:56px;object-fit:contain}.logo-fallback{display:none;width:100%;height:100%;place-items:center;color:var(--primary);background:#f0f6fa;font-size:28px}
        .gov-label{display:inline-flex;align-items:center;gap:7px;margin-bottom:7px;padding:6px 10px;border:1px solid rgba(255,255,255,.15);border-radius:999px;color:rgba(255,255,255,.84);background:rgba(255,255,255,.08);font-size:9px;font-weight:800;letter-spacing:.65px;text-transform:uppercase}.gov-label i{color:#9cebd2}
        .header h1{margin:0;font-size:clamp(22px,2.4vw,34px);line-height:1.04;letter-spacing:-1px;font-weight:900}.header-subtitle{margin:7px 0 0;color:rgba(255,255,255,.68);font-size:11px;line-height:1.55}
        .header-side{min-width:430px;display:flex;flex-direction:column;align-items:flex-end;gap:12px}.user-line{display:flex;align-items:center;gap:10px;text-align:right}.user-line strong{display:block;font-size:11px;font-weight:800}.user-line span{display:block;margin-top:3px;color:rgba(255,255,255,.6);font-size:8px}.avatar{width:40px;height:40px;display:grid;place-items:center;border-radius:13px;color:var(--primary-dark);background:linear-gradient(145deg,#fff,#dceaf5);font-size:17px}
        .header-actions{display:flex;justify-content:flex-end;gap:7px;flex-wrap:wrap}.header-btn{min-height:38px;display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:0 12px;border:1px solid rgba(255,255,255,.15);border-radius:13px;color:#fff;background:rgba(255,255,255,.08);font-size:9px;font-weight:800;text-transform:uppercase;transition:.2s}.header-btn:hover{color:#fff;background:rgba(255,255,255,.15);transform:translateY(-2px)}.header-btn.primary{color:var(--primary-dark);border-color:#fff;background:#fff}.header-btn.primary:hover{color:var(--primary-dark);background:#eef6fc}
        .main{width:100%;max-width:1700px;margin:0 auto;padding:17px 19px 32px}
        .flash{display:flex;align-items:center;gap:11px;margin-bottom:14px;padding:13px 15px;border:1px solid var(--border);border-radius:17px;background:#fff;box-shadow:var(--shadow-sm);font-size:10px;font-weight:700}.flash.success{color:#076448;border-color:#c3e9dc;background:var(--green-soft)}.flash.error{color:#932238;border-color:#efcbd2;background:var(--red-soft)}.flash-icon{width:35px;height:35px;display:grid;place-items:center;border-radius:12px;color:#fff;background:var(--primary)}.flash.success .flash-icon{background:var(--green)}.flash.error .flash-icon{background:var(--red)}
        .scanner{position:relative;display:grid;grid-template-columns:minmax(0,1.35fr) minmax(300px,.65fr);gap:17px;overflow:hidden;padding:22px;border:1px solid rgba(255,255,255,.9);border-radius:30px;background:rgba(255,255,255,.84);backdrop-filter:blur(20px);box-shadow:var(--shadow-md),inset 0 1px 0 #fff}.scanner:after{content:"";position:absolute;right:-95px;bottom:-150px;width:330px;height:330px;border-radius:50%;background:radial-gradient(circle,rgba(8,127,91,.08),transparent 68%)}
        .eyebrow{display:inline-flex;align-items:center;gap:7px;margin-bottom:11px;color:var(--primary);font-size:8px;font-weight:850;letter-spacing:.65px;text-transform:uppercase}.scanner h2{max-width:820px;margin:0;font-size:clamp(25px,3vw,41px);line-height:1.04;letter-spacing:-1.65px;font-weight:900}.scanner h2 span{color:var(--primary)}.scanner p{max-width:780px;margin:12px 0 0;color:var(--muted);font-size:10px;line-height:1.65}
        .scanner-modes{display:flex;gap:7px;margin-top:16px}.mode-btn{min-height:35px;display:inline-flex;align-items:center;gap:6px;padding:0 11px;border:1px solid var(--border);border-radius:11px;color:var(--muted);background:#fff;font-size:8px;font-weight:850;text-transform:uppercase;transition:.18s}.mode-btn.active{color:#fff;border-color:var(--primary);background:var(--primary);box-shadow:0 10px 20px rgba(8,57,111,.16)}.mode-btn.exit.active{border-color:var(--red);background:var(--red)}
        .scanner-input-wrap{position:relative;margin-top:11px}.scanner-input-wrap>i{position:absolute;top:50%;left:15px;color:var(--primary);font-size:19px;transform:translateY(-50%)}.scanner-input{width:100%;height:58px;border:2px solid #cddbe7;border-radius:18px;outline:0;color:var(--text);background:#fff;padding:0 115px 0 46px;box-shadow:var(--shadow-sm);font-size:13px;font-weight:750;letter-spacing:.4px;transition:.2s}.scanner-input:focus{border-color:var(--primary-light);box-shadow:0 0 0 5px rgba(20,91,159,.1),var(--shadow-sm);transform:translateY(-1px)}.scanner-ready{position:absolute;top:50%;right:10px;display:inline-flex;align-items:center;gap:6px;padding:7px 9px;border-radius:999px;color:#086247;background:var(--green-soft);font-size:7px;font-weight:850;text-transform:uppercase;transform:translateY(-50%)}.scanner-dot{width:7px;height:7px;border-radius:50%;background:var(--green);animation:pulse 1.5s infinite}@keyframes pulse{50%{box-shadow:0 0 0 7px rgba(8,127,91,0)}}
        .scanner-result{display:none;margin-top:10px;padding:11px 12px;border:1px solid var(--border);border-radius:13px;background:var(--surface-soft);color:var(--muted);font-size:9px;font-weight:600}.scanner-result.visible{display:block}.scanner-result.success{color:#076448;border-color:#c3e9dc;background:var(--green-soft)}.scanner-result.error{color:#932238;border-color:#efcbd2;background:var(--red-soft)}
        .scanner-side{position:relative;z-index:2;min-height:225px;padding:20px;display:flex;flex-direction:column;justify-content:space-between;border-radius:24px;color:#fff;background:radial-gradient(circle at 90% 10%,rgba(255,255,255,.13),transparent 12rem),linear-gradient(145deg,var(--primary-dark),var(--primary));box-shadow:0 22px 46px rgba(8,57,111,.2);transform:translateZ(20px)}.scanner-side strong{display:block;font-size:44px;line-height:1;letter-spacing:-1.5px;font-weight:900}.scanner-side h3{margin:9px 0 0;font-size:13px;font-weight:850}.scanner-side p{color:rgba(255,255,255,.65);font-size:9px;line-height:1.55}.smart-line{height:8px;overflow:hidden;border-radius:999px;background:rgba(255,255,255,.13)}.smart-line span{display:block;width:75%;height:100%;border-radius:inherit;background:linear-gradient(90deg,#91ebcf,#fff)}
        .kpi-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:11px;margin-top:14px}.kpi{position:relative;min-height:122px;padding:15px;overflow:hidden;border:1px solid var(--border);border-radius:21px;background:rgba(255,255,255,.9);backdrop-filter:blur(15px);box-shadow:var(--shadow-sm),inset 0 1px 0 #fff;transition:.22s}.kpi:hover{border-color:#c5d5e3;transform:translateY(-5px) perspective(800px) rotateX(2deg);box-shadow:var(--shadow-md)}.kpi:after{content:"";position:absolute;top:-50px;right:-50px;width:116px;height:116px;border-radius:50%;background:rgba(20,91,159,.05)}.kpi-top{position:relative;z-index:2;display:flex;justify-content:space-between;gap:8px}.kpi-icon{width:39px;height:39px;display:grid;place-items:center;border-radius:13px;color:var(--primary);background:var(--blue-soft);font-size:17px}.kpi-number{font-size:29px;line-height:1;letter-spacing:-1.2px;font-weight:900}.kpi-label{position:relative;z-index:2;display:block;margin-top:13px;color:var(--muted);font-size:7px;font-weight:850;letter-spacing:.5px;text-transform:uppercase}.kpi small{position:relative;z-index:2;display:block;margin-top:4px;color:var(--light);font-size:7px;line-height:1.4}.kpi.green .kpi-icon{color:var(--green);background:var(--green-soft)}.kpi.yellow .kpi-icon{color:var(--yellow);background:var(--yellow-soft)}.kpi.red .kpi-icon{color:var(--red);background:var(--red-soft)}
        .panel{margin-top:14px;overflow:hidden;border:1px solid rgba(255,255,255,.9);border-radius:30px;background:rgba(255,255,255,.9);backdrop-filter:blur(18px);box-shadow:var(--shadow-md),inset 0 1px 0 #fff}.panel-header{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:18px 19px;border-bottom:1px solid var(--border-soft);background:radial-gradient(circle at 100% 0,rgba(20,91,159,.06),transparent 17rem),linear-gradient(180deg,#fff,#f9fbfd)}.panel-title{display:flex;align-items:center;gap:11px}.panel-title-icon{width:41px;height:41px;display:grid;place-items:center;border-radius:14px;color:#fff;background:linear-gradient(145deg,var(--primary),var(--primary-light));box-shadow:0 12px 24px rgba(8,57,111,.18);font-size:17px}.panel-header h2{margin:0;font-size:15px;font-weight:850}.panel-header p{margin:4px 0 0;color:var(--muted);font-size:8px;line-height:1.45}.counter{display:inline-flex;align-items:center;gap:6px;padding:7px 9px;border:1px solid var(--border);border-radius:999px;color:var(--primary);background:#fff;font-size:8px;font-weight:800}
        .filters,.history-filters{display:grid;grid-template-columns:minmax(250px,1fr) 190px 190px auto;gap:9px;padding:14px 17px;border-bottom:1px solid var(--border-soft);background:#fbfdfe}.search-wrap{position:relative}.search-wrap i{position:absolute;top:50%;left:14px;color:var(--primary);font-size:14px;transform:translateY(-50%)}.search-input,.filter-select{width:100%;height:46px;border:1px solid var(--border);border-radius:14px;outline:0;color:var(--text);background:var(--surface-soft);padding:0 13px;font-size:9px;font-weight:650;transition:.2s}.search-input{padding-left:39px}.search-input:focus,.filter-select:focus{border-color:var(--primary-light);background:#fff;box-shadow:0 0 0 4px rgba(20,91,159,.1)}.clear-btn{min-height:46px;display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:0 13px;border:1px solid var(--border);border-radius:14px;color:var(--muted);background:#fff;font-size:8px;font-weight:850;text-transform:uppercase;transition:.18s}.clear-btn:hover{color:var(--primary);transform:translateY(-2px)}
        .inventory{display:grid;grid-template-columns:repeat(auto-fill,minmax(275px,1fr));gap:12px;padding:16px}.item-card{position:relative;min-height:285px;padding:16px;overflow:hidden;border:1px solid var(--border);border-radius:21px;background:#fff;box-shadow:var(--shadow-sm);transform-style:preserve-3d;transition:.22s}.item-card:hover{border-color:#c3d3e1;transform:translateY(-6px) perspective(900px) rotateX(2deg);box-shadow:var(--shadow-md)}.item-card:before{content:"";position:absolute;inset:0 auto 0 0;width:5px;background:var(--green)}.item-card.low:before{background:var(--yellow)}.item-card.critical:before,.item-card.empty:before{background:var(--red)}.item-card:after{content:"";position:absolute;top:-48px;right:-48px;width:114px;height:114px;border-radius:50%;background:rgba(20,91,159,.05)}.item-top{position:relative;z-index:2;display:flex;justify-content:space-between;align-items:flex-start;gap:10px}.item-title{margin:0;color:var(--text);font-size:13px;line-height:1.35;font-weight:850}.item-meta{margin-top:4px;color:var(--light);font-size:8px;line-height:1.4}.status{display:inline-flex;align-items:center;gap:5px;padding:6px 8px;border:1px solid #c3e9dc;border-radius:999px;color:#076448;background:var(--green-soft);font-size:7px;font-weight:850;white-space:nowrap}.status.low{color:#916000;border-color:#edd9aa;background:var(--yellow-soft)}.status.critical,.status.empty{color:#922138;border-color:#edc7cf;background:var(--red-soft)}.item-tags{position:relative;z-index:2;display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}.tag{display:inline-flex;align-items:center;gap:5px;padding:6px 8px;border:1px solid var(--border-soft);border-radius:999px;color:#5a6a7e;background:var(--surface-soft);font-size:7px;font-weight:750}.stock{position:relative;z-index:2;display:flex;align-items:flex-end;gap:6px;margin-top:15px}.stock strong{font-size:40px;line-height:.92;letter-spacing:-1.7px;font-weight:900}.stock span{color:var(--light);font-size:8px;font-weight:750}.smart-grid{position:relative;z-index:2;display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:12px}.smart{padding:8px;border:1px solid var(--border-soft);border-radius:11px;background:var(--surface-soft)}.smart span{display:block;color:var(--light);font-size:6px;font-weight:800;letter-spacing:.4px;text-transform:uppercase}.smart strong{display:block;margin-top:4px;color:var(--text);font-size:8px;font-weight:800}.progress-line{position:relative;z-index:2;height:7px;overflow:hidden;margin-top:11px;border-radius:999px;background:#e7edf3}.progress-line span{display:block;height:100%;border-radius:inherit;background:var(--green)}.item-card.low .progress-line span{background:var(--yellow)}.item-card.critical .progress-line span,.item-card.empty .progress-line span{background:var(--red)}.item-actions{position:relative;z-index:2;display:grid;grid-template-columns:1fr 1fr auto;gap:7px;margin-top:13px}.item-btn{min-height:37px;display:flex;align-items:center;justify-content:center;gap:6px;border:1px solid var(--border);border-radius:12px;color:var(--muted);background:#fff;font-size:7px;font-weight:850;text-transform:uppercase;transition:.18s}.item-btn:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm)}.item-btn:disabled{cursor:not-allowed;opacity:.45;transform:none}.item-btn.entry{color:#fff;border-color:var(--green);background:var(--green)}.item-btn.exit{color:#fff;border-color:var(--red);background:var(--red)}.item-btn.edit{width:37px;padding:0;color:var(--primary)}.empty-state{grid-column:1/-1;padding:55px 20px;text-align:center;color:var(--muted)}.empty-state i{display:block;margin-bottom:10px;color:var(--primary);font-size:34px}
        .table-wrap{max-height:62vh;overflow:auto;scrollbar-width:thin}.history-table{width:100%;min-width:1120px;border-collapse:separate;border-spacing:0}.history-table th{position:sticky;top:0;z-index:5;padding:13px 14px;border-bottom:1px solid var(--border);color:#65758a;background:#f5f8fb;font-size:8px;font-weight:850;letter-spacing:.55px;text-transform:uppercase;white-space:nowrap}.history-table td{padding:13px 14px;border-bottom:1px solid var(--border-soft);color:#354459;background:rgba(255,255,255,.86);font-size:9px;font-weight:600;vertical-align:middle}.history-table tr:hover td{background:#f7fafc}.movement-type{display:inline-flex;align-items:center;gap:5px;padding:6px 8px;border-radius:999px;color:#076448;background:var(--green-soft);font-size:7px;font-weight:850}.movement-type.exit{color:#922138;background:var(--red-soft)}.pdf-btn{min-height:31px;display:inline-flex;align-items:center;gap:5px;padding:0 9px;border:1px solid #efcbd2;border-radius:10px;color:var(--red);background:var(--red-soft);font-size:7px;font-weight:850;text-transform:uppercase}
        .modal-content{overflow:hidden;border:0;border-radius:24px;box-shadow:0 35px 100px rgba(5,41,79,.3)}.modal-header{padding:17px 20px;border:0;color:#fff;background:radial-gradient(circle at 90% 0,rgba(255,255,255,.12),transparent 14rem),linear-gradient(135deg,var(--primary-dark),var(--primary))}.modal-title{font-size:13px;font-weight:850}.modal-body{padding:21px}.modal-footer{padding:13px 20px;border-top:1px solid var(--border-soft);background:#f9fbfd}.form-label{display:block;margin-bottom:6px;color:#516176;font-size:8px;font-weight:850;letter-spacing:.45px;text-transform:uppercase}.form-control,.form-select{min-height:47px;border:1px solid var(--border);border-radius:14px;color:var(--text);background:var(--surface-soft);box-shadow:none;font-size:10px;font-weight:650}.form-control:focus,.form-select:focus{border-color:var(--primary-light);background:#fff;box-shadow:0 0 0 4px rgba(20,91,159,.1)}textarea.form-control{min-height:82px;padding-top:11px;resize:vertical}.modal-btn{min-height:40px;display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:0 14px;border:1px solid var(--border);border-radius:12px;color:var(--muted);background:#fff;font-size:9px;font-weight:800}.modal-btn.primary{color:#fff;border-color:var(--primary);background:var(--primary)}.modal-btn.green{color:#fff;border-color:var(--green);background:var(--green)}.movement-summary{margin-bottom:14px;padding:13px;border:1px solid var(--border);border-radius:14px;background:var(--surface-soft)}.movement-summary strong{display:block;color:var(--text);font-size:11px}.movement-summary span{display:block;margin-top:4px;color:var(--muted);font-size:8px}
        .footer{display:flex;align-items:center;justify-content:space-between;gap:15px;margin-top:14px;padding:13px 16px;border:1px solid rgba(255,255,255,.9);border-radius:17px;color:var(--light);background:rgba(255,255,255,.72);backdrop-filter:blur(14px);box-shadow:var(--shadow-sm);font-size:7px;line-height:1.5}.footer-secure{display:flex;align-items:center;gap:6px;color:var(--primary);font-weight:750}
        @media(max-width:1380px){.kpi-grid{grid-template-columns:repeat(4,1fr)}}
        @media(max-width:1050px){.header-content{align-items:flex-start;flex-direction:column}.header-side{width:100%;min-width:0;align-items:flex-start}.user-line{text-align:left}.header-actions{justify-content:flex-start}.scanner{grid-template-columns:1fr}.filters,.history-filters{grid-template-columns:1fr 1fr}.filters .search-wrap,.history-filters .search-wrap{grid-column:1/-1}.kpi-grid{grid-template-columns:repeat(2,1fr)}}
        @media(max-width:720px){.header{margin:13px 9px 0;padding:16px;border-radius:22px}.main{padding:13px 9px 27px}.header-actions{display:grid;grid-template-columns:repeat(2,1fr);width:100%}.header-btn{width:100%}.scanner{padding:18px;border-radius:24px}.scanner-input{padding-right:15px}.scanner-ready{display:none}.filters,.history-filters{grid-template-columns:1fr}.filters .search-wrap,.history-filters .search-wrap{grid-column:auto}.inventory{grid-template-columns:1fr}.table-wrap{max-height:none;overflow:visible}.history-table{min-width:0}.history-table thead{display:none}.history-table,.history-table tbody,.history-table tr,.history-table td{display:block;width:100%}.history-table tbody{padding:10px}.history-table tr.movement-row{overflow:hidden;margin-bottom:10px;border:1px solid var(--border);border-radius:18px;background:#fff;box-shadow:var(--shadow-sm)}.history-table td{display:grid;grid-template-columns:100px minmax(0,1fr);align-items:center;gap:10px;padding:10px 12px}.history-table td:before{content:attr(data-label);color:var(--light);font-size:6px;font-weight:850;letter-spacing:.5px;text-transform:uppercase}}
        @media(max-width:560px){.brand{align-items:flex-start;gap:10px}.logo{width:60px;height:60px;flex-basis:60px}.gov-label{font-size:7px}.header-subtitle{font-size:8px}.scanner h2{font-size:28px}.kpi-grid{grid-template-columns:1fr}.panel-header{align-items:flex-start}.smart-grid{grid-template-columns:1fr 1fr}.history-table td{grid-template-columns:84px minmax(0,1fr)}.footer{flex-direction:column;align-items:flex-start}}
        @media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}
    </style>
</head>
<body>
<div class="top-strip"></div>
<div class="bg-grid"></div>
<div class="orb one"></div>
<div class="orb two"></div>

<div class="app">
<header class="header">
    <div class="header-content">
        <div class="brand">
            <div class="logo">
                <div class="logo-inner">
                    <img src="assets/logo_pref.jpg" alt="Prefeitura de Extrema" onerror="this.style.display='none';this.nextElementSibling.style.display='grid';">
                    <div class="logo-fallback"><i class="bi bi-buildings-fill"></i></div>
                </div>
            </div>

            <div>
                <div class="gov-label"><i class="bi bi-shield-check"></i> Prefeitura de Extrema • Gerência de Tecnologia</div>
                <h1>Almoxarifado Inteligente de TI</h1>
                <p class="header-subtitle">Estoque rastreável, leitura por bipador e comprovantes de entrada e saída para assinatura.</p>
            </div>
        </div>

        <div class="header-side">
            <div class="user-line">
                <div>
                    <strong><?= e($greeting) ?>, <?= e($currentUser) ?></strong>
                    <span id="currentDateTime">Carregando data e horário...</span>
                </div>
                <div class="avatar"><i class="bi bi-person-fill"></i></div>
            </div>

            <nav class="header-actions">
                <button type="button" class="header-btn primary" data-bs-toggle="modal" data-bs-target="#modalNovoProduto"><i class="bi bi-plus-circle-fill"></i> Novo produto</button>
                <button type="button" class="header-btn" id="activateScanner"><i class="bi bi-upc-scan"></i> Ativar bipador</button>
                <a href="almoxarifado_inventario.php" class="header-btn">
                    <i class="bi bi-clipboard2-check-fill"></i>
                    Inventário
                </a>
                                <a href="tonner.php" class="header-btn"><i class="bi bi-printer-fill"></i> Toner</a>
                <a href="listar_os.php" class="header-btn"><i class="bi bi-arrow-left-circle-fill"></i> Ordens de serviço</a>
                <a href="dashboard.php" class="header-btn"><i class="bi bi-grid-1x2-fill"></i> Dashboard</a>
            </nav>
        </div>
    </div>
</header>

<main class="main">
    <?php if (is_array($flash)): ?>
        <div class="flash <?= e((string) $flash['type']) ?>">
            <div class="flash-icon"><i class="bi <?= $flash['type'] === 'success' ? 'bi-check-circle-fill' : 'bi-exclamation-triangle-fill' ?>"></i></div>
            <?= e((string) $flash['message']) ?>
        </div>
    <?php endif; ?>

    <section class="scanner">
        <div>
            <div class="eyebrow"><i class="bi bi-upc-scan"></i> Central de leitura rápida</div>
            <h2>Bipe o material e registre a <span>movimentação completa.</span></h2>
            <p>Selecione entrada ou saída e faça a leitura pelo bipador USB. O produto será localizado, o formulário será aberto e o comprovante ficará disponível para impressão e assinatura.</p>

            <div class="scanner-modes">
                <button type="button" class="mode-btn active" data-scanner-mode="ENTRADA"><i class="bi bi-box-arrow-in-down"></i> Entrada</button>
                <button type="button" class="mode-btn exit" data-scanner-mode="SAIDA"><i class="bi bi-box-arrow-up-right"></i> Saída</button>
            </div>

            <div class="scanner-input-wrap">
                <i class="bi bi-upc-scan"></i>
                <input type="text" id="scannerInput" class="scanner-input" placeholder="Bipe ou digite o código e pressione Enter..." autocomplete="off">
                <span class="scanner-ready"><span class="scanner-dot"></span> Leitor pronto</span>
            </div>

            <div class="scanner-result" id="scannerResult"></div>
        </div>

        <aside class="scanner-side">
            <div>
                <div class="eyebrow" style="color:#9cebd2"><i class="bi bi-file-earmark-pdf-fill"></i> Controle documental</div>
                <strong><?= count($movements) ?></strong>
                <h3>movimentações rastreáveis</h3>
                <p>Cada operação possui responsável, origem ou destino, usuário, saldo anterior, saldo final e comprovante.</p>
            </div>
            <div class="smart-line"><span></span></div>
        </aside>
    </section>

    <section class="kpi-grid">
        <article class="kpi"><div class="kpi-top"><div class="kpi-icon"><i class="bi bi-boxes"></i></div><span class="kpi-number"><?= $totalProducts ?></span></div><span class="kpi-label">Produtos cadastrados</span><small>Itens diferentes no inventário.</small></article>
        <article class="kpi"><div class="kpi-top"><div class="kpi-icon"><i class="bi bi-stack"></i></div><span class="kpi-number"><?= $totalUnits ?></span></div><span class="kpi-label">Total de unidades</span><small>Soma física registrada.</small></article>
        <article class="kpi green"><div class="kpi-top"><div class="kpi-icon"><i class="bi bi-check-circle-fill"></i></div><span class="kpi-number"><?= $healthy ?></span></div><span class="kpi-label">Estoque saudável</span><small>Acima da faixa de atenção.</small></article>
        <article class="kpi yellow"><div class="kpi-top"><div class="kpi-icon"><i class="bi bi-exclamation-triangle-fill"></i></div><span class="kpi-number"><?= $low ?></span></div><span class="kpi-label">Estoque baixo</span><small>Próximos do mínimo.</small></article>
        <article class="kpi red"><div class="kpi-top"><div class="kpi-icon"><i class="bi bi-exclamation-octagon-fill"></i></div><span class="kpi-number"><?= $critical + $empty ?></span></div><span class="kpi-label">Críticos ou zerados</span><small>Reposição prioritária.</small></article>
        <article class="kpi green"><div class="kpi-top"><div class="kpi-icon"><i class="bi bi-box-arrow-in-down"></i></div><span class="kpi-number"><?= $entriesToday ?></span></div><span class="kpi-label">Entradas hoje</span><small>Unidades recebidas no dia.</small></article>
        <article class="kpi red"><div class="kpi-top"><div class="kpi-icon"><i class="bi bi-box-arrow-up-right"></i></div><span class="kpi-number"><?= $exitsToday ?></span></div><span class="kpi-label">Saídas hoje</span><small>Unidades entregues no dia.</small></article>
    </section>

    <section class="panel">
        <div class="panel-header">
            <div class="panel-title">
                <div class="panel-title-icon"><i class="bi bi-box-seam-fill"></i></div>
                <div><h2>Inventário inteligente</h2><p>Estoque, consumo em 30 dias, cobertura e sugestão de compra.</p></div>
            </div>
            <span class="counter"><i class="bi bi-database-fill"></i> <span id="visibleItemCount"><?= $totalProducts ?></span> produtos</span>
        </div>

        <div class="filters">
            <div class="search-wrap"><i class="bi bi-search"></i><input type="search" id="itemSearch" class="search-input" placeholder="Pesquisar produto, marca, modelo, código ou localização..."></div>
            <select id="statusFilter" class="filter-select"><option value="">Todos os níveis</option><option value="healthy">Saudável</option><option value="low">Baixo</option><option value="critical">Crítico</option><option value="empty">Sem estoque</option></select>
            <select id="categoryFilter" class="filter-select"><option value="">Todas as categorias</option><?php foreach ($categories as $category => $_): ?><option value="<?= e($category) ?>"><?= e($category) ?></option><?php endforeach; ?></select>
            <button type="button" class="clear-btn" id="clearItemFilters"><i class="bi bi-arrow-counterclockwise"></i> Limpar</button>
        </div>

        <div class="inventory">
            <?php if (empty($items)): ?><div class="empty-state"><i class="bi bi-inbox-fill"></i>Nenhum produto cadastrado.</div><?php endif; ?>

            <?php foreach ($items as $item): ?>
                <?php
                    $quantity = (int) $item['quantidade'];
                    $minimum = (int) $item['minimo'];
                    $consumption = (int) $item['saidas_30_dias'];
                    $status = stockStatus($quantity, $minimum);
                    $dailyAverage = $consumption > 0 ? $consumption / 30 : 0;
                    $coverage = $dailyAverage > 0 ? (int) floor($quantity / $dailyAverage) : null;
                    $ideal = max($minimum + 5, $consumption, max(1, $minimum * 2));
                    $buy = max(0, $ideal - $quantity);
                    $percent = min(100, max(0, (int) round(($quantity / max(1, $ideal)) * 100)));
                    $searchText = lowerText(implode(' ', [$item['nome'], $item['categoria'], $item['marca'] ?? '', $item['modelo'] ?? '', $item['codigo_barras'] ?? '', $item['localizacao'] ?? '']));
                ?>

                <article class="item-card <?= e($status['code']) ?>" data-item-card data-search="<?= e($searchText) ?>" data-status="<?= e($status['code']) ?>" data-category="<?= e((string) $item['categoria']) ?>">
                    <div class="item-top">
                        <div><h3 class="item-title"><?= e((string) $item['nome']) ?></h3><div class="item-meta"><?= e((string) ($item['marca'] ?: 'Sem marca')) ?><?= $item['modelo'] ? ' / ' . e((string) $item['modelo']) : '' ?></div></div>
                        <span class="status <?= e($status['code']) ?>"><i class="bi <?= e($status['icon']) ?>"></i><?= e($status['label']) ?></span>
                    </div>

                    <div class="item-tags">
                        <span class="tag"><i class="bi bi-tag-fill"></i><?= e((string) $item['categoria']) ?></span>
                        <span class="tag"><i class="bi bi-geo-alt-fill"></i><?= e((string) ($item['localizacao'] ?: 'Sem localização')) ?></span>
                        <?php if (!empty($item['codigo_barras'])): ?><span class="tag"><i class="bi bi-upc-scan"></i><?= e((string) $item['codigo_barras']) ?></span><?php endif; ?>
                    </div>

                    <div class="stock"><strong><?= $quantity ?></strong><span>unidades disponíveis</span></div>

                    <div class="smart-grid">
                        <div class="smart"><span>Mínimo</span><strong><?= $minimum ?> un.</strong></div>
                        <div class="smart"><span>Saídas 30 dias</span><strong><?= $consumption ?> un.</strong></div>
                        <div class="smart"><span>Cobertura</span><strong><?= $coverage !== null ? $coverage . ' dias' : 'Sem média' ?></strong></div>
                        <div class="smart"><span>Comprar</span><strong><?= $buy > 0 ? $buy . ' un.' : 'Não necessário' ?></strong></div>
                        <div class="smart"><span>Localização</span><strong><?= e((string) ($item['localizacao'] ?: 'N/I')) ?></strong></div>
                        <div class="smart"><span>Último registro</span><strong><?= !empty($item['ultima_movimentacao_em']) ? date('d/m H:i', strtotime((string) $item['ultima_movimentacao_em'])) : 'Sem movimento' ?></strong></div>
                    </div>

                    <div class="progress-line"><span style="width:<?= $percent ?>%"></span></div>

                    <div class="item-actions">
                        <button type="button" class="item-btn entry" onclick="openMovement(<?= (int) $item['id'] ?>,'ENTRADA')"><i class="bi bi-plus-lg"></i>Entrada</button>
                        <button type="button" class="item-btn exit" onclick="openMovement(<?= (int) $item['id'] ?>,'SAIDA')" <?= $quantity <= 0 ? 'disabled' : '' ?>><i class="bi bi-dash-lg"></i>Saída</button>
                        <button type="button" class="item-btn edit" title="Editar" onclick="openEdit(<?= (int) $item['id'] ?>)"><i class="bi bi-pencil-fill"></i></button>
                    </div>
                </article>
            <?php endforeach; ?>

            <div class="empty-state" id="itemSearchEmpty" style="display:none"><i class="bi bi-search"></i>Nenhum produto corresponde aos filtros.</div>
        </div>
    </section>

    <section class="panel">
        <div class="panel-header">
            <div class="panel-title"><div class="panel-title-icon"><i class="bi bi-clock-history"></i></div><div><h2>Histórico e comprovantes</h2><p>Entradas e saídas com saldo anterior, saldo final e documento para assinatura.</p></div></div>
            <span class="counter"><i class="bi bi-file-earmark-text-fill"></i> <span id="visibleMovementCount"><?= count($movements) ?></span> registros</span>
        </div>

        <div class="history-filters">
            <div class="search-wrap"><i class="bi bi-search"></i><input type="search" id="movementSearch" class="search-input" placeholder="Pesquisar produto, responsável, destino ou documento..."></div>
            <select id="movementTypeFilter" class="filter-select"><option value="">Entrada e saída</option><option value="ENTRADA">Entradas</option><option value="SAIDA">Saídas</option></select>
            <select id="movementPeriodFilter" class="filter-select"><option value="">Todo o período</option><option value="today">Hoje</option><option value="7">Últimos 7 dias</option><option value="30">Últimos 30 dias</option></select>
            <button type="button" class="clear-btn" id="clearMovementFilters"><i class="bi bi-arrow-counterclockwise"></i>Limpar</button>
        </div>

        <div class="table-wrap">
            <table class="history-table">
                <thead><tr><th>Movimento</th><th>Produto</th><th>Data</th><th>Responsável</th><th>Origem / destino</th><th>Quantidade</th><th>Saldo</th><th>Usuário</th><th>Comprovante</th></tr></thead>
                <tbody>
                    <?php if (empty($movements)): ?><tr><td colspan="9"><div class="empty-state"><i class="bi bi-inbox-fill"></i>Nenhuma movimentação registrada.</div></td></tr><?php endif; ?>
                    <?php foreach ($movements as $movement): ?>
                        <?php $timestamp = strtotime((string) $movement['criado_em']); $movementSearch = lowerText(implode(' ', [$movement['nome'], $movement['categoria'], $movement['responsavel'], $movement['origem_destino'], $movement['documento'] ?? '', $movement['usuario_sistema'] ?? ''])); ?>
                        <tr class="movement-row" data-movement-row data-search="<?= e($movementSearch) ?>" data-type="<?= e((string) $movement['tipo']) ?>" data-date="<?= e(date('Y-m-d', $timestamp)) ?>">
                            <td data-label="Movimento"><span class="movement-type <?= $movement['tipo'] === 'SAIDA' ? 'exit' : '' ?>"><i class="bi <?= $movement['tipo'] === 'ENTRADA' ? 'bi-box-arrow-in-down' : 'bi-box-arrow-up-right' ?>"></i><?= e((string) $movement['tipo']) ?></span></td>
                            <td data-label="Produto"><strong><?= e((string) $movement['nome']) ?></strong><div class="text-muted" style="font-size:7px"><?= e((string) $movement['categoria']) ?></div></td>
                            <td data-label="Data"><strong><?= date('d/m/Y', $timestamp) ?></strong><div class="text-muted" style="font-size:7px"><?= date('H:i', $timestamp) ?></div></td>
                            <td data-label="Responsável"><?= e((string) $movement['responsavel']) ?></td>
                            <td data-label="Origem / destino"><?= e((string) $movement['origem_destino']) ?></td>
                            <td data-label="Quantidade"><strong><?= (int) $movement['quantidade'] ?> un.</strong></td>
                            <td data-label="Saldo"><?= (int) $movement['estoque_anterior'] ?> <i class="bi bi-arrow-right mx-1"></i> <strong><?= (int) $movement['estoque_posterior'] ?></strong></td>
                            <td data-label="Usuário"><?= e((string) ($movement['usuario_sistema'] ?: 'N/I')) ?></td>
                            <td data-label="Comprovante"><a href="comprovante_movimentacao.php?id=<?= (int) $movement['id'] ?>" target="_blank" class="pdf-btn"><i class="bi bi-file-earmark-pdf-fill"></i>PDF</a></td>
                        </tr>
                    <?php endforeach; ?>
                    <tr id="movementEmptyResult" style="display:none"><td colspan="9"><div class="empty-state"><i class="bi bi-search"></i>Nenhuma movimentação corresponde aos filtros.</div></td></tr>
                </tbody>
            </table>
        </div>
    </section>

    <footer class="footer"><span>Prefeitura de Extrema — Gerência de Tecnologia<br>Controle institucional de materiais, suprimentos e equipamentos.</span><span class="footer-secure"><i class="bi bi-shield-lock-fill"></i>Movimentações auditáveis e comprovadas</span></footer>
</main>
</div>

<!-- NOVO PRODUTO -->
<div class="modal fade" id="modalNovoProduto" tabindex="-1">
    <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
        <form method="POST" class="modal-content ajax-form" data-open-receipt="true">
            <div class="modal-header"><h5 class="modal-title"><i class="bi bi-plus-circle-fill me-2"></i>Cadastrar produto</h5><button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button></div>
            <div class="modal-body">
                <input type="hidden" name="acao" value="cadastrar"><input type="hidden" name="ajax" value="1">
                <div class="row g-3">
                    <div class="col-md-8"><label class="form-label">Nome do produto</label><input type="text" name="nome" class="form-control" placeholder="Ex.: Mouse USB, SSD, cabo de rede..." maxlength="150" required></div>
                    <div class="col-md-4"><label class="form-label">Categoria</label><input type="text" name="categoria" class="form-control" list="categoryList" placeholder="Ex.: Periféricos" maxlength="100" required><datalist id="categoryList"><?php foreach ($categories as $category => $_): ?><option value="<?= e($category) ?>"><?php endforeach; ?></datalist></div>
                    <div class="col-md-4"><label class="form-label">Marca</label><input type="text" name="marca" class="form-control" maxlength="100"></div>
                    <div class="col-md-4"><label class="form-label">Modelo</label><input type="text" name="modelo" class="form-control" maxlength="100"></div>
                    <div class="col-md-4"><label class="form-label">Código de barras</label><input type="text" name="codigo_barras" class="form-control" placeholder="Bipe ou digite" maxlength="120"></div>
                    <div class="col-md-4"><label class="form-label">Quantidade inicial</label><input type="number" name="quantidade" class="form-control" min="0" value="0" required></div>
                    <div class="col-md-4"><label class="form-label">Estoque mínimo</label><input type="number" name="minimo" class="form-control" min="0" value="1" required></div>
                    <div class="col-md-4"><label class="form-label">Localização</label><input type="text" name="localizacao" class="form-control" placeholder="Armário / prateleira" maxlength="150"></div>
                    <div class="col-md-6"><label class="form-label">Responsável pelo recebimento</label><input type="text" name="responsavel" class="form-control" placeholder="Obrigatório se houver quantidade inicial" maxlength="160"></div>
                    <div class="col-md-6"><label class="form-label">Origem / fornecedor</label><input type="text" name="origem_destino" class="form-control" placeholder="Fornecedor, setor ou servidor" maxlength="190"></div>
                    <div class="col-md-5"><label class="form-label">Documento</label><input type="text" name="documento" class="form-control" placeholder="NF, termo, requisição..." maxlength="100"></div>
                    <div class="col-md-7"><label class="form-label">Observação</label><input type="text" name="observacao" class="form-control" maxlength="255"></div>
                </div>
                <div class="alert alert-info border-0 rounded-4 mt-3 mb-0" style="font-size:10px"><i class="bi bi-file-earmark-pdf-fill me-1"></i>Quando houver quantidade inicial, o sistema registrará uma entrada e abrirá o comprovante.</div>
            </div>
            <div class="modal-footer"><button type="button" class="modal-btn" data-bs-dismiss="modal">Cancelar</button><button type="submit" class="modal-btn green"><i class="bi bi-check-circle-fill"></i>Cadastrar</button></div>
        </form>
    </div>
</div>

<!-- MOVIMENTAÇÃO -->
<div class="modal fade" id="modalMovimentacao" tabindex="-1">
    <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
        <form method="POST" class="modal-content ajax-form" data-open-receipt="true" id="movementForm">
            <div class="modal-header"><h5 class="modal-title" id="movementModalTitle">Registrar movimentação</h5><button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button></div>
            <div class="modal-body">
                <input type="hidden" name="acao" value="movimentar"><input type="hidden" name="ajax" value="1"><input type="hidden" name="item_id" id="movementItemId"><input type="hidden" name="tipo" id="movementType">
                <div class="movement-summary" id="movementSummary"></div>
                <div class="row g-3">
                    <div class="col-5"><label class="form-label">Quantidade</label><input type="number" name="quantidade" id="movementQuantity" class="form-control" min="1" value="1" required></div>
                    <div class="col-7"><label class="form-label">Documento / requisição</label><input type="text" name="documento" class="form-control" placeholder="Opcional" maxlength="100"></div>
                    <div class="col-12"><label class="form-label" id="responsibleLabel">Responsável</label><input type="text" name="responsavel" class="form-control" placeholder="Nome completo" maxlength="160" required></div>
                    <div class="col-12"><label class="form-label" id="originDestinationLabel">Origem / destino</label><input type="text" name="origem_destino" class="form-control" placeholder="Setor, secretaria, fornecedor ou servidor" maxlength="190" required></div>
                    <div class="col-12"><label class="form-label">Finalidade / observação</label><textarea name="observacao" class="form-control" maxlength="255" placeholder="Descreva a finalidade da movimentação..."></textarea></div>
                </div>
                <div class="alert alert-light border rounded-4 mt-3 mb-0" style="font-size:9px"><i class="bi bi-pen-fill me-1"></i>Após confirmar, o comprovante será aberto para impressão e assinatura.</div>
            </div>
            <div class="modal-footer"><button type="button" class="modal-btn" data-bs-dismiss="modal">Cancelar</button><button type="submit" class="modal-btn primary" id="movementSubmit"><i class="bi bi-check-circle-fill"></i>Confirmar</button></div>
        </form>
    </div>
</div>

<!-- EDIÇÃO -->
<div class="modal fade" id="modalEdicao" tabindex="-1">
    <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
        <form method="POST" class="modal-content ajax-form" data-open-receipt="false">
            <div class="modal-header"><h5 class="modal-title"><i class="bi bi-pencil-square me-2"></i>Editar produto</h5><button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button></div>
            <div class="modal-body">
                <input type="hidden" name="acao" value="editar"><input type="hidden" name="ajax" value="1"><input type="hidden" name="item_id" id="editItemId">
                <div class="row g-3">
                    <div class="col-md-8"><label class="form-label">Nome</label><input type="text" name="nome" id="editName" class="form-control" required></div>
                    <div class="col-md-4"><label class="form-label">Categoria</label><input type="text" name="categoria" id="editCategory" class="form-control" required></div>
                    <div class="col-md-4"><label class="form-label">Marca</label><input type="text" name="marca" id="editBrand" class="form-control"></div>
                    <div class="col-md-4"><label class="form-label">Modelo</label><input type="text" name="modelo" id="editModel" class="form-control"></div>
                    <div class="col-md-4"><label class="form-label">Código de barras</label><input type="text" name="codigo_barras" id="editBarcode" class="form-control"></div>
                    <div class="col-md-4"><label class="form-label">Estoque mínimo</label><input type="number" name="minimo" id="editMinimum" class="form-control" min="0" required></div>
                    <div class="col-md-8"><label class="form-label">Localização</label><input type="text" name="localizacao" id="editLocation" class="form-control"></div>
                </div>
            </div>
            <div class="modal-footer"><button type="button" class="modal-btn" data-bs-dismiss="modal">Cancelar</button><button type="submit" class="modal-btn primary"><i class="bi bi-floppy-fill"></i>Salvar</button></div>
        </form>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
const inventoryItems = <?= $itemsJson ?: '[]' ?>;
let scannerMode = 'ENTRADA';
let audioContext = null;

function normalizeText(value) {
    return String(value ?? '').normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase().trim();
}

function escapeHtml(value) {
    const div = document.createElement('div');
    div.textContent = String(value ?? '');
    return div.innerHTML;
}

function findById(id) {
    return inventoryItems.find(item => Number(item.id) === Number(id));
}

function findByBarcode(code) {
    const normalized = normalizeText(code);
    return inventoryItems.find(item => item.codigo_barras && normalizeText(item.codigo_barras) === normalized);
}

function getAudio() {
    if (!audioContext) {
        const AudioClass = window.AudioContext || window.webkitAudioContext;
        if (AudioClass) audioContext = new AudioClass();
    }
    return audioContext;
}

function beep(type = 'success') {
    const context = getAudio();
    if (!context) return;
    if (context.state === 'suspended') context.resume();

    const oscillator = context.createOscillator();
    const gain = context.createGain();
    const now = context.currentTime;

    oscillator.connect(gain);
    gain.connect(context.destination);

    if (type === 'error') {
        oscillator.frequency.setValueAtTime(190, now);
        oscillator.frequency.setValueAtTime(145, now + .12);
    } else {
        oscillator.frequency.setValueAtTime(650, now);
        oscillator.frequency.setValueAtTime(880, now + .08);
    }

    gain.gain.setValueAtTime(.0001, now);
    gain.gain.exponentialRampToValueAtTime(.18, now + .015);
    gain.gain.exponentialRampToValueAtTime(.0001, now + .22);
    oscillator.start(now);
    oscillator.stop(now + .24);
}

document.querySelectorAll('[data-scanner-mode]').forEach(button => {
    button.addEventListener('click', () => {
        scannerMode = button.dataset.scannerMode;
        document.querySelectorAll('[data-scanner-mode]').forEach(item => item.classList.remove('active'));
        button.classList.add('active');
        document.getElementById('scannerInput')?.focus();
    });
});

document.getElementById('activateScanner')?.addEventListener('click', () => {
    const input = document.getElementById('scannerInput');
    input?.focus();
    input?.select();
    beep('success');
});

document.getElementById('scannerInput')?.addEventListener('keydown', event => {
    if (event.key !== 'Enter') return;
    event.preventDefault();

    const input = event.currentTarget;
    const code = input.value.trim();
    const result = document.getElementById('scannerResult');
    const item = findByBarcode(code);

    if (!item) {
        beep('error');
        result.className = 'scanner-result visible error';
        result.innerHTML = `<i class="bi bi-x-octagon-fill me-1"></i>Código <strong>${escapeHtml(code)}</strong> não encontrado. Cadastre-o na edição do produto.`;
        input.select();
        return;
    }

    if (scannerMode === 'SAIDA' && Number(item.quantidade) <= 0) {
        beep('error');
        result.className = 'scanner-result visible error';
        result.innerHTML = `<i class="bi bi-exclamation-octagon-fill me-1"></i><strong>${escapeHtml(item.nome)}</strong> está sem estoque.`;
        return;
    }

    beep('success');
    result.className = 'scanner-result visible success';
    result.innerHTML = `<i class="bi bi-check-circle-fill me-1"></i>Produto localizado: <strong>${escapeHtml(item.nome)}</strong>. Estoque atual: <strong>${Number(item.quantidade)} unidade(s)</strong>.`;
    openMovement(item.id, scannerMode);
});

function openMovement(itemId, type) {
    const item = findById(itemId);
    if (!item) return;

    if (type === 'SAIDA' && Number(item.quantidade) <= 0) {
        beep('error');
        alert('Este produto está sem estoque.');
        return;
    }

    const isEntry = type === 'ENTRADA';
    const quantityInput = document.getElementById('movementQuantity');

    document.getElementById('movementItemId').value = item.id;
    document.getElementById('movementType').value = type;
    quantityInput.value = 1;
    quantityInput.removeAttribute('max');
    if (!isEntry) quantityInput.max = String(item.quantidade);

    document.getElementById('movementModalTitle').innerHTML = `<i class="bi ${isEntry ? 'bi-box-arrow-in-down' : 'bi-box-arrow-up-right'} me-2"></i>Registrar ${isEntry ? 'entrada' : 'saída'}`;
    document.getElementById('movementSummary').innerHTML = `<strong>${escapeHtml(item.nome)}</strong><span>Categoria: ${escapeHtml(item.categoria)} • Estoque atual: ${Number(item.quantidade)} unidade(s) • Local: ${escapeHtml(item.localizacao || 'Não informado')}</span>`;
    document.getElementById('responsibleLabel').textContent = isEntry ? 'Responsável pelo recebimento' : 'Responsável pela retirada';
    document.getElementById('originDestinationLabel').textContent = isEntry ? 'Origem / fornecedor' : 'Destino / setor solicitante';

    const submit = document.getElementById('movementSubmit');
    submit.className = `modal-btn ${isEntry ? 'green' : 'primary'}`;
    submit.innerHTML = `<i class="bi bi-check-circle-fill"></i>Confirmar ${isEntry ? 'entrada' : 'saída'}`;

    bootstrap.Modal.getOrCreateInstance(document.getElementById('modalMovimentacao')).show();
}

function openEdit(itemId) {
    const item = findById(itemId);
    if (!item) return;

    document.getElementById('editItemId').value = item.id;
    document.getElementById('editName').value = item.nome;
    document.getElementById('editCategory').value = item.categoria;
    document.getElementById('editBrand').value = item.marca;
    document.getElementById('editModel').value = item.modelo;
    document.getElementById('editBarcode').value = item.codigo_barras;
    document.getElementById('editMinimum').value = item.minimo;
    document.getElementById('editLocation').value = item.localizacao;

    bootstrap.Modal.getOrCreateInstance(document.getElementById('modalEdicao')).show();
}

async function submitAjaxForm(form) {
    const submitButton = form.querySelector('[type="submit"]');
    const originalHtml = submitButton?.innerHTML;

    if (submitButton) {
        submitButton.disabled = true;
        submitButton.innerHTML = '<span class="spinner-border spinner-border-sm"></span> Processando...';
    }

    try {
        const response = await fetch('almoxarifado.php', {
            method: 'POST',
            headers: {'X-Requested-With': 'XMLHttpRequest'},
            body: new FormData(form)
        });

        const data = await response.json();

        if (!data.ok) {
            beep('error');
            alert(data.message || 'Não foi possível concluir a operação.');
            return;
        }

        beep('success');

        if (data.receipt_id) {
            window.open(`comprovante_movimentacao.php?id=${encodeURIComponent(data.receipt_id)}&print=1`, '_blank');
        }

        alert(data.message || 'Operação concluída.');
        window.location.reload();
    } catch (error) {
        beep('error');
        alert('Erro de comunicação com o servidor.');
    } finally {
        if (submitButton) {
            submitButton.disabled = false;
            submitButton.innerHTML = originalHtml;
        }
    }
}

document.querySelectorAll('.ajax-form').forEach(form => {
    form.addEventListener('submit', event => {
        event.preventDefault();
        submitAjaxForm(form);
    });
});

const itemSearch = document.getElementById('itemSearch');
const statusFilter = document.getElementById('statusFilter');
const categoryFilter = document.getElementById('categoryFilter');

function filterItems() {
    const term = normalizeText(itemSearch?.value);
    const status = statusFilter?.value || '';
    const category = categoryFilter?.value || '';
    const cards = [...document.querySelectorAll('[data-item-card]')];
    let visible = 0;

    cards.forEach(card => {
        const show = (!term || normalizeText(card.dataset.search).includes(term))
            && (!status || card.dataset.status === status)
            && (!category || card.dataset.category === category);
        card.style.display = show ? '' : 'none';
        if (show) visible++;
    });

    document.getElementById('visibleItemCount').textContent = visible;
    document.getElementById('itemSearchEmpty').style.display = visible === 0 && cards.length ? '' : 'none';
}

itemSearch?.addEventListener('input', filterItems);
statusFilter?.addEventListener('change', filterItems);
categoryFilter?.addEventListener('change', filterItems);
document.getElementById('clearItemFilters')?.addEventListener('click', () => {
    itemSearch.value = '';
    statusFilter.value = '';
    categoryFilter.value = '';
    filterItems();
    itemSearch.focus();
});

const movementSearch = document.getElementById('movementSearch');
const movementTypeFilter = document.getElementById('movementTypeFilter');
const movementPeriodFilter = document.getElementById('movementPeriodFilter');

function filterMovements() {
    const term = normalizeText(movementSearch?.value);
    const type = movementTypeFilter?.value || '';
    const period = movementPeriodFilter?.value || '';
    const rows = [...document.querySelectorAll('[data-movement-row]')];
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    let visible = 0;

    rows.forEach(row => {
        const rowDate = new Date(`${row.dataset.date}T00:00:00`);
        let matchPeriod = true;

        if (period === 'today') {
            matchPeriod = rowDate.getTime() === today.getTime();
        } else if (period) {
            const limit = new Date(today);
            limit.setDate(limit.getDate() - Number(period));
            matchPeriod = rowDate >= limit;
        }

        const show = (!term || normalizeText(row.dataset.search).includes(term))
            && (!type || row.dataset.type === type)
            && matchPeriod;

        row.style.display = show ? '' : 'none';
        if (show) visible++;
    });

    document.getElementById('visibleMovementCount').textContent = visible;
    document.getElementById('movementEmptyResult').style.display = visible === 0 && rows.length ? '' : 'none';
}

movementSearch?.addEventListener('input', filterMovements);
movementTypeFilter?.addEventListener('change', filterMovements);
movementPeriodFilter?.addEventListener('change', filterMovements);
document.getElementById('clearMovementFilters')?.addEventListener('click', () => {
    movementSearch.value = '';
    movementTypeFilter.value = '';
    movementPeriodFilter.value = '';
    filterMovements();
    movementSearch.focus();
});

function updateClock() {
    const now = new Date();
    const date = now.toLocaleDateString('pt-BR', {weekday:'long',day:'2-digit',month:'long',year:'numeric'});
    const time = now.toLocaleTimeString('pt-BR', {hour:'2-digit',minute:'2-digit',second:'2-digit'});
    const element = document.getElementById('currentDateTime');
    if (element) element.textContent = date.charAt(0).toUpperCase() + date.slice(1) + ' • ' + time;
}

updateClock();
setInterval(updateClock, 1000);
</script>
</body>
</html>
