const config = require('../../config');
const { getRoomBasePriceByType } = config;

let db;

function init(database) {
    db = database;
}

function getEffectivePrice(roomType, date, callback) {
    const seasonalModule = require('../seasonalPrices');
    seasonalModule.getSeasonalPrice(roomType, date, (err, seasonalPrice) => {
        if (err || !seasonalPrice) {
            const basePrice = getRoomBasePriceByType(roomType);
            return callback(null, basePrice);
        }
        callback(null, seasonalPrice);
    });
}

function calculateNightPrices(roomType, checkin, checkout, callback) {
    const nights = config.calculateNights(checkin, checkout);
    if (nights <= 0) return callback(new Error('Invalid dates'));

    const dates = [];
    for (let i = 0; i < nights; i++) {
        const d = new Date(checkin);
        d.setDate(d.getDate() + i);
        dates.push(d.toISOString().split('T')[0]);
    }

    let total = 0;
    let processed = 0;
    let finished = false;

    dates.forEach(date => {
        getEffectivePrice(roomType, date, (err, price) => {
            if (finished) return;
            if (err) {
                finished = true;
                return callback(err, null);
            }
            total += price;
            processed++;
            if (processed === dates.length) {
                finished = true;
                callback(null, total);
            }
        });
    });
}

function validatePromocode(promocode, callback) {
    if (!promocode) return callback(null, null);
    const now = new Date().toISOString();
    db.get(`SELECT * FROM promocodes WHERE code = ? AND is_active = 1`, [promocode], (err, row) => {
        if (err || !row) return callback(null, null);
        if (row.valid_from && row.valid_from > now) return callback(null, null);
        if (row.valid_to && row.valid_to < now) return callback(null, null);
        if (row.valid_days) {
            const createdDate = new Date(row.created_at);
            const expireDate = new Date(createdDate.getTime() + row.valid_days * 24 * 60 * 60 * 1000);
            if (expireDate < new Date()) return callback(null, null);
        }
        callback(null, row);
    });
}

function checkAvailability(roomId, roomType, checkin, checkout, requestedCount, callback) {
    let sql;
    let params;

    if (roomId) {
        sql = `SELECT r.rooms_count, COALESCE(
            (SELECT COUNT(b.id) FROM bookings b
             WHERE b.room_id = r.id AND b.status IN ('новая','оплачена','зарезервирована','заселена')
             AND b.checkin_date < ? AND b.checkout_date > ?), 0) as booked
        FROM rooms r WHERE r.id = ? AND r.is_active = 1`;
        params = [checkout, checkin, roomId];
    } else {
        sql = `SELECT r.rooms_count, COALESCE(
            (SELECT COUNT(b.id) FROM bookings b
             WHERE b.room_type = r.type AND b.status IN ('новая','оплачена','зарезервирована','заселена')
             AND b.checkin_date < ? AND b.checkout_date > ?), 0) as booked
        FROM rooms r WHERE r.type = ? AND r.is_active = 1 LIMIT 1`;
        params = [checkout, checkin, roomType];
    }

    db.get(sql, params, (err, row) => {
        if (err) return callback(err, null);
        if (!row) return callback(null, { available: 0, total: 0 });
        const available = Math.max(0, row.rooms_count - row.booked);
        callback(null, { available, total: row.rooms_count, booked: row.booked });
    });
}

