let db;
let settingsModule;
let lastUpdateId = 0;
let pollingTimeout = null;

let pollErrorCount = 0;
let lastPollErrorKey = null;
let pollingFatalLogged = false;
let pollingActiveLogged = false;

let lastSendErrors = {};
let connectionMode = null;
let connectionLoggedKey = null;

const DEFAULT_API = 'https://api.telegram.org';

function init(database, settings) {
    db = database;
    settingsModule = settings;
}

function getSettings(callback) {
    settingsModule.getAll((err, all) => {
        if (err) return callback(err);
        callback(null, all);
    });
}

function isNetworkError(err) {
    const msg = (err.message || '').toLowerCase();
    return msg.includes('econnrefused') || msg.includes('etimedout') ||
           msg.includes('enotfound') || msg.includes('fetch failed') ||
           msg.includes('network') || err.name === 'TypeError' ||
           err.cause !== undefined;
}

function apiCall(settings, method, body, callback) {
    const token = settings.telegram_bot_token;
    const apiUrl = (settings.telegram_api_url || DEFAULT_API).replace(/\/+$/, '');
    const proxyUrl = apiUrl !== DEFAULT_API ? apiUrl : null;
    const urlsToTry = proxyUrl ? [proxyUrl, DEFAULT_API] : [DEFAULT_API];

    function tryNext(index) {
        if (index >= urlsToTry.length) {
            return callback(new Error('Telegram недоступен: все адреса недоступны'));
        }

        const url = urlsToTry[index];
        const fullUrl = `${url}/bot${token}/${method}`;
        const fetchOpts = body ? {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(body)
        } : {};

        fetch(fullUrl, fetchOpts)
        .then(res => res.json().then(data => ({ status: res.status, data })))
        .then(result => {
            const data = result.data;

            if (!data.ok) {
                const err = new Error(data.description);
                err.code = data.error_code;
                err.fromProxy = url !== DEFAULT_API;
                return callback(err);
            }

            if (url !== DEFAULT_API) {
                updateConnectionMode('proxied', url);
            } else {
                updateConnectionMode('direct', null);
            }

            callback(null, data);
        })
        .catch(fetchErr => {
            if (isNetworkError(fetchErr) && index < urlsToTry.length - 1) {
                tryNext(index + 1);
            } else if (isNetworkError(fetchErr)) {
                updateConnectionMode('blocked', null);
                callback(fetchErr);
            } else {
                callback(fetchErr);
            }
        });
    }

    tryNext(0);
}

function updateConnectionMode(mode, proxyUrl) {
    const key = mode + (proxyUrl || '');
    if (connectionLoggedKey === key) return;
    connectionLoggedKey = key;
    connectionMode = mode;

    if (mode === 'direct') {
        console.log('Telegram подключён напрямую');
    } else if (mode === 'proxied') {
        console.log(`Telegram подключён через прокси-сервер: ${proxyUrl}`);
    } else if (mode === 'blocked') {
        console.error('Telegram заблокирован. Укажите прокси-URL в настройках Telegram.');
    }
}

function sendMessage(token, chatId, text, callback) {
    getSettings((err, settings) => {
        if (err) {
            if (callback) callback(err);
            return;
        }
        apiCall(settings, 'sendMessage', { chat_id: chatId, text: text, parse_mode: 'HTML' }, (err, data) => {
            if (!err) {
                if (callback) callback(null, data);
                return;
            }
            if (!err.code) {
                const key = `network:${chatId}`;
                if (lastSendErrors[key] !== true) {
                    lastSendErrors[key] = true;
                    console.error(`Telegram sendMessage: chat ${chatId} — ${err.message}`);
                }
            } else {
                const key = `${chatId}:${err.code}:${err.message}`;
                if (lastSendErrors[key] !== true) {
                    lastSendErrors[key] = true;
                    console.error(`Telegram sendMessage: chat ${chatId} — ${err.message}`);
                }
            }
            if (callback) callback(err);
        });
    });
}

