<?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');
}

header('Content-Type: application/json; charset=utf-8');

function responder(array $dados, int $status = 200): never
{
    http_response_code($status);

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

    exit;
}

function normalizar(string $texto): string
{
    $texto = trim($texto);
    $texto = function_exists('mb_strtolower')
        ? mb_strtolower($texto, 'UTF-8')
        : strtolower($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'
    ]);

    $texto = preg_replace('/[^a-z0-9\s\-\/\.]/', ' ', $texto) ?? $texto;

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

function tokens(string $texto): array
{
    $stopwords = [
        'uma', 'para', 'com', 'sem', 'que', 'por', 'dos', 'das',
        'esta', 'foi', 'nao', 'equipamento', 'problema', 'apresenta'
    ];

    $partes = preg_split('/\s+/', normalizar($texto)) ?: [];
    $resultado = [];

    foreach ($partes as $parte) {
        if (strlen($parte) < 3 || in_array($parte, $stopwords, true)) {
            continue;
        }

        $resultado[$parte] = true;
    }

    return array_keys($resultado);
}

function similaridade(string $a, string $b): int
{
    $aTokens = tokens($a);
    $bTokens = tokens($b);

    if (!$aTokens || !$bTokens) {
        return 0;
    }

    $intersecao = array_intersect($aTokens, $bTokens);
    $uniao = array_unique(array_merge($aTokens, $bTokens));

    return $uniao
        ? (int) round((count($intersecao) / count($uniao)) * 100)
        : 0;
}

