<?php
declare(strict_types=1);

require_once __DIR__ . '/auth.php';
require_once __DIR__ . '/conexao.php';
require_once __DIR__ . '/alerta_global_helpers.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 responder(array $dados, int $status = 200): never
{
    http_response_code($status);
    header('Content-Type: application/json; charset=utf-8');
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');

    echo json_encode(
        $dados,
        JSON_UNESCAPED_UNICODE |
        JSON_UNESCAPED_SLASHES |
        JSON_HEX_TAG |
        JSON_HEX_APOS |
        JSON_HEX_QUOT |
        JSON_HEX_AMP
    );

    exit;
}

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

function normalizar(string $texto): string
{
    $texto = trim(minusculo($texto));

    $texto = strtr($texto, [
        'á' => 'a', 'à' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a',
        'é' => 'e', 'è' => 'e', 'ê' => 'e', 'ë' => 'e',
        'í' => 'i', 'ì' => 'i', 'î' => 'i', 'ï' => 'i',
        'ó' => 'o', 'ò' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o',
        'ú' => 'u', 'ù' => 'u', 'û' => 'u', 'ü' => 'u',
        'ç' => 'c'
    ]);

    return preg_replace('/\s+/u', ' ', $texto) ?? $texto;
}

function compacto(string $texto): string
{
    return preg_replace('/[^a-z0-9]+/i', '', normalizar($texto)) ?? '';
}

function limitarTexto(string $texto, int $limite = 220): string
{
    $texto = trim(preg_replace('/\s+/u', ' ', $texto) ?? $texto);

    if ($texto === '') {
        return '';
    }

    $tamanho = function_exists('mb_strlen')
        ? mb_strlen($texto, 'UTF-8')
        : strlen($texto);

    if ($tamanho <= $limite) {
        return $texto;
    }

    $corte = function_exists('mb_substr')
        ? mb_substr($texto, 0, $limite - 1, 'UTF-8')
        : substr($texto, 0, $limite - 1);

    return rtrim($corte) . '…';
}

function codigoStatus(string $status): string
{
    $normalizado = normalizar($status);

    if (str_contains($normalizado, 'finaliz')) {
        return 'finalizado';
    }

    if (
        str_contains($normalizado, 'pendente') &&
        str_contains($normalizado, 'retirada')
    ) {
        return 'pendente_retirada';
    }

    return 'em_andamento';
}

function dataFormatada(?string $data): string
{
    $data = trim((string) $data);

    if ($data === '') {
        return '';
    }

    $timestamp = strtotime($data);

    return $timestamp !== false
        ? date('d/m/Y H:i', $timestamp)
        : $data;
}


function rastreadorTabelaExiste(
    mysqli $mysqli,
    string $tabela
): bool {
    $nome = $mysqli->real_escape_string($tabela);
    $resultado = $mysqli->query("SHOW TABLES LIKE '{$nome}'");

    return $resultado instanceof mysqli_result &&
        $resultado->num_rows > 0;
}

function rastreadorStatusComputador(string $status): string
{
    return match (strtoupper(trim($status))) {
        'EM_USO' => 'Em uso',
        'DISPONIVEL' => 'Disponível',
        'MANUTENCAO' => 'Em manutenção',
        'RESERVA' => 'Reserva técnica',
        'EXTRAVIADO' => 'Extraviado',
        'AGUARDANDO_BAIXA' => 'Aguardando baixa',
        'BAIXADO' => 'Baixado',
        default => 'Cadastro inicial'
    };
}

function bindDinamico(mysqli_stmt $stmt, array &$valores): void
{
    if (!$valores) {
        return;
    }

    $tipos = str_repeat('s', count($valores));
    $parametros = [$tipos];

    foreach ($valores as $indice => &$valor) {
        $parametros[] = &$valor;
    }
    unset($valor);

    if (!call_user_func_array([$stmt, 'bind_param'], $parametros)) {
        throw new RuntimeException('Não foi possível preparar os critérios da pesquisa.');
    }
}


if (empty($_SESSION['csrf_rastreador_os'])) {
    $_SESSION['csrf_rastreador_os'] =
        bin2hex(random_bytes(24));
}

$csrfRastreador =
    (string) $_SESSION['csrf_rastreador_os'];

$usuarioLogado = alertaUsuarioAtual();
$usuarioPodeGerenciarAlerta =
    alertaUsuarioEhAdmin();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$tokenRecebido = (string) ($_POST['csrf_token'] ?? '');
$tokenSessao = (string) ($_SESSION['csrf_rastreador_os'] ?? '');

if (
    $tokenRecebido === '' ||
    $tokenSessao === '' ||
    !hash_equals($tokenSessao, $tokenRecebido)
) {
    responder([
        'ok' => false,
        'message' => 'A sessão expirou. Atualize a página e tente novamente.'
    ], 419);
}

$termo = trim((string) ($_POST['termo'] ?? ''));

$tamanhoTermo = function_exists('mb_strlen')
    ? mb_strlen($termo, 'UTF-8')
    : strlen($termo);

if ($tamanhoTermo < 2) {
    responder([
        'ok' => false,
        'message' => 'Informe pelo menos dois caracteres para pesquisar.'
    ], 422);
}

if ($tamanhoTermo > 120) {
    responder([
        'ok' => false,
        'message' => 'A pesquisa deve possuir no máximo 120 caracteres.'
    ], 422);
}

$resultadoColunas = $mysqli->query('SHOW COLUMNS FROM ordens_servico');

if (!$resultadoColunas) {
    responder([
        'ok' => false,
        'message' => 'Não foi possível identificar os campos das ordens de serviço.'
    ], 500);
}

$colunasExistentes = [];

while ($coluna = $resultadoColunas->fetch_assoc()) {
    $nome = (string) ($coluna['Field'] ?? '');

    if ($nome !== '') {
        $colunasExistentes[$nome] = true;
    }
}

$resultadoColunas->free();

$candidatas = [
    'id' => 'Código interno',
    'numero_os' => 'Número da OS',
    'nome_solicitante' => 'Solicitante',
    'telefone' => 'Telefone / ramal',
    'setor' => 'Setor',
    'tipo_equipamento' => 'Equipamento',
    'marca' => 'Marca',
    'modelo' => 'Modelo',
    'patrimonio' => 'Patrimônio',
    'numero_serie' => 'Número de série',
    'problema' => 'Problema informado',
    'solucao' => 'Solução técnica',
    'tecnico' => 'Técnico',
    'responsavel_retirada' => 'Responsável pela retirada',
    'status' => 'Status',
    'prioridade' => 'Prioridade',
    'data_entrada' => 'Data de entrada',
    'data_finalizacao' => 'Data de finalização'
];