function sendBookingNotification(booking) {
    if (!booking.phone) return;
    getSettings((err, settings) => {
        if (err || settings.telegram_notify_enabled !== 'true') return;
        const token = settings.telegram_bot_token;
        if (!token) return;
        const usersStr = settings.telegram_notify_users || '';
        const chatIds = usersStr.split(',').map(s => s.trim()).filter(s => s);
        if (chatIds.length === 0) return;

        const text = [
            '<b>Hotel 777 — Новая бронь</b>',
            '',
            `<b>Имя:</b> ${escapeHtml(booking.name)}`,
            `<b>Телефон:</b> ${escapeHtml(booking.phone)}`,
            `<b>Номер:</b> ${escapeHtml(booking.room_type || '—')}`,
            `<b>Гостей:</b> ${booking.adults} взр.${booking.children ? ', ' + booking.children + ' дет.' : ''}`,
            `<b>Заезд:</b> ${escapeHtml(booking.checkin_date)}`,
            `<b>Выезд:</b> ${escapeHtml(booking.checkout_date)}`,
            `<b>Сумма:</b> ${booking.total_price || booking.base_price || 0} ₽`,
        ];

        if (booking.wishes) {
            text.push(`<b>Пожелания:</b> ${escapeHtml(booking.wishes)}`);
        }

        text.push('');
        text.push('<a href="https://hotel777.ru/admin">Перейти в админ-панель</a>');

        const message = text.join('\n');

        chatIds.forEach(chatId => {
            sendMessage(token, chatId, message);
        });
    });
}