function createBooking(req, res) {
    const { name, phone, adults, children, checkin, checkout, wishes, room, room_id, promocode } = req.body;
    if (!name || !phone || !adults || !checkin || !checkout) {
        return res.status(400).json({ error: 'Missing required fields' });
    }

    const roomType = room;
    const roomIdValue = room_id ? parseInt(room_id) : null;

    checkAvailability(roomIdValue, roomType, checkin, checkout, 1, (err, avail) => {
        if (err) return res.status(500).json({ error: 'Database error' });
        if (avail.available < 1) {
            return res.status(409).json({
                error: `На выбранные даты нет свободных номеров типа "${roomType}". Доступно: ${avail.available} из ${avail.total}`,
                available: avail.available
            });
        }

        calculateNightPrices(roomType, checkin, checkout, (err, baseSum) => {
            if (err) return res.status(400).json({ error: err.message });
            const basePrice = baseSum * (parseInt(adults) || 1);

            validatePromocode(promocode, (err, promo) => {
                if (err) return res.status(500).json({ error: 'Database error' });
                let discountPercent = 0;
                let promocodeId = null;
                if (promo) {
                    discountPercent = promo.discount_percent;
                    promocodeId = promo.id;
                }
                const safeBasePrice = basePrice || 0;
                const discountAmount = Math.round(safeBasePrice * discountPercent / 100);
                const totalPrice = safeBasePrice - discountAmount;

                const stmt = db.prepare(`INSERT INTO bookings (name, phone, adults, children, checkin_date, checkout_date, wishes, status, room_type, room_id, base_price, discount_percent, discount_amount, total_price, promocode_id)
                                         VALUES (?, ?, ?, ?, ?, ?, ?, 'новая', ?, ?, ?, ?, ?, ?, ?)`);
                stmt.run(name, phone, parseInt(adults), parseInt(children || 0), checkin, checkout, wishes || null,
                    room || null, roomIdValue, safeBasePrice || null, discountPercent || 0, discountAmount || 0, totalPrice || null,
                    promocodeId, function(err) {
                    if (err) {
                        console.error(err);
                        return res.status(500).json({ error: 'Database error' });
                    }
                    const booking = {
                        id: this.lastID,
                        name, phone, adults: parseInt(adults), children: parseInt(children || 0),
                        checkin_date: checkin, checkout_date: checkout, wishes, room_type: room, room_id: roomIdValue,
                        base_price: safeBasePrice, discount_percent: discountPercent, discount_amount: discountAmount,
                        total_price: totalPrice, promocode_id: promocodeId
                    };
                    try { require('../email').sendBookingConfirmation(booking); } catch {}
                    res.status(201).json({
                        id: this.lastID, message: 'Booking saved',
                        base_price: safeBasePrice, discount_percent: discountPercent,
                        discount_amount: discountAmount, total_price: totalPrice
                    });
                });
                stmt.finalize();
            });
        });
    });
}

function getBookings(req, res) {
    const providedKey = req.headers['x-api-key'];
    if (!providedKey) return res.status(401).json({ error: 'Invalid or missing API key' });
    const API_KEY = process.env.HOTEL777KEY;
    if (providedKey !== API_KEY) return res.status(401).json({ error: 'Invalid or missing API key' });
    db.all(`SELECT b.*, p.code as promocode_code FROM bookings b
            LEFT JOIN promocodes p ON b.promocode_id = p.id
            ORDER BY b.checkin_date ASC`, (err, rows) => {
        if (err) {
            console.error(err);
            return res.status(500).json({ error: 'Database error' });
        }
        res.json(rows);
    });
}

function getBookingHistory(req, res) {
    const bookingId = parseInt(req.params.id);
    db.all(`SELECT id, booking_id, user_id, user_login, field, old_value, new_value, created_at
            FROM booking_history WHERE booking_id = ? ORDER BY created_at DESC`, [bookingId], (err, rows) => {
        if (err) return res.status(500).json({ error: 'Database error' });
        res.json(rows);
    });
}

function logHistory(bookingId, userId, userLogin, field, oldValue, newValue) {
    db.run(`INSERT INTO booking_history (booking_id, user_id, user_login, field, old_value, new_value) VALUES (?, ?, ?, ?, ?, ?)`,
        [bookingId, userId, userLogin, field, oldValue, newValue], (err) => {
            if (err) console.error('History log error:', err);
        });
}

function setupRoutes(app, authenticateToken, requireAdmin) {
    app.post('/api/bookings', createBooking);
    app.get('/api/bookings', getBookings);
    app.get('/api/admin/bookings/:id/history', authenticateToken, getBookingHistory);
}

module.exports = { init, setupRoutes, validatePromocode, logHistory, calculateNightPrices, checkAvailability };
