let db;
let settingsModule;
let emailModule;
let telegramModule;

let jwt = null;
let syncTimer = null;
let running = false;

const PRIMARY_URL = (process.env.PRIMARY_URL || '').replace(/\/+$/, '');
const PRIMARY_LOGIN = process.env.PRIMARY_LOGIN || '';
const PRIMARY_PASSWORD = process.env.PRIMARY_PASSWORD || '';
const PRIMARY_SYNC_INTERVAL = parseInt(process.env.PRIMARY_SYNC_INTERVAL) || 60;

function init(database, settings, email, telegram) {
    db = database;
    settingsModule = settings;
    emailModule = email;
    telegramModule = telegram;
}

function start() {
    if (!PRIMARY_URL || !PRIMARY_LOGIN || !PRIMARY_PASSWORD) {
        console.log('[SYNC] PRIMARY_URL/LOGIN/PASSWORD not set — replica mode disabled');
        return;
    }
    console.log(`[SYNC] Replica mode: pulling from ${PRIMARY_URL} every ${PRIMARY_SYNC_INTERVAL}s`);
    loginAndSync();
}

function stop() {
    running = false;
    if (syncTimer) {
        clearTimeout(syncTimer);
        syncTimer = null;
    }
}

function loginAndSync() {
    login((err) => {
        if (err) {
            console.error(`[SYNC] Login failed: ${err.message}. Retrying in 30s...`);
            syncTimer = setTimeout(loginAndSync, 30000);
            return;
        }
        running = true;
        settingsModule.get('sync_first_sync_done', (err, val) => {
            if (err || val !== 'true') {
                firstSync();
            } else {
                syncLoop();
            }
        });
    });
}

function login(callback) {
    fetch(`${PRIMARY_URL}/api/auth/login`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ login: PRIMARY_LOGIN, password: PRIMARY_PASSWORD })
    })
    .then(res => {
        if (!res.ok) return res.json().then(d => { throw new Error(`HTTP ${res.status}: ${d.error || 'unknown'}`); });
        return res.json();
    })
    .then(data => {
        jwt = data.token;
        console.log('[SYNC] Logged in to primary server');
        callback(null);
    })
    .catch(err => {
        callback(err);
    });
}

function firstSync() {
    console.log('[SYNC] First sync — pulling ALL bookings...');
    apiGet('/api/admin/bookings?limit=99999', (err, result) => {
        if (err) {
            console.error(`[SYNC] First sync failed: ${err.message}. Retrying in 30s...`);
            syncTimer = setTimeout(firstSync, 30000);
            return;
        }
        const bookings = result.data || [];
        insertBatch(bookings, false, (insertCount) => {
            console.log(`[SYNC] First sync done: ${insertCount} bookings imported (no notifications)`);
            settingsModule.set('sync_first_sync_done', 'true', (err) => {
                if (err) console.error('[SYNC] Failed to save sync_first_sync_done:', err);
            });
            saveLastSync(() => {
                scheduleNext();
            });
        });
    });
}

function syncLoop() {
    settingsModule.get('sync_last_sync_at', (err, lastSyncAt) => {
        if (err) {
            console.error('[SYNC] Failed to read last_sync_at:', err);
            scheduleNext();
            return;
        }
        const since = lastSyncAt ? encodeURIComponent(lastSyncAt) : '';
        const url = since ? `/api/admin/bookings?limit=99999&since=${since}` : '/api/admin/bookings?limit=99999';

        apiGet(url, (err, result) => {
            if (err) {
                if (err.message.includes('401') || err.message.includes('token') || err.message.includes('jwt')) {
                    console.log('[SYNC] Token expired, re-logging in...');
                    loginAndSync();
                    return;
                }
                console.error(`[SYNC] Sync failed: ${err.message}. Retry at next interval.`);
                scheduleNext();
                return;
            }
            const bookings = result.data || [];
            if (bookings.length === 0) {
                saveLastSync(() => scheduleNext());
                return;
            }

            insertBatch(bookings, true, (insertCount, notifyCount) => {
                console.log(`[SYNC] Pulled ${bookings.length}, new: ${insertCount}, notified: ${notifyCount}`);
                saveLastSync(() => scheduleNext());
            });
        });
    });
}

function scheduleNext() {
    if (!running) return;
    syncTimer = setTimeout(syncLoop, PRIMARY_SYNC_INTERVAL * 1000);
}

function saveLastSync(callback) {
    const now = new Date().toISOString();
    settingsModule.set('sync_last_sync_at', now, (err) => {
        if (err) console.error('[SYNC] Failed to save last_sync_at:', err);
        callback();
    });
}

function apiGet(path, callback) {
    if (!jwt) return callback(new Error('Not authenticated'));

    fetch(PRIMARY_URL + path, {
        method: 'GET',
        headers: {
            'Authorization': `Bearer ${jwt}`,
            'Content-Type': 'application/json'
        }
    })
    .then(res => {
        if (!res.ok) {
            if (res.status === 401) {
                jwt = null;
                return res.json().then(d => { throw Object.assign(new Error('401 Unauthorized'), { code: 401 }); });
            }
            return res.json().then(d => { throw new Error(`HTTP ${res.status}: ${d.error || 'unknown'}`); });
        }
        return res.json();
    })
    .then(data => callback(null, data))
    .catch(err => callback(err));
}

function insertBatch(bookings, withNotifications, callback) {
    let inserted = 0;
    let notified = 0;
    const total = bookings.length;
    const stmt = db.prepare(`INSERT OR IGNORE INTO bookings (remote_id, name, phone, adults, children, checkin_date, checkout_date, wishes, status, room_type, room_id, base_price, discount_percent, discount_amount, total_price, promocode_id, comment, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);

    bookings.forEach((b, index) => {
        stmt.run(
            b.id, b.name, b.phone, b.adults, b.children,
            b.checkin_date, b.checkout_date, b.wishes,
            b.status || 'новая', b.room_type, b.room_id,
            b.base_price, b.discount_percent, b.discount_amount,
            b.total_price, b.promocode_id, b.comment, b.created_at,
            function(err) {
                if (err) {
                    console.error('[SYNC] Insert error:', err.message);
                } else if (this.changes > 0) {
                    inserted++;
                    if (withNotifications && b.status !== 'отменена') {
                        sendNotifications(b);
                        notified++;
                    }
                }

                if (index === total - 1) {
                    stmt.finalize();
                    callback(inserted, notified);
                }
            }
        );
    });

    if (total === 0) {
        stmt.finalize();
        callback(0, 0);
    }
}

function sendNotifications(booking) {
    try {
        if (telegramModule && typeof telegramModule.sendBookingNotification === 'function') {
            telegramModule.sendBookingNotification(booking);
        }
    } catch(e) {
        console.error('[SYNC] Telegram notify error:', e.message);
    }
    try {
        if (emailModule && typeof emailModule.sendBookingConfirmation === 'function') {
            emailModule.sendBookingConfirmation(booking);
        }
    } catch(e) {
        console.error('[SYNC] Email notify error:', e.message);
    }
}

module.exports = { init, start, stop };