$camposPesquisa = [];

foreach ($candidatas as $campo => $rotulo) {
    if (isset($colunasExistentes[$campo])) {
        $camposPesquisa[$campo] = $rotulo;
    }
}

if (!$camposPesquisa) {
    responder([
        'ok' => false,
        'message' => 'Nenhum campo pesquisável foi encontrado.'
    ], 500);
}

$termoNormalizado = normalizar($termo);
$termoCompacto = compacto($termo);

$tokens = preg_split('/\s+/u', $termoNormalizado) ?: [];
$tokens = array_values(array_unique(array_filter(
    $tokens,
    static fn(string $token): bool => strlen($token) >= 2
)));

if (!$tokens) {
    $tokens = [$termoNormalizado];
}

$tokens = array_slice($tokens, 0, 6);

$camposCompactos = array_values(array_intersect(
    ['numero_os', 'telefone', 'patrimonio', 'numero_serie'],
    array_keys($camposPesquisa)
));

$grupos = [];
$valores = [];

foreach ($tokens as $token) {
    $ors = [];

    foreach ($camposPesquisa as $campo => $_rotulo) {
        $ors[] = "CAST(COALESCE(`{$campo}`, '') AS CHAR) LIKE ?";
        $valores[] = '%' . $token . '%';
    }

    $tokenCompacto = compacto($token);

    if (strlen($tokenCompacto) >= 3) {
        foreach ($camposCompactos as $campo) {
            $expressao = "REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(CAST(COALESCE(`{$campo}`, '') AS CHAR), ' ', ''), '.', ''), '-', ''), '/', ''), '(', ''), ')', ''), '+', '')";

            $ors[] = $expressao . ' LIKE ?';
            $valores[] = '%' . $tokenCompacto . '%';
        }
    }

    $grupos[] = '(' . implode(' OR ', $ors) . ')';
}

$selectCampos = array_map(
    static fn(string $campo): string => "`{$campo}`",
    array_keys($camposPesquisa)
);

if (!isset($camposPesquisa['id'])) {
    array_unshift($selectCampos, '`id`');
}

$sql = "
    SELECT " . implode(', ', $selectCampos) . "
    FROM ordens_servico
    WHERE " . implode(' AND ', $grupos) . "
    ORDER BY " . (
        isset($colunasExistentes['data_entrada'])
            ? '`data_entrada` DESC, '
            : ''
    ) . "`id` DESC
    LIMIT 120
";

$stmt = $mysqli->prepare($sql);

if (!$stmt) {
    responder([
        'ok' => false,
        'message' => 'Não foi possível preparar a pesquisa no histórico.'
    ], 500);
}

try {
    bindDinamico($stmt, $valores);
    $stmt->execute();

    $linhas = $stmt
        ->get_result()
        ->fetch_all(MYSQLI_ASSOC);

    $stmt->close();
} catch (Throwable $erro) {
    $stmt->close();

    responder([
        'ok' => false,
        'message' => $erro->getMessage()
    ], 500);
}

$resultados = [];

foreach ($linhas as $linha) {
    $pontuacao = 0;
    $correspondencias = [];

    foreach ($camposPesquisa as $campo => $rotulo) {
        $valor = trim((string) ($linha[$campo] ?? ''));

        if ($valor === '') {
            continue;
        }

        $valorNormalizado = normalizar($valor);
        $valorCompacto = compacto($valor);

        $encontrou = false;

        if ($valorNormalizado === $termoNormalizado) {
            $pontuacao += in_array(
                $campo,
                ['numero_os', 'telefone', 'patrimonio', 'numero_serie'],
                true
            ) ? 150 : 105;

            $encontrou = true;
        } elseif (
            $termoCompacto !== '' &&
            $valorCompacto === $termoCompacto
        ) {
            $pontuacao += 145;
            $encontrou = true;
        } elseif (str_starts_with($valorNormalizado, $termoNormalizado)) {
            $pontuacao += 55;
            $encontrou = true;
        } elseif (str_contains($valorNormalizado, $termoNormalizado)) {
            $pontuacao += 32;
            $encontrou = true;
        } elseif (
            strlen($termoCompacto) >= 3 &&
            str_contains($valorCompacto, $termoCompacto)
        ) {
            $pontuacao += 38;
            $encontrou = true;
        }

        $tokensEncontrados = 0;

        foreach ($tokens as $token) {
            if (
                $token !== '' &&
                str_contains($valorNormalizado, $token)
            ) {
                $tokensEncontrados++;
            }
        }

        if ($tokensEncontrados > 0) {
            $pontuacao += $tokensEncontrados * 8;
            $encontrou = true;
        }

        if ($encontrou) {
            $correspondencias[] = $rotulo;
        }
    }

    $id = (int) ($linha['id'] ?? 0);

    if (ctype_digit($termoCompacto) && $id === (int) $termoCompacto) {
        $pontuacao += 180;
        $correspondencias[] = 'Código interno';
    }

    $correspondencias = array_values(array_unique($correspondencias));

    $resultado = [
        'id' => $id,
        'numero_os' => (string) ($linha['numero_os'] ?? $id),
        'nome_solicitante' => (string) ($linha['nome_solicitante'] ?? ''),
        'telefone' => (string) ($linha['telefone'] ?? ''),
        'setor' => (string) ($linha['setor'] ?? ''),
        'tipo_equipamento' => (string) ($linha['tipo_equipamento'] ?? ''),
        'marca' => (string) ($linha['marca'] ?? ''),
        'modelo' => (string) ($linha['modelo'] ?? ''),
        'patrimonio' => (string) ($linha['patrimonio'] ?? ''),
        'numero_serie' => (string) ($linha['numero_serie'] ?? ''),
        'problema_resumo' => limitarTexto(
            (string) ($linha['problema'] ?? ''),
            210
        ),
        'status' => (string) ($linha['status'] ?? ''),
        'status_codigo' => codigoStatus(
            (string) ($linha['status'] ?? '')
        ),
        'prioridade' => (string) ($linha['prioridade'] ?? ''),
        'data_entrada' => (string) ($linha['data_entrada'] ?? ''),
        'data_entrada_formatada' => dataFormatada(
            $linha['data_entrada'] ?? null
        ),
        'correspondencias' => array_slice($correspondencias, 0, 6),
        'pontuacao' => $pontuacao
    ];

    $resultados[] = $resultado;
}

