/**
 * Dev-log клиент — шлёт логи на локальный HTTP-сервер на localhost:8765.
 *
 * Полезно когда нужно собирать console.* логи из браузера в файл для
 * последующего просмотра (например при отладке вместе с AI-ассистентом).
 *
 * Активен только на localhost. На любом другом хосте запросы тихо
 * игнорируются (если devlog-сервер не запущен).
 *
 * Простой devlog-сервер можно собрать за 30 строк на Python/Node.js —
 * принимать POST /log с JSON-body и писать в файл.
 *
 * Использование:
 *   import { devlog, attachConsoleHook } from './devlog';
 *   devlog('info', 'PerfReport', { fps: 30, triangles: 5000000 });
 *   attachConsoleHook();   // перехват console.log/warn/error
 */

const DEVLOG_URL = 'http://localhost:8765/log';
const RESET_URL = 'http://localhost:8765/reset';

// Активируем только в development (localhost)
const isDev = typeof window !== 'undefined'
    && (window.location.hostname === 'localhost'
        || window.location.hostname === '127.0.0.1');

let devlogEnabled = isDev;
let pendingTimer = null;
const pendingQueue = [];

/**
 * Отправить одну запись в devlog. Не блокирует — fire-and-forget.
 * Запросы батчатся (флашатся через 200мс), чтобы не спамить сервер.
 */
export function devlog(level, msg, data) {
    if (!devlogEnabled) return;
    pendingQueue.push({ level, msg, data });
    if (!pendingTimer) {
        pendingTimer = setTimeout(flushQueue, 200);
    }
}

function flushQueue() {
    pendingTimer = null;
    if (!devlogEnabled) { pendingQueue.length = 0; return; }
    if (pendingQueue.length === 0) return;
    const batch = pendingQueue.splice(0, pendingQueue.length);
    // ВАЖНО: шлём ОДИН POST на весь батч, а не N штук. Раньше цикл
    // запускал все fetch сразу — а devlogEnabled=false из .catch()
    // выставлялся асинхронно уже после вылета всех 50 запросов, и
    // консоль засорялась десятками ERR_CONNECTION_REFUSED. Теперь —
    // один запрос: упал → один лог в консоли → devlog навсегда выключен.
    try {
        fetch(DEVLOG_URL, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            // Сервер принимает либо одиночную запись, либо массив.
            body: JSON.stringify(batch.length === 1 ? batch[0] : batch),
            // keepalive чтобы запрос не отменился при уходе со страницы
            keepalive: true,
        }).catch(() => {
            // Сервер не запущен — глушим devlog навсегда (один раз).
            devlogEnabled = false;
            pendingQueue.length = 0;
        });
    } catch (e) {
        devlogEnabled = false;
    }
}

/**
 * Сбросить лог-файл (очистить). Вызывать перед новым тестом.
 */
export function devlogReset() {
    if (!devlogEnabled) return;
    try {
        fetch(RESET_URL, { method: 'POST', keepalive: true })
            .catch(() => { devlogEnabled = false; });
    } catch (e) { /* ignore */ }
}

/**
 * Подключить перехват console.log/warn/error/info — все логи будут
 * автоматически попадать в devlog.txt. Безопасно вызывать многократно
 * (повторный вызов — no-op).
 */
let consoleHooked = false;
export function attachConsoleHook() {
    if (!devlogEnabled || consoleHooked) return;
    consoleHooked = true;
    const original = {
        log: console.log,
        warn: console.warn,
        error: console.error,
        info: console.info,
    };
    const formatArg = (arg) => {
        if (arg === null || arg === undefined) return String(arg);
        if (typeof arg === 'string') return arg;
        if (typeof arg === 'number' || typeof arg === 'boolean') return String(arg);
        if (arg instanceof Error) return `${arg.name}: ${arg.message}\n${arg.stack || ''}`;
        try {
            return JSON.stringify(arg, (key, value) => {
                // Защита от циклических ссылок и больших объектов Babylon
                if (typeof value === 'object' && value !== null) {
                    if (value.constructor?.name === 'Scene') return '[Babylon.Scene]';
                    if (value.constructor?.name === 'Mesh') return `[Mesh ${value.name}]`;
                    if (value.constructor?.name === 'Engine') return '[Babylon.Engine]';
                }
                return value;
            }, 0);
        } catch (e) {
            return String(arg);
        }
    };
    // Высокочастотные сообщения от engine (R15Animator update — 60Hz,
    // PerfReport — 0.5Hz но огромный JSON, etc.) НЕ нужно слать на
    // devlog-сервер: они сериализуются (JSON.stringify Babylon-объектов
    // дорого), батчатся в POST на localhost:8765, каждый batch блокирует
    // main thread → лагает игра. В оригинальной консоли они ПО-ПРЕЖНЕМУ
    // показываются (originalFn.apply ниже не фильтрует).
    //
    // Если потребуется ловить такие сообщения для диагностики — временно
    // закомментировать NOISY_FILTER. ERROR/warn никогда не фильтруем.
    const NOISY_PATTERNS = [
        // ВРЕМЕННО: PerfReport включён для диагностики лагов GD prod.
        // /^\[PerfReport\]/,
        /^\[R15Animator\]/,
        /^\[SmoothDecoManager\] (loaded|loadFromState|\w+: Y=)/,
        /^\[BabylonScene\] enterPlayMode/,
        /^\[GameRuntime\] start called with scripts/,
    ];
    const isNoisy = (level, msg) => {
        if (level === 'warn' || level === 'error') return false;
        for (const p of NOISY_PATTERNS) if (p.test(msg)) return true;
        return false;
    };

    const hook = (level, originalFn) => (...args) => {
        try {
            const formatted = args.map(formatArg).join(' ');
            if (!isNoisy(level, formatted)) {
                devlog(level, formatted);
            }
        } catch (e) { /* ignore */ }
        try { originalFn.apply(console, args); } catch (e) {}
    };
    console.log = hook('log', original.log);
    console.warn = hook('warn', original.warn);
    console.error = hook('error', original.error);
    console.info = hook('info', original.info);
}

// Глобальные хелперы для ручного дёрганья из консоли DevTools
if (typeof window !== 'undefined' && isDev) {
    window.__devlog = devlog;
    window.__devlogReset = devlogReset;
    window.__devlogAttach = attachConsoleHook;
}