function colunaExiste(mysqli $db, string $tabela, string $coluna): bool
{
    $stmt = $db->prepare("\n        SELECT COUNT(*) 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', $tabela, $coluna);
    $stmt->execute();
    $row = $stmt->get_result()->fetch_assoc();
    $stmt->close();

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

function regras(): array
{
    return [
        [
            'id' => 'energia',
            'titulo' => 'Falha no circuito de alimentação',
            'equipamentos' => ['computador', 'desktop', 'notebook', 'nobreak', 'monitor', 'impressora'],
            'palavras' => [
                'nao liga' => 12,
                'sem energia' => 11,
                'nao acende' => 10,
                'sem led' => 9,
                'queda de energia' => 8,
                'fonte' => 5,
                'carregador' => 5
            ],
            'resumo' => 'Os sintomas apontam primeiro para tomada, cabo, fonte, carregador ou circuito interno de entrada de energia.',
            'causas' => [
                ['titulo' => 'Fonte, carregador ou cabo com defeito', 'explicacao' => 'A ausência de LEDs e ventilação normalmente começa pela alimentação externa.'],
                ['titulo' => 'Tomada, filtro de linha ou nobreak', 'explicacao' => 'O ponto elétrico pode não estar entregando energia ao equipamento.'],
                ['titulo' => 'Placa-mãe ou circuito de entrada', 'explicacao' => 'Considere depois de eliminar tomada, cabo e fonte.']
            ],
            'passos' => [
                'Desligue o equipamento, retire o cabo de energia e desconecte todos os periféricos.',
                'Teste a tomada com outro equipamento e dispense temporariamente filtro de linha ou nobreak.',
                'Inspecione cabo, carregador, conector e sinais de aquecimento, corte ou folga.',
                'Em notebook, remova a bateria removível e mantenha o botão de ligar pressionado por 20 segundos.',
                'Reconecte somente a alimentação e tente ligar sem acessórios USB ou rede.',
                'Teste outro cabo, carregador ou fonte compatível e comprovadamente funcional.',
                'Em desktop, confira a chave da fonte, conectores ATX/EPS e o cabo do botão power.',
                'Se persistir, teste a fonte com equipamento apropriado ou fonte substituta.',
                'Somente após eliminar a alimentação externa, inspecione placa-mãe, oxidação e possíveis curtos.',
                'Após a correção, execute três ciclos completos de desligamento e inicialização.'
            ],
            'ferramentas' => ['Cabo ou carregador compatível', 'Multímetro ou testador de fonte', 'Pulseira antiestática', 'Kit de abertura'],
            'validacao' => ['Liga em três tentativas consecutivas.', 'LEDs, ventiladores e tela iniciam normalmente.', 'Não há cheiro, ruído ou aquecimento anormal.'],
            'alertas' => ['Não abra fonte, nobreak ou monitor energizado.', 'Interrompa em caso de cheiro de queimado, faísca ou aquecimento excessivo.'],
            'risco' => 'Alto'
        ],
        [
            'id' => 'video',
            'titulo' => 'Falha de vídeo, memória RAM ou inicialização',
            'equipamentos' => ['computador', 'desktop', 'notebook', 'monitor'],
            'palavras' => [
                'sem video' => 12,
                'sem imagem' => 12,
                'tela preta' => 11,
                'liga mas nao aparece' => 10,
                'sem sinal' => 9,
                'bipes' => 7
            ],
            'resumo' => 'O equipamento recebe energia, mas não conclui corretamente a geração ou a exibição do vídeo.',
            'causas' => [
                ['titulo' => 'Memória RAM mal encaixada ou defeituosa', 'explicacao' => 'É frequente quando o computador liga sem vídeo ou emite bipes.'],
                ['titulo' => 'Cabo, monitor ou entrada de vídeo', 'explicacao' => 'O sistema pode estar iniciando, mas o sinal não chega ao monitor.'],
                ['titulo' => 'BIOS, placa de vídeo ou placa-mãe', 'explicacao' => 'Hipótese posterior aos testes de monitor, cabo e memória.']
            ],
            'passos' => [
                'Confirme se há LEDs, ventilação e algum código de bipes.',
                'Teste outro cabo de vídeo e selecione a entrada correta do monitor.',
                'Teste o computador em outro monitor e o monitor em outro computador.',
                'Desconecte acessórios USB e tente iniciar apenas com teclado, vídeo e energia.',
                'Desligue completamente e descarregue a energia residual.',
                'Remova os módulos de memória, limpe os contatos e recoloque um módulo por vez.',
                'Teste cada slot e, se possível, uma memória compatível conhecida.',
                'Em placa de vídeo dedicada, teste a saída integrada ou outra placa compatível.',
                'Execute reset seguro da BIOS/CMOS conforme o fabricante.',
                'Persistindo, encaminhe para diagnóstico de placa-mãe, GPU ou circuito da tela.'
            ],
            'ferramentas' => ['Monitor conhecido', 'Cabo de vídeo conhecido', 'Memória RAM compatível', 'Pulseira antiestática'],
            'validacao' => ['A imagem aparece desde o logotipo do fabricante.', 'O sistema inicia sem bipes.', 'O vídeo permanece estável em teste prolongado.'],
            'alertas' => ['Desligue a alimentação antes de manipular memória ou placa de vídeo.', 'Não force conectores, travas ou cabo flat.'],
            'risco' => 'Médio'
        ],
        [
            'id' => 'lentidao',
            'titulo' => 'Baixo desempenho por armazenamento, memória ou software',
            'equipamentos' => ['computador', 'desktop', 'notebook'],
            'palavras' => [
                'lento' => 9,
                'lentidao' => 11,
                'travando' => 10,
                'demora' => 7,
                'disco 100' => 10,
                '100 disco' => 10,
                'congelando' => 8,
                'nao responde' => 7
            ],
            'resumo' => 'O desempenho pode estar limitado por SSD/HD degradado, pouca memória, excesso de processos, temperatura ou corrupção do sistema.',
            'causas' => [
                ['titulo' => 'SSD ou HD degradado', 'explicacao' => 'Uso de disco em 100% e travamentos apontam para armazenamento.'],
                ['titulo' => 'Memória insuficiente ou processos em excesso', 'explicacao' => 'Muitos serviços provocam paginação e resposta lenta.'],
                ['titulo' => 'Sistema, perfil ou software corrompido', 'explicacao' => 'Inicialização carregada e arquivos danificados também reduzem o desempenho.']
            ],
            'passos' => [
                'Confirme se a lentidão ocorre na inicialização, em um sistema específico ou durante todo o uso.',
                'Abra o Gerenciador de Tarefas e observe CPU, memória, disco e rede por cinco minutos.',
                'Verifique espaço livre e mantenha pelo menos 15% disponível no disco do sistema.',
                'Consulte a integridade SMART do SSD/HD e execute o diagnóstico do fabricante.',
                'Revise programas de inicialização, serviços desnecessários e tarefas em segundo plano.',
                'Execute verificação de malware com a solução institucional.',
                'Verifique atualizações, Visualizador de Eventos e integridade dos arquivos do Windows.',
                'Teste memória RAM e monitore temperaturas.',
                'Teste outro perfil de usuário para separar perfil e sistema.',
                'Se utilizar HD mecânico, avalie troca por SSD após autorização e backup.'
            ],
            'ferramentas' => ['Gerenciador de Tarefas', 'Ferramenta SMART', 'Diagnóstico de memória', 'Monitor de temperatura'],
            'validacao' => ['Inicialização e login ocorrem em tempo aceitável.', 'CPU, memória e disco ficam estáveis.', 'O sistema do setor abre sem travamentos.'],
            'alertas' => ['Faça backup antes de substituir ou reparar o armazenamento.', 'Não remova arquivos do usuário sem autorização.'],
            'risco' => 'Médio'
        ],
        [
            'id' => 'rede',
            'titulo' => 'Falha de conectividade de rede, DHCP ou DNS',
            'equipamentos' => ['computador', 'notebook', 'switch', 'roteador', 'telefone ip'],
            'palavras' => [
                'sem internet' => 12,
                'rede caiu' => 12,
                'sem rede' => 11,
                'nao acessa rede' => 10,
                'dns' => 7,
                'dhcp' => 7,
                'cabo de rede' => 6,
                'wifi' => 5
            ],
            'resumo' => 'A indisponibilidade pode estar no cabo, ponto de rede, configuração IP, DHCP, DNS, switch ou autenticação.',
            'causas' => [
                ['titulo' => 'Cabo, conector ou porta do switch', 'explicacao' => 'A camada física deve ser verificada antes da configuração.'],
                ['titulo' => 'Configuração IP, DHCP ou DNS', 'explicacao' => 'Endereço inválido ou falha na resolução impede o acesso.'],
                ['titulo' => 'Autenticação ou serviço central', 'explicacao' => 'Domínio, proxy, firewall ou serviço central podem afetar o setor.']
            ],
            'passos' => [
                'Confirme se a falha afeta um equipamento, um setor ou toda a rede.',
                'Verifique LEDs da placa de rede, cabo, tomada lógica e porta do switch.',
                'Teste outro cabo e outro ponto de rede conhecido.',
                'Consulte IP, máscara, gateway e DNS recebidos.',
                'Renove o DHCP e confirme se não existe endereço 169.254.x.x.',
                'Teste o endereço local, gateway e um IP externo.',
                'Teste resolução de nome para separar internet e DNS.',
                'Verifique autenticação de domínio, proxy, VPN e políticas.',
                'Confira a porta correspondente no switch e procure bloqueios ou erros.',
                'Valide sistemas internos, internet, compartilhamentos e impressão de rede.'
            ],
            'ferramentas' => ['Cabo de rede conhecido', 'Testador de cabo', 'ipconfig, ping, tracert e nslookup', 'Acesso autorizado ao switch'],
            'validacao' => ['Recebe IP válido.', 'Gateway, DNS e sistemas respondem.', 'A conexão permanece estável.'],
            'alertas' => ['Não altere switch, VLAN ou firewall sem autorização.', 'Registre toda alteração de porta ou IP.'],
            'risco' => 'Médio'
        ],
        [
            'id' => 'impressora_offline',
            'titulo' => 'Impressora offline ou sem comunicação',
            'equipamentos' => ['impressora', 'multifuncional'],
            'palavras' => [
                'offline' => 12,
                'nao imprime' => 10,
                'nao esta imprimindo' => 10,
                'fila travada' => 9,
                'spooler' => 8,
                'sem comunicacao' => 9,
                'erro ao imprimir' => 8
            ],
            'resumo' => 'A impressora pode estar indisponível por conexão, endereço IP, fila, porta ou driver.',
            'causas' => [
                ['titulo' => 'Fila ou spooler travado', 'explicacao' => 'Documentos presos impedem novos trabalhos.'],
                ['titulo' => 'Endereço IP ou porta incorreta', 'explicacao' => 'Mudança de IP deixa a impressora offline.'],
                ['titulo' => 'Driver ou comunicação física', 'explicacao' => 'Cabo, Wi-Fi ou driver incompatível interrompem a impressão.']
            ],
            'passos' => [
                'Confirme se a impressora está ligada, pronta e sem erro no painel.',
                'Imprima uma página interna de configuração.',
                'Verifique cabo USB ou rede e confirme o IP atual.',
                'Execute ping e confirme se não há duplicidade de IP.',
                'Abra a fila, cancele documentos presos e desative Usar impressora offline.',
                'Reinicie o serviço Spooler de Impressão.',
                'Confira a porta TCP/IP configurada.',
                'Instale ou atualize o driver oficial.',
                'Imprima uma página de teste do Windows.',
                'Valide a impressão pelo sistema utilizado pelo setor.'
            ],
            'ferramentas' => ['Página de configuração', 'Comando ping', 'Console de Serviços', 'Driver oficial'],
            'validacao' => ['A impressora aparece como pronta.', 'A página de teste é concluída.', 'O usuário imprime normalmente.'],
            'alertas' => ['Não remova impressora compartilhada sem registrar a configuração.', 'Não altere IP fixo sem verificar a rede.'],
            'risco' => 'Baixo'
        ],
        [
            'id' => 'impressao',
            'titulo' => 'Falha de toner, cilindro, fusor ou caminho do papel',
            'equipamentos' => ['impressora', 'multifuncional'],
            'palavras' => [
                'papel atolado' => 12,
                'atolamento' => 11,
                'mancha' => 9,
                'linhas' => 8,
                'apagada' => 8,
                'nao puxa papel' => 11,
                'toner nao reconhecido' => 11,
                'folha amassada' => 9
            ],
            'resumo' => 'A qualidade ou alimentação do papel pode estar comprometida por toner, cilindro, roletes, sensores ou fusor.',
            'causas' => [
                ['titulo' => 'Toner, cilindro ou unidade de imagem', 'explicacao' => 'Manchas e impressão apagada geralmente começam pelos suprimentos.'],
                ['titulo' => 'Roletes, sensores ou papel', 'explicacao' => 'Falha de tração e atolamento estão ligados ao caminho do papel.'],
                ['titulo' => 'Unidade fusora desgastada', 'explicacao' => 'Folha amassada, pó solto e ruído podem indicar fusor.']
            ],
            'passos' => [
                'Registre o código do painel e imprima uma página de teste interna.',
                'Retire o papel no sentido correto e procure pequenos fragmentos.',
                'Confirme tipo, tamanho, umidade e posicionamento do papel.',
                'Inspecione roletes, guias e sensores.',
                'Remova o toner e verifique vazamento, lacre, engrenagens e chip.',
                'Teste outro toner compatível e conhecido.',
                'Observe se manchas ou linhas se repetem em intervalos regulares.',
                'Inspecione cilindro, unidade de imagem e fusor sem tocar superfícies sensíveis.',
                'Limpe ou substitua somente o componente confirmado.',
                'Imprima várias páginas com texto e imagem para validar.'
            ],
            'ferramentas' => ['Toner compatível', 'Pano sem fiapos', 'Kit de limpeza', 'Manual do modelo'],
            'validacao' => ['Alimenta várias folhas sem atolamento.', 'A impressão sai uniforme e fixada.', 'O painel permanece sem erros.'],
            'alertas' => ['O fusor pode permanecer quente após desligar.', 'Não toque no cilindro fotossensível.'],
            'risco' => 'Médio'
        ],
        [
            'id' => 'acesso',
            'titulo' => 'Falha de acesso, credencial ou permissão',
            'equipamentos' => ['sistema', 'acesso', 'usuario', 'computador', 'notebook'],
            'palavras' => [
                'senha' => 7,
                'usuario bloqueado' => 12,
                'nao consegue entrar' => 10,
                'acesso negado' => 11,
                'sem permissao' => 11,
                'login' => 7,
                'credencial' => 8,
                'dominio' => 6
            ],
            'resumo' => 'A ocorrência pode envolver senha, bloqueio, permissão, domínio ou perfil local.',
            'causas' => [
                ['titulo' => 'Senha expirada ou usuário bloqueado', 'explicacao' => 'Tentativas repetidas e credenciais antigas são frequentes.'],
                ['titulo' => 'Permissão ausente', 'explicacao' => 'O usuário autentica, mas não possui o grupo necessário.'],
                ['titulo' => 'Perfil ou cache de credenciais', 'explicacao' => 'Credenciais salvas e perfil corrompido impedem o acesso.']
            ],
            'passos' => [
                'Confirme o usuário, o recurso e a mensagem exata.',
                'Verifique Caps Lock, layout do teclado e nome de usuário.',
                'Confirme conectividade com a rede e domínio.',
                'Consulte se a conta está bloqueada, desabilitada ou expirada.',
                'Desbloqueie ou redefina conforme a política e confirme a identidade.',
                'Verifique grupos, perfis e permissões.',
                'Remova credenciais antigas somente quando necessário.',
                'Teste o acesso em outro equipamento ou perfil.',
                'Preserve dados antes de reparar o perfil.',
                'Valide login e acesso ao recurso solicitado.'
            ],
            'ferramentas' => ['Console autorizado de usuários', 'Ferramenta de domínio', 'Gerenciador de Credenciais', 'Registro da identificação'],
            'validacao' => ['O usuário autentica com a própria credencial.', 'O recurso abre com a permissão correta.', 'A conta permanece desbloqueada.'],
            'alertas' => ['Nunca solicite ou registre a senha do usuário.', 'Confirme a identidade antes de redefinir credenciais.'],
            'risco' => 'Médio'
        ],
        [
            'id' => 'generico',
            'titulo' => 'Diagnóstico inicial ainda inconclusivo',
            'equipamentos' => [],
            'palavras' => [],
            'resumo' => 'A descrição não contém sintomas suficientes para apontar uma causa única. O roteiro abaixo coleta evidências e isola a origem.',
            'causas' => [
                ['titulo' => 'Falha física ou conexão', 'explicacao' => 'Cabos, alimentação e periféricos devem ser eliminados primeiro.'],
                ['titulo' => 'Configuração, software ou driver', 'explicacao' => 'A falha pode estar restrita ao sistema ou perfil.'],
                ['titulo' => 'Componente interno', 'explicacao' => 'Considere hardware depois dos testes externos.']
            ],
            'passos' => [
                'Registre a mensagem, o comportamento e o momento exato da falha.',
                'Confirme se ocorre sempre e se afeta um usuário ou vários.',
                'Verifique alimentação, cabos, conectores e indicadores.',
                'Reinicie de forma controlada e teste sem acessórios desnecessários.',
                'Reproduza o problema em outro usuário, porta, cabo ou equipamento.',
                'Consulte logs, mensagens e códigos apresentados.',
                'Verifique alterações recentes de software, driver ou ambiente.',
                'Execute os diagnósticos oficiais do fabricante.',
                'Aplique somente a correção confirmada pelos testes.',
                'Valide com o usuário e registre causa e solução na OS.'
            ],
            'ferramentas' => ['Manual do fabricante', 'Cabo ou equipamento conhecido', 'Ferramentas de diagnóstico', 'Registro detalhado dos sintomas'],
            'validacao' => ['O problema deixa de ocorrer.', 'O usuário confirma o funcionamento.', 'A causa e solução são registradas.'],
            'alertas' => ['Não formate, apague dados ou substitua peças sem confirmação.', 'Interrompa em caso de risco elétrico ou perda de dados.'],
            'risco' => 'Médio'
        ]
    ];
}

function pontuar(array $regra, string $texto, string $equipamento): array
{
    $pontos = 0;
    $evidencias = [];

    foreach ($regra['palavras'] as $palavra => $peso) {
        if (str_contains($texto, normalizar($palavra))) {
            $pontos += (int) $peso;
            $evidencias[] = $palavra;
        }
    }

    foreach ($regra['equipamentos'] as $termo) {
        if (
            str_contains($equipamento, normalizar($termo)) ||
            str_contains($texto, normalizar($termo))
        ) {
            $pontos += 5;
            break;
        }
    }

    return ['pontos' => $pontos, 'evidencias' => $evidencias];
}

$entrada = json_decode(file_get_contents('php://input') ?: '', true);

if (!is_array($entrada)) {
    $entrada = $_POST;
}

$osId = (int) ($entrada['os_id'] ?? 0);

if ($osId <= 0) {
    responder(['sucesso' => false, 'erro' => 'Identificador da OS inválido.'], 422);
}

$stmt = $mysqli->prepare('SELECT * FROM ordens_servico WHERE id = ? LIMIT 1');

if (!$stmt) {
    responder(['sucesso' => false, 'erro' => 'Não foi possível preparar a consulta.'], 500);
}

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

if (!$ordem) {
    responder(['sucesso' => false, 'erro' => 'Ordem de serviço não encontrada.'], 404);
}

$problema = trim((string) ($ordem['problema'] ?? ''));
$equipamento = trim((string) ($ordem['tipo_equipamento'] ?? ''));
$marca = trim((string) ($ordem['marca'] ?? ''));
$modelo = trim((string) ($ordem['modelo'] ?? ''));
$patrimonio = trim((string) ($ordem['patrimonio'] ?? ''));

$texto = normalizar(implode(' ', [$problema, $equipamento, $marca, $modelo]));
$equipamentoNormalizado = normalizar($equipamento);

$classificadas = [];
$generica = null;

foreach (regras() as $regra) {
    if ($regra['id'] === 'generico') {
        $generica = $regra;
        continue;
    }

    $pontuacao = pontuar($regra, $texto, $equipamentoNormalizado);
    $regra['pontos'] = $pontuacao['pontos'];
    $regra['evidencias'] = $pontuacao['evidencias'];
    $classificadas[] = $regra;
}

usort($classificadas, static fn(array $a, array $b): int => $b['pontos'] <=> $a['pontos']);

$principal = $classificadas[0] ?? $generica;

if (!$principal || (int) ($principal['pontos'] ?? 0) <= 0) {
    $principal = $generica;
    $principal['pontos'] = 0;
    $principal['evidencias'] = [];
}

$pontosPrincipal = (int) ($principal['pontos'] ?? 0);
$pontosSegundo = (int) ($classificadas[1]['pontos'] ?? 0);
$confianca = $principal['id'] === 'generico'
    ? 38
    : min(96, 44 + min(43, $pontosPrincipal * 2) + min(9, max(0, $pontosPrincipal - $pontosSegundo)));

$causas = [];

foreach ($principal['causas'] as $indice => $causa) {
    $causas[] = [
        'titulo' => $causa['titulo'],
        'explicacao' => $causa['explicacao'],
        'probabilidade' => max(18, min(95, $confianca - ($indice * 13)))
    ];
}

$historico = [];
$totalReincidencias = 0;
$abertas = 0;
$temSolucao = colunaExiste($mysqli, 'ordens_servico', 'solucao');

if ($patrimonio !== '') {
    $stmt = $mysqli->prepare("\n        SELECT *\n        FROM ordens_servico\n        WHERE patrimonio = ? AND id <> ?\n        ORDER BY data_entrada DESC\n        LIMIT 12\n    ");

    if ($stmt) {
        $stmt->bind_param('si', $patrimonio, $osId);
        $stmt->execute();
        $res = $stmt->get_result();

        while ($anterior = $res->fetch_assoc()) {
            $totalReincidencias++;

            if (!str_contains(normalizar((string) ($anterior['status'] ?? '')), 'finaliz')) {
                $abertas++;
            }

            $problemaAnterior = trim((string) ($anterior['problema'] ?? ''));
            $similaridade = similaridade($problema, $problemaAnterior);

            if ($similaridade < 14) {
                continue;
            }

            $historico[] = [
                'id' => (int) ($anterior['id'] ?? 0),
                'numero_os' => (string) ($anterior['numero_os'] ?? $anterior['id'] ?? ''),
                'problema' => $problemaAnterior,
                'solucao' => $temSolucao ? trim((string) ($anterior['solucao'] ?? '')) : '',
                'similaridade' => $similaridade
            ];
        }

        $stmt->close();
    }
}

usort($historico, static fn(array $a, array $b): int => $b['similaridade'] <=> $a['similaridade']);
$historico = array_slice($historico, 0, 4);

$alertas = $principal['alertas'];

if ($abertas > 0) {
    array_unshift($alertas, "Este patrimônio possui {$abertas} outra(s) OS aberta(s). Verifique possível duplicidade.");
}

if (
    str_contains($texto, 'ssd') ||
    str_contains($texto, 'hd') ||
    str_contains($texto, 'dados') ||
    str_contains($texto, 'format')
) {
    $alertas[] = 'Confirme o backup antes de qualquer intervenção que possa alterar dados.';
}

$resumo = $principal['resumo'];

if (!empty($principal['evidencias'])) {
    $resumo .= ' Evidências reconhecidas: ' . implode(', ', array_slice($principal['evidencias'], 0, 5)) . '.';
}

responder([
    'sucesso' => true,
    'os' => [
        'id' => $osId,
        'numero_os' => (string) ($ordem['numero_os'] ?? $osId),
        'equipamento' => $equipamento !== '' ? $equipamento : 'Não informado',
        'marca_modelo' => trim(implode(' / ', array_filter([$marca, $modelo]))) ?: 'Não informado',
        'patrimonio' => $patrimonio !== '' ? $patrimonio : 'Sem patrimônio',
        'problema' => $problema
    ],
    'diagnostico_principal' => $principal['titulo'],
    'resumo' => $resumo,
    'confianca' => $confianca,
    'nivel_risco' => $principal['risco'],
    'causas_possiveis' => $causas,
    'passos' => $principal['passos'],
    'ferramentas' => $principal['ferramentas'],
    'validacao' => $principal['validacao'],
    'alertas' => array_values(array_unique($alertas)),
    'reincidencia' => ['total' => $totalReincidencias, 'abertas' => $abertas],
    'historico_semelhante' => $historico,
    'motor' => [
        'tipo' => 'Motor técnico local por sintomas e histórico',
        'api_externa' => false,
        'internet' => false,
        'gerado_em' => date('d/m/Y H:i:s')
    ]
]);