usort(
    $resultados,
    static function (array $a, array $b): int {
        $comparacao = (int) $b['pontuacao'] <=> (int) $a['pontuacao'];

        if ($comparacao !== 0) {
            return $comparacao;
        }

        $dataA = strtotime((string) ($a['data_entrada'] ?? '')) ?: 0;
        $dataB = strtotime((string) ($b['data_entrada'] ?? '')) ?: 0;

        return $dataB <=> $dataA;
    }
);

$resultados = array_slice($resultados, 0, 30);

$cadastrosAtuais = [];

if (rastreadorTabelaExiste($mysqli, 'ti_computadores')) {
    $likeCadastro = '%' . $termo . '%';
    $compactoCadastro = '%' . $termoCompacto . '%';

    $sqlCadastro = "
        SELECT
            c.id,
            c.codigo_interno,
            c.tipo,
            c.patrimonio,
            c.numero_serie,
            c.nome_maquina,
            c.fabricante,
            c.modelo,
            c.processador,
            c.memoria_ram_gb,
            c.armazenamento_tipo,
            c.armazenamento_gb,
            c.sistema_operacional,
            c.ip_fixo,
            c.mac_rede,
            c.mac_wifi,
            c.status,
            c.responsavel_nome,
            c.responsavel_matricula,
            c.responsavel_cargo,
            c.localizacao_texto,
            c.atualizado_em,
            s.nome AS setor_nome,
            s.secretaria,
            s.predio,
            s.andar,
            a.nome AS ambiente_nome
        FROM ti_computadores AS c
        LEFT JOIN ti_setores AS s
            ON s.id = c.setor_id
        LEFT JOIN ti_ambientes AS a
            ON a.id = c.ambiente_id
        WHERE
            c.codigo_interno LIKE ?
            OR c.patrimonio LIKE ?
            OR c.numero_serie LIKE ?
            OR c.nome_maquina LIKE ?
            OR c.fabricante LIKE ?
            OR c.modelo LIKE ?
            OR c.responsavel_nome LIKE ?
            OR c.responsavel_matricula LIKE ?
            OR c.localizacao_texto LIKE ?
            OR c.ip_fixo LIKE ?
            OR c.mac_rede LIKE ?
            OR c.mac_wifi LIKE ?
            OR s.nome LIKE ?
            OR s.secretaria LIKE ?
            OR s.predio LIKE ?
            OR a.nome LIKE ?
            OR REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(c.patrimonio,''),' ',''),'.',''),'-',''),'/',''),'(',''),')',''),'+','') LIKE ?
            OR REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(c.numero_serie,''),' ',''),'.',''),'-',''),'/',''),'(',''),')',''),'+','') LIKE ?
        ORDER BY
            CASE
                WHEN LOWER(TRIM(COALESCE(c.patrimonio,''))) = LOWER(TRIM(?)) THEN 0
                WHEN LOWER(TRIM(COALESCE(c.numero_serie,''))) = LOWER(TRIM(?)) THEN 1
                WHEN LOWER(TRIM(COALESCE(c.nome_maquina,''))) = LOWER(TRIM(?)) THEN 2
                ELSE 3
            END,
            c.atualizado_em DESC,
            c.id DESC
        LIMIT 12
    ";

    $stmtCadastro = $mysqli->prepare($sqlCadastro);

    if ($stmtCadastro) {
        $valoresCadastro = array_fill(0, 16, $likeCadastro);
        $valoresCadastro[] = $compactoCadastro;
        $valoresCadastro[] = $compactoCadastro;
        $valoresCadastro[] = $termo;
        $valoresCadastro[] = $termo;
        $valoresCadastro[] = $termo;

        bindDinamico($stmtCadastro, $valoresCadastro);
        $stmtCadastro->execute();
        $resultadoCadastro = $stmtCadastro->get_result();

        while ($linha = $resultadoCadastro->fetch_assoc()) {
            $cadastrosAtuais[] = [
                'id' => (int) $linha['id'],
                'codigo_interno' => (string) $linha['codigo_interno'],
                'tipo' => (string) $linha['tipo'],
                'patrimonio' => (string) ($linha['patrimonio'] ?? ''),
                'numero_serie' => (string) ($linha['numero_serie'] ?? ''),
                'nome_maquina' => (string) ($linha['nome_maquina'] ?? ''),
                'fabricante' => (string) ($linha['fabricante'] ?? ''),
                'modelo' => (string) ($linha['modelo'] ?? ''),
                'processador' => (string) ($linha['processador'] ?? ''),
                'memoria_ram_gb' => (string) ($linha['memoria_ram_gb'] ?? ''),
                'armazenamento_tipo' => (string) ($linha['armazenamento_tipo'] ?? ''),
                'armazenamento_gb' => (string) ($linha['armazenamento_gb'] ?? ''),
                'sistema_operacional' => (string) ($linha['sistema_operacional'] ?? ''),
                'ip_fixo' => (string) ($linha['ip_fixo'] ?? ''),
                'status' => (string) ($linha['status'] ?? ''),
                'status_rotulo' => rastreadorStatusComputador(
                    (string) ($linha['status'] ?? '')
                ),
                'responsavel_nome' => (string) ($linha['responsavel_nome'] ?? ''),
                'responsavel_matricula' => (string) ($linha['responsavel_matricula'] ?? ''),
                'responsavel_cargo' => (string) ($linha['responsavel_cargo'] ?? ''),
                'setor_nome' => (string) ($linha['setor_nome'] ?? ''),
                'secretaria' => (string) ($linha['secretaria'] ?? ''),
                'predio' => (string) ($linha['predio'] ?? ''),
                'andar' => (string) ($linha['andar'] ?? ''),
                'ambiente_nome' => (string) ($linha['ambiente_nome'] ?? ''),
                'localizacao_texto' => (string) ($linha['localizacao_texto'] ?? ''),
                'atualizado_em' => dataFormatada(
                    $linha['atualizado_em'] ?? null
                )
            ];
        }

        $stmtCadastro->close();
    }
}

