<?php
/**
 * ajax/notificacoes.php
 * Retorna notificações em tempo real do sistema.
 *
 * GET ?tipo=resumo  → contagem total para o badge
 * GET ?tipo=lista   → lista completa para o dropdown
 * GET ?tipo=marcar&id=X → marca uma notificação como lida
 * GET ?tipo=marcar_todas → marca todas como lidas
 */
require_once __DIR__ . '/../auth.php';
require_once __DIR__ . '/../functions.php';
requireLogin();

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

$tipo  = $_GET['tipo']  ?? 'lista';
$notId = (int)($_GET['id'] ?? 0);
$uid   = usuarioLogado()['id'];

// ── Garante tabela de notificações ──────────────────────────────
try {
    pdo()->exec("CREATE TABLE IF NOT EXISTS `notificacoes` (
        `id`          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        `usuario_id`  INT UNSIGNED DEFAULT NULL COMMENT 'NULL = todos os usuários',
        `tipo`        VARCHAR(40)  NOT NULL DEFAULT 'info'
                      COMMENT 'info|sucesso|aviso|critico',
        `titulo`      VARCHAR(120) NOT NULL,
        `mensagem`    TEXT         DEFAULT NULL,
        `link`        VARCHAR(255) DEFAULT NULL,
        `icone`       VARCHAR(10)  DEFAULT '🔔',
        `lida`        TINYINT(1)   NOT NULL DEFAULT 0,
        `criada_em`   DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP,
        INDEX `idx_uid_lida` (`usuario_id`, `lida`),
        INDEX `idx_criada`   (`criada_em`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
} catch (PDOException $e) { /* silencia se já existir */ }

// ── Gera notificações automáticas do sistema ────────────────────
function gerarNotifSistema(): void {
    try {
        $db  = pdo();
        $ago = date('Y-m-d H:i:s', strtotime('-5 minutes'));

        // Evita duplicatas recentes (não gera se já existe da mesma categoria nos últimos 5 min)
        $temRecente = fn(string $titulo) =>
            (int)$db->prepare("SELECT COUNT(*) FROM notificacoes WHERE titulo=? AND criada_em > ? AND usuario_id IS NULL")
                    ->execute([$titulo, $ago]) &&
            (int)$db->query("SELECT COUNT(*) FROM notificacoes WHERE titulo LIKE '%{$titulo}%' AND criada_em > '{$ago}'")->fetchColumn() > 0;

        // 1. OS abertas há mais de 7 dias (vencidas)
        $diasVenc = (int)(getConfig('os_vencimento_dias') ?: 7);
        $osVenc   = $db->query(
            "SELECT COUNT(*) FROM ordens_servico
             WHERE status IN ('ABERTA','AGENDADA')
             AND data_abertura < DATE_SUB(NOW(), INTERVAL {$diasVenc} DAY)"
        )->fetchColumn();
        if ($osVenc > 0) {
            $titulo = "OS vencidas";
            $existe = $db->prepare("SELECT id FROM notificacoes WHERE titulo=? AND lida=0 AND usuario_id IS NULL LIMIT 1");
            $existe->execute([$titulo]);
            if (!$existe->fetch()) {
                $db->prepare("INSERT INTO notificacoes (tipo,titulo,mensagem,link,icone) VALUES (?,?,?,?,?)")
                   ->execute(['critico', $titulo,
                     "{$osVenc} OS aberta(s) com mais de {$diasVenc} dias sem atualização.",
                     'ordens.php?status=ABERTA', '⏰']);
            }
        }

        // 2. Materiais com estoque zerado
        $matZero = $db->query(
            "SELECT nome FROM materiais WHERE quantidade_estoque = 0 LIMIT 5"
        )->fetchAll(PDO::FETCH_COLUMN);
        if ($matZero) {
            $titulo = "Estoque zerado";
            $existe = $db->prepare("SELECT id FROM notificacoes WHERE titulo=? AND lida=0 AND usuario_id IS NULL LIMIT 1");
            $existe->execute([$titulo]);
            if (!$existe->fetch()) {
                $nomes = implode(', ', $matZero);
                $db->prepare("INSERT INTO notificacoes (tipo,titulo,mensagem,link,icone) VALUES (?,?,?,?,?)")
                   ->execute(['critico', $titulo,
                     "Sem estoque: {$nomes}.",
                     'materiais.php?sit=zerado', '📦']);
            }
        }

        // 3. Materiais com estoque baixo
        $matBaixo = $db->query(
            "SELECT COUNT(*) FROM materiais WHERE quantidade_estoque > 0 AND quantidade_estoque <= alerta_minimo"
        )->fetchColumn();
        if ($matBaixo > 0) {
            $titulo = "Estoque baixo";
            $existe = $db->prepare("SELECT id FROM notificacoes WHERE titulo=? AND lida=0 AND usuario_id IS NULL LIMIT 1");
            $existe->execute([$titulo]);
            if (!$existe->fetch()) {
                $db->prepare("INSERT INTO notificacoes (tipo,titulo,mensagem,link,icone) VALUES (?,?,?,?,?)")
                   ->execute(['aviso', $titulo,
                     "{$matBaixo} material(is) abaixo do estoque mínimo.",
                     'materiais.php?sit=baixo', '⚠️']);
            }
        }

        // 4. Clientes bloqueados com OS aberta
        $cliOS = $db->query(
            "SELECT COUNT(DISTINCT os.cliente_id) FROM ordens_servico os
             JOIN clientes c ON c.id = os.cliente_id
             WHERE c.bloqueado = 1 AND os.status IN ('ABERTA','AGENDADA','EM_ANDAMENTO')"
        )->fetchColumn();
        if ($cliOS > 0) {
            $titulo = "Clientes bloqueados com OS";
            $existe = $db->prepare("SELECT id FROM notificacoes WHERE titulo=? AND lida=0 AND usuario_id IS NULL LIMIT 1");
            $existe->execute([$titulo]);
            if (!$existe->fetch()) {
                $db->prepare("INSERT INTO notificacoes (tipo,titulo,mensagem,link,icone) VALUES (?,?,?,?,?)")
                   ->execute(['aviso', $titulo,
                     "{$cliOS} cliente(s) bloqueado(s) com ordens de serviço em aberto.",
                     'clientes.php?status=bloqueado', '🚫']);
            }
        }

    } catch (Throwable $e) { /* silencia erros de sistema */ }
}

// ── MARCAR UMA COMO LIDA ────────────────────────────────────────
if ($tipo === 'marcar' && $notId > 0) {
    pdo()->prepare("UPDATE notificacoes SET lida=1 WHERE id=?")->execute([$notId]);
    echo json_encode(['ok' => true]);
    exit;
}

// ── MARCAR TODAS COMO LIDAS ─────────────────────────────────────
if ($tipo === 'marcar_todas') {
    pdo()->exec("UPDATE notificacoes SET lida=1 WHERE lida=0");
    echo json_encode(['ok' => true]);
    exit;
}

// ── NOVA NOTIFICAÇÃO MANUAL ─────────────────────────────────────
if ($tipo === 'nova' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true) ?? $_POST;
    pdo()->prepare("INSERT INTO notificacoes (usuario_id,tipo,titulo,mensagem,link,icone) VALUES (?,?,?,?,?,?)")
         ->execute([
             !empty($input['usuario_id']) ? (int)$input['usuario_id'] : null,
             $input['tipo']     ?? 'info',
             $input['titulo']   ?? 'Notificação',
             $input['mensagem'] ?? null,
             $input['link']     ?? null,
             $input['icone']    ?? '🔔',
         ]);
    echo json_encode(['ok' => true]);
    exit;
}

// ── GERA NOTIFICAÇÕES AUTOMÁTICAS (a cada chamada) ──────────────
gerarNotifSistema();

// ── BUSCA NOTIFICAÇÕES ──────────────────────────────────────────
$notifs = pdo()->prepare(
    "SELECT * FROM notificacoes
     WHERE (usuario_id IS NULL OR usuario_id = ?)
       AND lida = 0
     ORDER BY
       CASE tipo WHEN 'critico' THEN 1 WHEN 'aviso' THEN 2 ELSE 3 END,
       criada_em DESC
     LIMIT 20"
);
$notifs->execute([$uid]);
$lista = $notifs->fetchAll();

$naoLidas = count($lista);

// ── RESUMO APENAS ───────────────────────────────────────────────
if ($tipo === 'resumo') {
    echo json_encode(['total' => $naoLidas]);
    exit;
}

// ── LISTA COMPLETA ──────────────────────────────────────────────
$corTipo = [
    'critico' => '#ef4444',
    'aviso'   => '#f59e0b',
    'sucesso' => '#10b981',
    'info'    => '#00d4ff',
];

$items = array_map(fn($n) => [
    'id'       => $n['id'],
    'tipo'     => $n['tipo'],
    'cor'      => $corTipo[$n['tipo']] ?? '#00d4ff',
    'icone'    => $n['icone'],
    'titulo'   => $n['titulo'],
    'mensagem' => $n['mensagem'],
    'link'     => $n['link'],
    'tempo'    => tempoRelativo($n['criada_em']),
], $lista);

echo json_encode([
    'ok'       => true,
    'total'    => $naoLidas,
    'notifs'   => $items,
]);

// ── Helper tempo relativo ────────────────────────────────────────
function tempoRelativo(?string $dt): string {
    if (!$dt) return '';
    $diff = time() - strtotime($dt);
    if ($diff < 60)     return 'agora';
    if ($diff < 3600)   return round($diff/60) . ' min atrás';
    if ($diff < 86400)  return round($diff/3600) . 'h atrás';
    return date('d/m H:i', strtotime($dt));
}
