<?php
declare(strict_types=1);

require_once __DIR__ . '/auth.php';

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

require_once __DIR__ . '/alerta_global_helpers.php';

date_default_timezone_set('America/Sao_Paulo');

function alertaResponder(
    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 alertaValidarCsrf(): void
{
    $recebido = (string) (
        $_POST['csrf_token'] ?? ''
    );

    $sessao = (string) (
        $_SESSION['csrf_alerta_global'] ?? ''
    );

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

function alertaExigirAdmin(): void
{
    if (!alertaUsuarioEhAdmin()) {
        alertaResponder([
            'ok' => false,
            'message' =>
                'Somente o administrador pode executar esta ação.'
        ], 403);
    }
}

function alertaPresencasAtivas(
    array $dados,
    int $alertaId,
    int $agora
): int {
    $total = 0;

    foreach ((array) ($dados['presencas'] ?? []) as $presenca) {
        if (
            (int) ($presenca['alerta_id'] ?? 0) !==
            $alertaId
        ) {
            continue;
        }

        $ultimoPing = (int) (
            $presenca['ultimo_ping_timestamp'] ?? 0
        );

        if ($ultimoPing >= ($agora - 8)) {
            $total++;
        }
    }

    return $total;
}

function alertaRemoverPresencasAntigas(
    array &$dados,
    int $agora
): void {
    $limite = $agora - 3600;

    $dados['presencas'] = array_filter(
        (array) ($dados['presencas'] ?? []),
        static function (array $presenca) use ($limite): bool {
            return (int) (
                $presenca['ultimo_ping_timestamp'] ?? 0
            ) >= $limite;
        }
    );
}

$acao = trim((string) (
    $_REQUEST['acao'] ?? 'status'
));

try {
    alertaEncerrarExpirados();
} catch (Throwable $erro) {
    alertaResponder([
        'ok' => false,
        'message' =>
            'O armazenamento do Alerta Global não está disponível: ' .
            $erro->getMessage()
    ], 500);
}

if ($acao === 'status') {
    try {
        $retorno = alertaStorageAlterar(
            static function (array &$dados): array {
                $agora = time();
                $alerta = $dados['ativo'] ?? null;

                alertaRemoverPresencasAntigas(
                    $dados,
                    $agora
                );

                if (!is_array($alerta)) {
                    return [
                        'ativo' => false
                    ];
                }

                $alertaId = (int) ($alerta['id'] ?? 0);
                $clienteHash = alertaClienteHash();

                $dados['presencas'][$clienteHash] = [
                    'alerta_id' => $alertaId,
                    'cliente_hash' => $clienteHash,
                    'usuario' => alertaLimitarTexto(
                        alertaUsuarioAtual(),
                        150
                    ),
                    'pagina' => alertaLimitarTexto(
                        (string) ($_REQUEST['pagina'] ?? ''),
                        220
                    ),
                    'ultimo_ping' => alertaAgoraBanco($agora),
                    'ultimo_ping_timestamp' => $agora
                ];

                $expiraTimestamp = (int) (
                    $alerta['expira_timestamp'] ?? 0
                );

                $segundosRestantes = max(
                    0,
                    $expiraTimestamp - $agora
                );

                $alcancados = alertaPresencasAtivas(
                    $dados,
                    $alertaId,
                    $agora
                );

                return [
                    'ativo' => true,
                    'alerta' => [
                        'id' => $alertaId,
                        'titulo' => (string) (
                            $alerta['titulo'] ?? ''
                        ),
                        'mensagem' => (string) (
                            $alerta['mensagem'] ?? ''
                        ),
                        'tipo' => (string) (
                            $alerta['tipo'] ?? 'TESTE'
                        ),
                        'som' => (string) (
                            $alerta['som'] ?? 'NUCLEAR'
                        ),
                        'frase_falada' => (string) (
                            $alerta['frase_falada'] ??
                            (
                                ($alerta['titulo'] ?? '') .
                                '. ' .
                                ($alerta['mensagem'] ?? '')
                            )
                        ),
                        'voz_estilo' => (string) (
                            $alerta['voz_estilo'] ?? 'GRAVE'
                        ),
                        'criado_por' => (string) (
                            $alerta['criado_por'] ??
                            'Administrador'
                        ),
                        'criado_em' => (string) (
                            $alerta['criado_em'] ?? ''
                        ),
                        'expira_em' => (string) (
                            $alerta['expira_em'] ?? ''
                        ),
                        'duracao_segundos' => (int) (
                            $alerta['duracao_segundos'] ?? 30
                        ),
                        'segundos_restantes' =>
                            $segundosRestantes,
                        'alcancados' => $alcancados
                    ]
                ];
            }
        );
    } catch (Throwable $erro) {
        alertaResponder([
            'ok' => false,
            'message' => $erro->getMessage()
        ], 500);
    }

    alertaResponder([
        'ok' => true,
        'ativo' => (bool) ($retorno['ativo'] ?? false),
        'admin' => alertaUsuarioEhAdmin(),
        'alerta' => $retorno['alerta'] ?? null,
        'servidor_em' => alertaAgoraBanco()
    ]);
}

if ($acao === 'historico') {
    alertaExigirAdmin();

    try {
        $dados = alertaStorageLer();
    } catch (Throwable $erro) {
        alertaResponder([
            'ok' => false,
            'message' => $erro->getMessage()
        ], 500);
    }

    alertaResponder([
        'ok' => true,
        'historico' => array_values(
            array_slice(
                (array) ($dados['historico'] ?? []),
                0,
                20
            )
        )
    ]);
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    alertaResponder([
        'ok' => false,
        'message' => 'Método não permitido.'
    ], 405);
}

alertaExigirAdmin();
alertaValidarCsrf();

if ($acao === 'disparar') {
    $tiposPermitidos = [
        'TESTE',
        'TECNOLOGICO',
        'PEGADINHA',
        'URGENTE'
    ];

    $tipo = strtoupper(
        trim((string) ($_POST['tipo'] ?? 'TESTE'))
    );

    if (!in_array($tipo, $tiposPermitidos, true)) {
        $tipo = 'TESTE';
    }

    $sonsPermitidos = [
        'NUCLEAR',
        'APOCALIPTICA',
        'INDUSTRIAL',
        'ALERTA_VERMELHO',
        'CYBER'
    ];

    $som = strtoupper(
        trim((string) ($_POST['som'] ?? 'NUCLEAR'))
    );

    if (!in_array($som, $sonsPermitidos, true)) {
        $som = 'NUCLEAR';
    }

    $vozesPermitidas = [
        'GRAVE',
        'ROBOTICA',
        'COMANDO',
        'PADRAO'
    ];

    $vozEstilo = strtoupper(
        trim((string) ($_POST['voz_estilo'] ?? 'GRAVE'))
    );

    if (!in_array($vozEstilo, $vozesPermitidas, true)) {
        $vozEstilo = 'GRAVE';
    }

    $fraseFalada = alertaLimitarTexto(
        (string) ($_POST['frase_falada'] ?? ''),
        500
    );

    $titulo = alertaLimitarTexto(
        (string) ($_POST['titulo'] ?? ''),
        150
    );

    $mensagem = alertaLimitarTexto(
        (string) ($_POST['mensagem'] ?? ''),
        500
    );

    $duracao = (int) (
        $_POST['duracao_segundos'] ?? 30
    );

    $duracao = min(180, max(15, $duracao));

    if ($titulo === '') {
        alertaResponder([
            'ok' => false,
            'message' => 'Informe o título do alerta.'
        ], 422);
    }

    if ($mensagem === '') {
        alertaResponder([
            'ok' => false,
            'message' => 'Informe a mensagem do alerta.'
        ], 422);
    }

    if ($fraseFalada === '') {
        $fraseFalada = $titulo . '. ' . $mensagem;
    }

    $usuario = alertaLimitarTexto(
        alertaUsuarioAtual(),
        150
    );

    try {
        $alertaId = alertaStorageAlterar(
            static function (array &$dados) use (
                $tipo,
                $som,
                $vozEstilo,
                $fraseFalada,
                $titulo,
                $mensagem,
                $duracao,
                $usuario
            ): int {
                $agora = time();

                if (is_array($dados['ativo'] ?? null)) {
                    alertaEncerrarNoStorage(
                        $dados,
                        $usuario,
                        $agora
                    );
                }

                $id = max(
                    1,
                    (int) ($dados['proximo_id'] ?? 1)
                );

                $dados['proximo_id'] = $id + 1;

                $alerta = [
                    'id' => $id,
                    'titulo' => $titulo,
                    'mensagem' => $mensagem,
                    'tipo' => $tipo,
                    'som' => $som,
                    'frase_falada' => $fraseFalada,
                    'voz_estilo' => $vozEstilo,
                    'ativo' => 1,
                    'duracao_segundos' => $duracao,
                    'criado_por' => $usuario,
                    'criado_em' => alertaAgoraBanco($agora),
                    'criado_timestamp' => $agora,
                    'expira_em' => alertaAgoraBanco(
                        $agora + $duracao
                    ),
                    'expira_timestamp' => $agora + $duracao,
                    'encerrado_por' => null,
                    'encerrado_em' => null,
                    'ip_criacao' => alertaIpAtual(),
                    'alcancados_total' => 0
                ];

                $dados['ativo'] = $alerta;

                array_unshift(
                    $dados['historico'],
                    $alerta
                );

                $dados['historico'] = array_slice(
                    $dados['historico'],
                    0,
                    20
                );

                $dados['presencas'] = [];

                return $id;
            }
        );
    } catch (Throwable $erro) {
        alertaResponder([
            'ok' => false,
            'message' => $erro->getMessage()
        ], 500);
    }

    alertaResponder([
        'ok' => true,
        'message' =>
            'Alerta global disparado em todas as telas abertas.',
        'alerta_id' => $alertaId
    ]);
}

if ($acao === 'desarmar') {
    $usuario = alertaLimitarTexto(
        alertaUsuarioAtual(),
        150
    );

    try {
        $alterado = alertaStorageAlterar(
            static function (array &$dados) use ($usuario): bool {
                return alertaEncerrarNoStorage(
                    $dados,
                    $usuario
                );
            }
        );
    } catch (Throwable $erro) {
        alertaResponder([
            'ok' => false,
            'message' => $erro->getMessage()
        ], 500);
    }

    alertaResponder([
        'ok' => true,
        'message' => $alterado
            ? 'Alerta global desarmado.'
            : 'Nenhum alerta estava ativo.'
    ]);
}

alertaResponder([
    'ok' => false,
    'message' => 'Ação inválida.'
], 422);