$mobiles = [];
if (rastreadorTabelaExiste($mysqli, 'ti_mobile_dispositivos')) {
    $likeMobile = '%' . $termo . '%';
    $stmtMobile = $mysqli->prepare("SELECT id,agent_id,tipo_dispositivo,patrimonio,numero_serie_manual,imei_manual,fabricante,modelo,android_version,ram_total_mb,armazenamento_total_mb,armazenamento_livre_mb,bateria_percentual,rede_tipo,ip_local,responsavel_nome,setor,status,ultima_comunicacao FROM ti_mobile_dispositivos WHERE agent_id LIKE ? OR patrimonio LIKE ? OR numero_serie_manual LIKE ? OR imei_manual LIKE ? OR fabricante LIKE ? OR modelo LIKE ? OR responsavel_nome LIKE ? OR setor LIKE ? OR ip_local LIKE ? ORDER BY ultima_comunicacao DESC LIMIT 20");
    if ($stmtMobile) {
        $mobileValues = array_fill(0, 9, $likeMobile);bindDinamico($stmtMobile, $mobileValues);$stmtMobile->execute();$resultMobile = $stmtMobile->get_result();
        while ($row = $resultMobile->fetch_assoc()) {$row['ultima_comunicacao_formatada'] = dataFormatada($row['ultima_comunicacao'] ?? null);$mobiles[] = $row;}
        $stmtMobile->close();
    }
}

responder([
    'ok' => true,
    'termo' => $termo,
    'total' => count($cadastrosAtuais) + count($mobiles) + count($resultados),
    'total_cadastros' => count($cadastrosAtuais),
    'total_os' => count($resultados),
    'cadastros' => $cadastrosAtuais,
    'mobiles' => $mobiles,
    'resultados' => $resultados
]);

}