function escapeHtml(str) {
    if (!str) return '';
    return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

function startPolling() {
    getSettings((err, settings) => {
        if (err || !settings.telegram_bot_token) {
            schedulePolling(60000);
            return;
        }
        const token = settings.telegram_bot_token;

        apiCall(settings, `getUpdates?offset=${lastUpdateId + 1}&timeout=10`, null, (err, data) => {
            if (err) {
                if (err.code === 404) {
                    if (!pollingFatalLogged) {
                        pollingFatalLogged = true;
                        console.error(`Telegram polling: бот не найден — ${err.message}. Polling остановлен до смены токена.`);
                    }
                    return;
                }

                if (err.code) {
                    pollErrorCount++;
                    const backoff = Math.min(5000 * Math.pow(2, pollErrorCount - 1), 300000);
                    const errKey = `${err.code}:${err.message}`;
                    if (lastPollErrorKey !== errKey) {
                        lastPollErrorKey = errKey;
                        console.error(`Telegram polling: ${err.message}`);
                    }
                    schedulePolling(backoff);
                    return;
                }

                pollErrorCount++;
                const backoff = Math.min(5000 * Math.pow(2, pollErrorCount - 1), 300000);
                const errKey = `network:${err.message}`;
                if (lastPollErrorKey !== errKey) {
                    lastPollErrorKey = errKey;
                }
                schedulePolling(backoff);
                return;
            }

            pollErrorCount = 0;
            lastPollErrorKey = null;

            if (!pollingActiveLogged) {
                pollingActiveLogged = true;
                const modeText = connectionMode === 'proxied' ? ' (через прокси)' : '';
                console.log(`Telegram polling active — бот слушает сообщения${modeText}`);
            }

            if (data.result && data.result.length > 0) {
                data.result.forEach(update => {
                    lastUpdateId = update.update_id;
                    if (update.message && update.message.text && update.message.chat) {
                        const chatId = update.message.chat.id;
                        const replyText = `<b>Ваш chat_id:</b> <code>${chatId}</code>\n\nДобавьте его в настройках админ-панели Hotel 777 для получения уведомлений о новых заявках.`;
                        sendMessage(token, chatId, replyText);
                    }
                });
            }
            schedulePolling(1000);
        });
    });
}

function schedulePolling(ms) {
    if (pollingTimeout) clearTimeout(pollingTimeout);
    pollingTimeout = setTimeout(startPolling, ms);
}

function stopPolling() {
    if (pollingTimeout) {
        clearTimeout(pollingTimeout);
        pollingTimeout = null;
    }
}

function resetPollState() {
    stopPolling();
    lastUpdateId = 0;
    pollErrorCount = 0;
    lastPollErrorKey = null;
    pollingFatalLogged = false;
    pollingActiveLogged = false;
    lastSendErrors = {};
    connectionMode = null;
    connectionLoggedKey = null;
    startPolling();
}

function sendTestMessage(settings, callback) {
    const token = settings.telegram_bot_token;
    if (!token) return callback(new Error('Токен бота не настроен'));
    const usersStr = settings.telegram_notify_users || '';
    const chatIds = usersStr.split(',').map(s => s.trim()).filter(s => s);
    if (chatIds.length === 0) return callback(new Error('Не указаны chat_id получателей'));

    let sent = 0;
    let errors = [];

    chatIds.forEach((chatId, index) => {
        sendMessage(token, chatId, '<b>Hotel 777</b> — Тестовое уведомление Telegram. Бот работает корректно.', (err) => {
            if (err) {
                let errText = err.message;
                if (!err.code) errText = `${errText} (проверьте подключение или укажите прокси-URL)`;
                errors.push(`chat_id ${chatId}: ${errText}`);
            } else {
                sent++;
            }
            if (index === chatIds.length - 1) {
                if (errors.length > 0) {
                    callback(null, { sent, total: chatIds.length, errors });
                } else {
                    callback(null, { sent, total: chatIds.length, errors: [] });
                }
            }
        });
    });
}

function setupRoutes(app, authenticateToken, requireAdmin) {
    app.get('/api/admin/settings/telegram', authenticateToken, requireAdmin, (req, res) => {
        getSettings((err, settings) => {
            if (err) return res.status(500).json({ error: 'Database error' });
            const token = settings.telegram_bot_token || '';
            res.json({
                telegram_bot_token_masked: token ? maskToken(token) : '',
                telegram_notify_enabled: settings.telegram_notify_enabled || 'false',
                telegram_notify_users: settings.telegram_notify_users || '',
                telegram_api_url: settings.telegram_api_url || DEFAULT_API,
                telegram_proxy_status: connectionMode || 'unknown'
            });
        });
    });

    app.put('/api/admin/settings/telegram', authenticateToken, requireAdmin, (req, res) => {
        const { telegram_bot_token, telegram_notify_enabled, telegram_notify_users, telegram_api_url } = req.body;
        const updates = [];

        if (telegram_bot_token !== undefined && !(telegram_bot_token || '').startsWith('****')) {
            updates.push(['telegram_bot_token', telegram_bot_token]);
        }
        if (telegram_notify_enabled !== undefined) {
            updates.push(['telegram_notify_enabled', telegram_notify_enabled]);
        }
        if (telegram_notify_users !== undefined) {
            updates.push(['telegram_notify_users', telegram_notify_users]);
        }
        if (telegram_api_url !== undefined) {
            const url = (telegram_api_url || '').trim();
            updates.push(['telegram_api_url', url || DEFAULT_API]);
        }

        let processed = 0;
        if (updates.length === 0) return res.json({ message: 'No changes' });

        updates.forEach(([key, value]) => {
            settingsModule.set(key, value, (err) => {
                if (err) console.error('Telegram settings update error:', err);
                processed++;
                if (processed === updates.length) {
                    res.json({ message: 'Настройки Telegram сохранены' });
                    resetPollState();
                }
            });
        });
    });

    app.post('/api/admin/settings/telegram/test', authenticateToken, requireAdmin, (req, res) => {
        getSettings((err, settings) => {
            if (err) return res.status(500).json({ error: 'Database error' });
            sendTestMessage(settings, (sendErr, result) => {
                if (sendErr) return res.status(400).json({ error: sendErr.message });
                if (result.errors.length > 0) {
                    return res.json({
                        message: `Отправлено ${result.sent} из ${result.total}. Ошибки: ${result.errors.join('; ')}`,
                        sent: result.sent,
                        total: result.total
                    });
                }
                res.json({ message: `Тестовое сообщение отправлено (${result.sent}/${result.total})` });
            });
        });
    });
}

function maskToken(val) {
    if (!val) return '';
    const parts = val.split(':');
    if (parts.length === 2) {
        const idPart = parts[0];
        const hashPart = parts[1];
        if (hashPart.length <= 4) return '****';
        return idPart.slice(0, 3) + '***:' + '****' + hashPart.slice(-4);
    }
    return '****';
}

module.exports = { init, setupRoutes, sendBookingNotification, sendTestMessage, startPolling, stopPolling, connectionMode };