$consultaInicial = trim((string) ($_GET['q'] ?? ''));
?>
<!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>Rastreador de Equipamentos | 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{
            --blue:#08396f;
            --blue-dark:#05294f;
            --blue-light:#145b9f;
            --green:#087f5b;
            --gold:#e8ad16;
            --red:#bf263d;
            --text:#172438;
            --muted:#62738a;
            --border:#dce6ee;
            --surface:#fff;
            --soft:#f5f9fc;
        }

        *{box-sizing:border-box}

        html,body{
            margin:0;
            min-height:100%;
            font-family:"Inter",system-ui,-apple-system,"Segoe UI",sans-serif;
            color:var(--text);
            background:
                radial-gradient(circle at 0 0,rgba(20,91,159,.13),transparent 30rem),
                radial-gradient(circle at 100% 100%,rgba(8,127,91,.1),transparent 32rem),
                #edf3f8;
        }

        body{padding:18px}

        .shell{
            width:min(1550px,100%);
            margin:auto;
        }

        .header{
            position:relative;
            overflow:hidden;
            display:flex;
            align-items:center;
            justify-content:space-between;
            gap:18px;
            padding:23px;
            border-radius:29px;
            color:#fff;
            background:
                radial-gradient(circle at 82% 0,rgba(255,255,255,.13),transparent 25rem),
                linear-gradient(145deg,var(--blue-dark),var(--blue) 58%,#07537c);
            box-shadow:0 30px 80px rgba(5,41,79,.24);
        }

        .header::after{
            content:"";
            position:absolute;
            right:-130px;
            bottom:-220px;
            width:430px;
            height:430px;
            border:50px solid rgba(255,255,255,.04);
            border-radius:50%;
        }

        .brand,.header-actions{position:relative;z-index:2}

        .brand small{
            display:block;
            color:rgba(255,255,255,.7);
            font-size:8px;
            font-weight:900;
            letter-spacing:.7px;
            text-transform:uppercase;
        }

        .brand h1{
            margin:7px 0 0;
            font-size:clamp(27px,4vw,52px);
            line-height:.98;
            letter-spacing:-1.8px;
            font-weight:950;
        }

        .brand p{
            max-width:760px;
            margin:10px 0 0;
            color:rgba(255,255,255,.7);
            font-size:10px;
            line-height:1.55;
        }

        .header-actions{
            display:flex;
            gap:8px;
            flex-wrap:wrap;
        }

        .header-button{
            min-height:42px;
            display:inline-flex;
            align-items:center;
            justify-content:center;
            gap:7px;
            padding:0 13px;
            border:1px solid rgba(255,255,255,.17);
            border-radius:13px;
            color:#fff;
            background:rgba(255,255,255,.09);
            text-decoration:none;
            font-size:8px;
            font-weight:900;
            text-transform:uppercase;
        }

        .search-panel{
            margin-top:15px;
            padding:22px;
            border:1px solid rgba(255,255,255,.9);
            border-radius:27px;
            background:rgba(255,255,255,.9);
            box-shadow:0 20px 60px rgba(8,57,111,.1);
            backdrop-filter:blur(18px);
        }

        .search-head{
            display:flex;
            align-items:center;
            gap:12px;
        }

        .search-icon{
            width:52px;
            height:52px;
            display:grid;
            place-items:center;
            border-radius:17px;
            color:#fff;
            background:linear-gradient(145deg,var(--blue),var(--blue-light));
            box-shadow:0 14px 30px rgba(8,57,111,.2);
            font-size:23px;
        }

        .search-head h2{
            margin:0;
            font-size:17px;
            font-weight:900;
        }

        .search-head p{
            margin:4px 0 0;
            color:var(--muted);
            font-size:9px;
            line-height:1.45;
        }

        .search-form{
            display:grid;
            grid-template-columns:minmax(0,1fr) auto;
            gap:9px;
            margin-top:17px;
        }

        .search-field{
            position:relative;
        }

        .search-field i{
            position:absolute;
            top:50%;
            left:16px;
            color:var(--blue);
            transform:translateY(-50%);
            font-size:18px;
        }

        .search-input{
            width:100%;
            min-height:58px;
            padding:0 16px 0 49px;
            border:1px solid var(--border);
            border-radius:17px;
            outline:0;
            color:var(--text);
            background:var(--soft);
            font-size:12px;
            font-weight:750;
        }

        .search-input:focus{
            border-color:var(--blue-light);
            background:#fff;
            box-shadow:0 0 0 5px rgba(20,91,159,.1);
        }

        .search-button{
            min-width:160px;
            min-height:58px;
            display:inline-flex;
            align-items:center;
            justify-content:center;
            gap:8px;
            border:0;
            border-radius:17px;
            color:#fff;
            background:linear-gradient(145deg,var(--blue-dark),var(--blue));
            box-shadow:0 16px 34px rgba(8,57,111,.19);
            font-size:9px;
            font-weight:950;
            text-transform:uppercase;
        }

        .hints{
            display:flex;
            align-items:center;
            gap:7px;
            flex-wrap:wrap;
            margin-top:12px;
        }

        .hint{
            padding:7px 9px;
            border:1px solid var(--border);
            border-radius:999px;
            color:#536277;
            background:#fff;
            font-size:7px;
            font-weight:800;
            cursor:pointer;
        }

        .results-panel{
            margin-top:15px;
            overflow:hidden;
            border:1px solid rgba(255,255,255,.9);
            border-radius:27px;
            background:rgba(255,255,255,.91);
            box-shadow:0 20px 60px rgba(8,57,111,.09);
        }

        .results-head{
            display:flex;
            align-items:center;
            justify-content:space-between;
            gap:12px;
            padding:17px 20px;
            border-bottom:1px solid var(--border);
            background:linear-gradient(180deg,#fff,#f8fbfd);
        }

        .results-head h2{
            margin:0;
            font-size:14px;
            font-weight:900;
        }

        .results-head p{
            margin:4px 0 0;
            color:var(--muted);
            font-size:8px;
        }

        .result-count{
            padding:8px 10px;
            border-radius:999px;
            color:var(--blue);
            background:#eaf4fc;
            font-size:8px;
            font-weight:900;
        }

        .results-body{padding:15px}

        .empty{
            padding:50px 18px;
            text-align:center;
            color:var(--muted);
        }

        .empty-icon{
            width:70px;
            height:70px;
            display:grid;
            place-items:center;
            margin:0 auto 14px;
            border:1px solid var(--border);
            border-radius:23px;
            color:var(--blue);
            background:var(--soft);
            font-size:30px;
        }

        .empty strong{
            display:block;
            color:var(--text);
            font-size:13px;
            font-weight:900;
        }

        .empty span{
            display:block;
            max-width:600px;
            margin:7px auto 0;
            font-size:9px;
            line-height:1.55;
        }

        .registry-section{
            margin-bottom:16px;
            padding-bottom:16px;
            border-bottom:1px solid var(--border);
        }

        .registry-heading{
            display:flex;
            align-items:center;
            justify-content:space-between;
            gap:12px;
            margin-bottom:10px;
        }

        .registry-heading strong{
            display:flex;
            align-items:center;
            gap:7px;
            color:var(--blue);
            font-size:10px;
            font-weight:950;
            text-transform:uppercase;
        }

        .registry-heading span{
            color:var(--muted);
            font-size:7px;
            font-weight:800;
        }

        .registry-card{
            border-color:#a9cfe6;
            background:
                radial-gradient(circle at 100% 0,rgba(20,91,159,.08),transparent 12rem),
                #ffffff;
            box-shadow:0 17px 42px rgba(8,57,111,.12);
        }

        .registry-label{
            display:inline-flex;
            align-items:center;
            gap:6px;
            width:fit-content;
            margin-bottom:9px;
            padding:5px 7px;
            border-radius:999px;
            color:#fff;
            background:var(--blue);
            font-size:6px;
            font-weight:950;
            text-transform:uppercase;
        }

        .registry-status{
            padding:6px 8px;
            border-radius:999px;
            color:#086247;
            background:#e8f8f1;
            font-size:7px;
            font-weight:900;
        }

        .history-heading{
            display:flex;
            align-items:center;
            justify-content:space-between;
            gap:12px;
            margin:2px 0 10px;
        }

        .history-heading strong{
            display:flex;
            align-items:center;
            gap:7px;
            color:#493592;
            font-size:10px;
            font-weight:950;
            text-transform:uppercase;
        }

        .history-heading span{
            color:var(--muted);
            font-size:7px;
            font-weight:800;
        }

        .result-list{
            display:grid;
            grid-template-columns:repeat(2,minmax(0,1fr));
            gap:11px;
        }

        .result-card{
            position:relative;
            overflow:hidden;
            padding:16px;
            border:1px solid var(--border);
            border-radius:20px;
            background:#fff;
            box-shadow:0 10px 27px rgba(8,57,111,.05);
        }

        .result-card.best{
            border-color:#9bc8e4;
            box-shadow:0 16px 38px rgba(8,57,111,.12);
        }

        .best-label{
            display:none;
            width:fit-content;
            margin-bottom:9px;
            padding:5px 7px;
            border-radius:999px;
            color:#fff;
            background:var(--green);
            font-size:6px;
            font-weight:950;
            text-transform:uppercase;
        }

        .best .best-label{display:inline-flex}

        .result-top{
            display:flex;
            align-items:flex-start;
            justify-content:space-between;
            gap:12px;
        }

        .result-os{
            color:var(--blue);
            font-size:12px;
            font-weight:950;
        }

        .status{
            padding:6px 8px;
            border-radius:999px;
            color:#946000;
            background:#fff7e6;
            font-size:7px;
            font-weight:900;
        }

        .status.finalizado{
            color:#086247;
            background:#e8f8f1;
        }

        .status.pendente_retirada{
            color:#195d90;
            background:#eaf4fc;
        }

        .result-person{
            margin-top:11px;
            font-size:11px;
            font-weight:900;
        }

        .result-sub{
            margin-top:4px;
            color:var(--muted);
            font-size:8px;
            line-height:1.45;
        }

        .data-grid{
            display:grid;
            grid-template-columns:repeat(2,minmax(0,1fr));
            gap:7px;
            margin-top:12px;
        }

        .data{
            padding:9px;
            border:1px solid var(--border);
            border-radius:13px;
            background:var(--soft);
        }

        .data span{
            display:block;
            color:var(--muted);
            font-size:6px;
            font-weight:900;
            text-transform:uppercase;
        }

        .data strong{
            display:block;
            margin-top:4px;
            font-size:8px;
            line-height:1.35;
            font-weight:850;
            word-break:break-word;
        }

        .problem{
            margin-top:9px;
            padding:10px;
            border-left:4px solid var(--blue);
            border-radius:0 12px 12px 0;
            color:#46566c;
            background:#f5f9fc;
            font-size:8px;
            line-height:1.5;
        }

        .matches{
            display:flex;
            gap:5px;
            flex-wrap:wrap;
            margin-top:10px;
        }

        .match{
            padding:5px 7px;
            border-radius:999px;
            color:#493592;
            background:#f0edfb;
            font-size:6px;
            font-weight:900;
        }

        .actions{
            display:flex;
            gap:7px;
            flex-wrap:wrap;
            margin-top:12px;
        }

        .action{
            min-height:39px;
            display:inline-flex;
            align-items:center;
            justify-content:center;
            gap:6px;
            padding:0 11px;
            border:1px solid var(--border);
            border-radius:12px;
            color:var(--blue);
            background:#fff;
            font-size:7px;
            font-weight:900;
            text-transform:uppercase;
            cursor:pointer;
        }

        .action.primary{
            color:#fff;
            border-color:var(--blue);
            background:var(--blue);
        }

        .loading{
            padding:55px;
            text-align:center;
            color:var(--muted);
            font-size:9px;
        }

        .spinner{
            width:45px;
            height:45px;
            margin:0 auto 12px;
            border:4px solid #dce6ee;
            border-top-color:var(--blue);
            border-radius:50%;
            animation:spin .8s linear infinite;
        }

        @keyframes spin{to{transform:rotate(360deg)}}

        @media(max-width:900px){
            .result-list{grid-template-columns:1fr}
        }

        @media(max-width:700px){
            body{padding:8px}
            .header{flex-direction:column;align-items:flex-start;padding:19px;border-radius:23px}
            .search-panel,.results-panel{border-radius:22px}
            .search-form{grid-template-columns:1fr}
            .search-button{width:100%}
            .data-grid{grid-template-columns:1fr}
        }
    </style>
</head>
<body>

<div class="shell">

    <header class="header">
        <div class="brand">
            <small>
                Prefeitura de Extrema • Gerência de Tecnologia
            </small>

            <h1>Rastreador de equipamentos</h1>

            <p>
                Pesquise por patrimônio, série, nome, telefone, setor,
                modelo, problema ou qualquer informação disponível.
            </p>
        </div>

        <nav class="header-actions">
            <?php if ($usuarioPodeGerenciarAlerta): ?>
                <a href="alerta_global_admin.php" class="header-button">
                    <i class="bi bi-broadcast-pin"></i>
                    Alerta global
                </a>
            <?php endif; ?>

            <a href="nova_os.php" class="header-button">
                <i class="bi bi-plus-circle-fill"></i>
                Nova OS
            </a>

            <a href="listar_os.php" class="header-button">
                <i class="bi bi-arrow-left-circle-fill"></i>
                Voltar às OS
            </a>
        </nav>
    </header>

    <section class="search-panel">
        <div class="search-head">
            <span class="search-icon">
                <i class="bi bi-radar"></i>
            </span>

            <div>
                <h2>Digite qualquer pista encontrada</h2>
                <p>
                    O sistema cruza todos os campos disponíveis no histórico.
                </p>
            </div>
        </div>

        <form class="search-form" id="trackerForm">
            <div class="search-field">
                <i class="bi bi-search"></i>

                <input
                    type="search"
                    class="search-input"
                    id="trackerInput"
                    value="<?= htmlspecialchars($consultaInicial, ENT_QUOTES, 'UTF-8') ?>"
                    placeholder="Ex.: 59411, Dell, Kevin, 3598..., CN0ABC, Cultura..."
                    autocomplete="off"
                    autofocus
                >
            </div>

            <button type="submit" class="search-button" id="trackerButton">
                <i class="bi bi-radar"></i>
                Rastrear agora
            </button>
        </form>

        <div class="hints">
            <button type="button" class="hint" data-hint="59411">Patrimônio</button>
            <button type="button" class="hint" data-hint="Dell">Marca ou modelo</button>
            <button type="button" class="hint" data-hint="não liga">Problema</button>
            <button type="button" class="hint" data-hint="Cultura">Setor</button>
            <span class="hint">
                <i class="bi bi-upc-scan"></i>
                Bipador: leia o código e pressione Enter
            </span>
        </div>
    </section>

    <section class="results-panel">
        <div class="results-head">
            <div>
                <h2>Resultados encontrados</h2>
                <p id="resultDescription">
                    Informe uma pista para iniciar.
                </p>
            </div>

            <span class="result-count" id="resultCount">
                0 resultados
            </span>
        </div>

        <div class="results-body" id="resultsBody">
            <div class="empty">
                <div class="empty-icon">
                    <i class="bi bi-search"></i>
                </div>

                <strong>Pronto para rastrear</strong>

                <span>
                    Mesmo que o equipamento chegue sem nome ou setor,
                    tente o patrimônio, série, etiqueta, marca, modelo
                    ou qualquer palavra que esteja nele.
                </span>
            </div>
        </div>
    </section>

</div>

<div
    class="modal fade"
    id="trackerDetailModal"
    tabindex="-1"
    aria-hidden="true"
>
    <div class="modal-dialog modal-xl modal-dialog-centered modal-dialog-scrollable">
        <div class="modal-content" style="border:0;border-radius:24px;overflow:hidden;">
            <div class="modal-header" style="color:#fff;background:linear-gradient(145deg,#05294f,#08396f);">
                <h5 class="modal-title">
                    <i class="bi bi-clipboard2-data-fill me-2"></i>
                    Detalhes da ordem de serviço
                </h5>

                <button
                    type="button"
                    class="btn-close btn-close-white"
                    data-bs-dismiss="modal"
                ></button>
            </div>

            <div class="modal-body" id="trackerDetailBody">
                Carregando...
            </div>
        </div>
    </div>
</div>

<script
    src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
></script>

<script>
const csrfRastreador = <?= json_encode(
    $csrfRastreador,
    JSON_HEX_TAG |
    JSON_HEX_APOS |
    JSON_HEX_QUOT |
    JSON_HEX_AMP
) ?>;

const form = document.getElementById('trackerForm');
const input = document.getElementById('trackerInput');
const button = document.getElementById('trackerButton');
const body = document.getElementById('resultsBody');
const count = document.getElementById('resultCount');
const description = document.getElementById('resultDescription');

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

function montarEquipamento(item) {
    return [
        item.tipo_equipamento,
        item.marca,
        item.modelo
    ].filter(Boolean).join(' • ') || 'Não informado';
}

function statusCadastroClasse(status) {
    const valor = String(status || '').toUpperCase();

    if (valor === 'EM_USO' || valor === 'DISPONIVEL') {
        return 'finalizado';
    }

    if (valor === 'MANUTENCAO' || valor === 'AGUARDANDO_BAIXA') {
        return 'pendente_retirada';
    }

    return 'em_andamento';
}

function montarConfiguracaoCadastro(item) {
    return [
        item.processador,
        item.memoria_ram_gb
            ? `${item.memoria_ram_gb} GB RAM`
            : '',
        [
            item.armazenamento_tipo,
            item.armazenamento_gb
                ? `${item.armazenamento_gb} GB`
                : ''
        ].filter(Boolean).join(' '),
        item.sistema_operacional
    ].filter(Boolean).join(' • ') || 'Configuração não informada';
}

function montarLocalizacaoCadastro(item) {
    return [
        item.setor_nome,
        item.predio,
        item.andar,
        item.ambiente_nome,
        item.localizacao_texto
    ].filter(Boolean).join(' • ') || 'Localização não informada';
}

function renderizarResultados(dados) {
    const cadastros = dados.cadastros || [];
    const mobiles = dados.mobiles || [];
    const resultados = dados.resultados || [];
    const total = cadastros.length + mobiles.length + resultados.length;

    count.textContent =
        `${total} ` +
        (total === 1
            ? 'vínculo'
            : 'vínculos');

    description.textContent = total
        ? `Cadastro atual e histórico pesquisados por “${dados.termo}”.`
        : `Nenhum vínculo localizado para “${dados.termo}”.`;

    if (!total) {
        body.innerHTML = `
            <div class="empty">
                <div class="empty-icon">
                    <i class="bi bi-question-circle-fill"></i>
                </div>

                <strong>Nenhuma correspondência encontrada</strong>

                <span>
                    Tente somente parte do patrimônio, nome, telefone,
                    série, marca ou modelo. Também é possível abrir uma
                    nova OS para registrar este equipamento.
                </span>

                <div class="actions" style="justify-content:center;">
                    <a href="nova_os.php" class="action primary">
                        <i class="bi bi-plus-circle-fill"></i>
                        Abrir nova OS
                    </a>
                </div>
            </div>
        `;
        return;
    }

    const cadastroHtml = cadastros.length
        ? `
            <section class="registry-section">
                <div class="registry-heading">
                    <strong>
                        <i class="bi bi-database-fill-check"></i>
                        Cadastro atual no inventário
                    </strong>

                    <span>
                        ${cadastros.length}
                        ${cadastros.length === 1 ? 'equipamento' : 'equipamentos'}
                    </span>
                </div>

                <div class="result-list">
                    ${cadastros.map(item => `
                        <article class="result-card registry-card">
                            <span class="registry-label">
                                <i class="bi bi-pc-display"></i>
                                Localização atual
                            </span>

                            <div class="result-top">
                                <strong class="result-os">
                                    ${eHtml(
                                        [item.fabricante, item.modelo]
                                            .filter(Boolean)
                                            .join(' ') ||
                                        item.codigo_interno
                                    )}
                                </strong>

                                <span class="registry-status ${statusCadastroClasse(item.status)}">
                                    ${eHtml(item.status_rotulo || item.status)}
                                </span>
                            </div>

                            <div class="result-person">
                                ${eHtml(item.responsavel_nome || 'Sem responsável definido')}
                            </div>

                            <div class="result-sub">
                                <i class="bi bi-geo-alt-fill"></i>
                                ${eHtml(montarLocalizacaoCadastro(item))}
                            </div>

                            <div class="data-grid">
                                <div class="data">
                                    <span>Patrimônio</span>
                                    <strong>${eHtml(item.patrimonio || 'Não informado')}</strong>
                                </div>

                                <div class="data">
                                    <span>Número de série</span>
                                    <strong>${eHtml(item.numero_serie || 'Não informado')}</strong>
                                </div>

                                <div class="data">
                                    <span>Nome da máquina</span>
                                    <strong>${eHtml(item.nome_maquina || 'Não informado')}</strong>
                                </div>

                                <div class="data">
                                    <span>IP fixo</span>
                                    <strong>${eHtml(item.ip_fixo || 'Não informado')}</strong>
                                </div>
                            </div>

                            <div class="problem">
                                <strong>Configuração:</strong>
                                ${eHtml(montarConfiguracaoCadastro(item))}
                            </div>

                            <div class="actions">
                                <a
                                    href="computadores.php?busca=${encodeURIComponent(item.patrimonio || item.nome_maquina || item.codigo_interno)}"
                                    class="action primary"
                                >
                                    <i class="bi bi-pc-display"></i>
                                    Abrir cadastro
                                </a>

                                <a
                                    href="computadores.php?busca=${encodeURIComponent(item.patrimonio || item.numero_serie || item.nome_maquina)}"
                                    class="action"
                                >
                                    <i class="bi bi-clock-history"></i>
                                    Histórico patrimonial
                                </a>
                            </div>
                        </article>
                    `).join('')}
                </div>
            </section>
        `
        : '';

    const mobileHtml = mobiles.length
        ? `<section class="registry-section"><div class="registry-heading"><strong><i class="bi bi-android2"></i> Inventário automático Android</strong><span>${mobiles.length} dispositivo(s)</span></div><div class="result-list">${mobiles.map(item => `<article class="result-card registry-card"><span class="registry-label"><i class="bi bi-broadcast-pin"></i> Agente Android ${eHtml(item.status)}</span><div class="result-top"><strong class="result-os">${eHtml([item.fabricante,item.modelo].filter(Boolean).join(' ')||item.agent_id)}</strong><span class="registry-status">${eHtml(item.agent_id)}</span></div><div class="result-person">${eHtml(item.responsavel_nome||'Sem responsável')}</div><div class="result-sub"><i class="bi bi-geo-alt-fill"></i> ${eHtml(item.setor||'Sem setor')}</div><div class="data-grid"><div class="data"><span>Patrimônio</span><strong>${eHtml(item.patrimonio||'N/I')}</strong></div><div class="data"><span>Android</span><strong>${eHtml(item.android_version||'N/I')}</strong></div><div class="data"><span>Bateria</span><strong>${eHtml(String(item.bateria_percentual??'N/I'))}%</strong></div><div class="data"><span>Armazenamento livre</span><strong>${item.armazenamento_livre_mb?eHtml((Number(item.armazenamento_livre_mb)/1024).toFixed(1)+' GB'):'N/I'}</strong></div></div><div class="problem"><strong>Última comunicação:</strong> ${eHtml(item.ultima_comunicacao_formatada||'Nunca')} • ${eHtml(item.rede_tipo||'Rede N/I')} • ${eHtml(item.ip_local||'IP N/I')}</div><div class="actions"><a href="inventario_dispositivo.php?id=${Number(item.id)}" class="action primary"><i class="bi bi-tablet-fill"></i>Abrir ficha Android</a></div></article>`).join('')}</div></section>`
        : '';

    const historicoHtml = resultados.length
        ? `
            <section>
                <div class="history-heading">
                    <strong>
                        <i class="bi bi-clipboard2-pulse-fill"></i>
                        Histórico de ordens de serviço
                    </strong>

                    <span>
                        ${resultados.length}
                        ${resultados.length === 1 ? 'ordem' : 'ordens'}
                    </span>
                </div>

                <div class="result-list">
                    ${resultados.map((item, index) => `
                        <article class="result-card ${index === 0 ? 'best' : ''}">
                            <span class="best-label">
                                <i class="bi bi-stars me-1"></i>
                                Melhor correspondência
                            </span>

                            <div class="result-top">
                                <strong class="result-os">
                                    OS #${eHtml(item.numero_os || item.id)}
                                </strong>

                                <span class="status ${eHtml(item.status_codigo)}">
                                    ${eHtml(item.status || 'Em andamento')}
                                </span>
                            </div>

                            <div class="result-person">
                                ${eHtml(item.nome_solicitante || 'Solicitante não informado')}
                            </div>

                            <div class="result-sub">
                                <i class="bi bi-building"></i>
                                ${eHtml(item.setor || 'Setor não informado')}
                                ${item.telefone
                                    ? ` • <i class="bi bi-telephone-fill"></i> ${eHtml(item.telefone)}`
                                    : ''}
                            </div>

                            <div class="data-grid">
                                <div class="data">
                                    <span>Equipamento</span>
                                    <strong>${eHtml(montarEquipamento(item))}</strong>
                                </div>

                                <div class="data">
                                    <span>Patrimônio</span>
                                    <strong>${eHtml(item.patrimonio || 'Não informado')}</strong>
                                </div>

                                <div class="data">
                                    <span>Número de série</span>
                                    <strong>${eHtml(item.numero_serie || 'Não informado')}</strong>
                                </div>

                                <div class="data">
                                    <span>Entrada</span>
                                    <strong>${eHtml(item.data_entrada_formatada || 'Não informada')}</strong>
                                </div>
                            </div>

                            ${item.problema_resumo
                                ? `<div class="problem">
                                    <strong>Problema:</strong>
                                    ${eHtml(item.problema_resumo)}
                                   </div>`
                                : ''}

                            <div class="matches">
                                ${(item.correspondencias || []).map(valor => `
                                    <span class="match">
                                        <i class="bi bi-check-circle-fill"></i>
                                        ${eHtml(valor)}
                                    </span>
                                `).join('')}
                            </div>

                            <div class="actions">
                                <button
                                    type="button"
                                    class="action primary"
                                    onclick="abrirDetalhes(${Number(item.id)})"
                                >
                                    <i class="bi bi-eye-fill"></i>
                                    Visualizar OS
                                </button>

                                <a
                                    href="listar_os.php?buscar=${encodeURIComponent(item.numero_os || item.id)}&abrir_os=${Number(item.id)}"
                                    class="action"
                                >
                                    <i class="bi bi-list-check"></i>
                                    Abrir na lista
                                </a>
                            </div>
                        </article>
                    `).join('')}
                </div>
            </section>
        `
        : `
            <section class="empty" style="padding:25px 15px 5px;">
                <strong>Nenhuma OS anterior encontrada</strong>
                <span>O cadastro atual foi localizado, mas ainda não existe ordem de serviço vinculada a esta pesquisa.</span>
            </section>
        `;

    body.innerHTML = mobileHtml + cadastroHtml + historicoHtml;
}

async function pesquisar(termo) {
    const valor = String(termo || '').trim();

    if (valor.length < 2) {
        description.textContent =
            'Informe pelo menos dois caracteres.';

        input.focus();
        return;
    }

    body.innerHTML = `
        <div class="loading">
            <div class="spinner"></div>
            Cruzando todos os campos do histórico...
        </div>
    `;

    button.disabled = true;

    try {
        const payload = new URLSearchParams({
            termo: valor,
            csrf_token: csrfRastreador
        });

        const response = await fetch(
            'rastrear_equipamento.php',
            {
                method: 'POST',
                credentials: 'same-origin',
                headers: {
                    'Content-Type':
                        'application/x-www-form-urlencoded;charset=UTF-8',
                    'X-Requested-With':
                        'XMLHttpRequest'
                },
                body: payload.toString()
            }
        );

        const dados = await response.json().catch(() => ({}));

        if (!response.ok || dados.ok === false) {
            throw new Error(
                dados.message ||
                'Não foi possível realizar a pesquisa.'
            );
        }

        renderizarResultados(dados);

        const url = new URL(window.location.href);
        url.searchParams.set('q', valor);
        history.replaceState({}, '', url);
    } catch (erro) {
        body.innerHTML = `
            <div class="empty">
                <div class="empty-icon" style="color:#bf263d;">
                    <i class="bi bi-exclamation-triangle-fill"></i>
                </div>

                <strong>Pesquisa indisponível</strong>

                <span>${eHtml(erro.message)}</span>
            </div>
        `;
    } finally {
        button.disabled = false;
    }
}

form.addEventListener('submit', event => {
    event.preventDefault();
    pesquisar(input.value);
});

document.querySelectorAll('[data-hint]').forEach(item => {
    item.addEventListener('click', () => {
        input.value = item.dataset.hint || '';
        pesquisar(input.value);
    });
});

function abrirDetalhes(id) {
    const modalElement =
        document.getElementById('trackerDetailModal');

    const modalBody =
        document.getElementById('trackerDetailBody');

    modalBody.innerHTML = `
        <div class="loading">
            <div class="spinner"></div>
            Carregando informações...
        </div>
    `;

    bootstrap.Modal
        .getOrCreateInstance(modalElement)
        .show();

    fetch(
        `detalhes_os.php?id=${encodeURIComponent(id)}`,
        {
            credentials: 'same-origin',
            headers: {
                'X-Requested-With':
                    'XMLHttpRequest'
            }
        }
    )
        .then(response => {
            if (!response.ok) {
                throw new Error();
            }

            return response.text();
        })
        .then(html => {
            modalBody.innerHTML = html;
        })
        .catch(() => {
            modalBody.innerHTML = `
                <div class="alert alert-danger border-0 rounded-4">
                    Não foi possível carregar os detalhes.
                </div>
            `;
        });
}

if (input.value.trim().length >= 2) {
    pesquisar(input.value);
}
</script>

<script src="alerta_global_cliente.js?v=1"></script>

</body>
</html>
