// Подключаем необходимые библиотеки
const { Telegraf, Scenes, session, Markup, Stage } = require('telegraf');
const { Op } = require('sequelize');
const sequelize = require('./db'); // Подключение базы данных
  // Подключаем обработчики
const commands = require('./commands');
const utils = require('./utils');
const handlers = require('./handlers');
const {
    UserModel,
    WorldModel,
    JobModel,
    PropertyModel,
    AFKPropertyModel,
    BusinessModel,
    ReportModel,
    BlockModel,
    PromocodeModel,
    EnterpriseModel,
    WarehouseModel,
    TruckModel,
    SaleModel,
    ResourcePriceModel,
    SkillsModel,
} = global.config
  const bot = new Telegraf(process.env.BOT_TOKEN)
  const crime = require('./scenes/crime')
  const pocketsteal = require('./scenes/pocketsteal')
  const shop = require('./scenes/shop')
  const pve = require('./scenes/pve')
const newpve = require('./scenes/newpve')
  const stage = new Scenes.Stage([crime, pocketsteal, shop, pve, newpve]);

  const start = async () => {
    try {
        // Подключаемся к базе данных
        await sequelize.authenticate();
        console.log('Подключение к базе данных успешно!');
        
        // Синхронизация моделей, если нужно
        await sequelize.sync({ alter: true });
        console.log('Синхронизация моделей завершена.');

        // Запуск бота
        console.log('Бот успешно запущен!');
    } catch (error) {
        console.error('Ошибка при запуске приложения:', error);
    }
}

bot.telegram.setMyCommands([{
        command: "pay",
        description: "Перевести указанному пользователю сумму."
    },
    {
        command: "buy",
        description: "Приобрести указанное имущество."
    },
    {
        command: "business",
        description: "Создать организацию."
    },
    {
        command: "invite",
        description: "Пригласить пользователя в организацию."
    },
    {
        command: "percent",
        description: "Установить пользователю процент заработка."
    },
    {
        command: "report",
        description: "Создать жалобу/обращение/идею."
    }
])

bot.use(stage.middleware())

bot.use(
    session({
      getSessionKey: (ctx) => {
        if ((ctx.from && ctx.chat && ctx.chat.id === ctx.from.id) || (!ctx.chat && ctx.from)) {
          return `user:${ctx.from.id}`
        } else if (ctx.from && ctx.chat) {
          return `${ctx.from.id}:${ctx.chat.id}`
        }
        return ctx.update.update_id
      }
    })
  )
  bot.use(stage)
bot.use(utils.stats)

bot.use(async (ctx, next) => {
    bot.context.config = require('./ctxconfig.json')
    let id = ctx.from.id
    let username = ctx.from.username
    if(username == null) username = ctx.from.id
    switch(ctx.updateType){
        case `message`:
            console.log(utils.getCurrentTime() + `: ` + username + `: ` + ctx.update.message.text)
            break;
        case `callback_query`:
            console.log(utils.getCurrentTime() + `: ${username}: ${ctx.update.callback_query.data}`)
            break;
        default:
            console.log(ctx)
    }
    let user = await UserModel.findByPk(id);
    let block = await BlockModel.findByPk(id);
    let property = await PropertyModel.findByPk(id);
    let skill = await SkillsModel.findByPk(ctx.from.id)
    if (!user) ctx.reply(`❕ Первичная регистрация профиля.`);
    if (user === null) {
        await UserModel.create({
            telegram_id: id,
            username: username,
            name: ctx.from.first_name
        })
    } else {
      user.name = ctx.from.first_name
      if(user.username === null) user.username = ctx.from.id
      user.save()
    }
    if (property === null) {
        await PropertyModel.create({
            telegram_id: id
        })
    }
    if (skill === null) {
        await SkillsModel.create({
            telegram_id: id,
            stealing: {
                level: 1,
                exp: 0
            }
        })
    }
    //if (whitelist.includes(id) == false) return ctx.reply(`У вас пока нет доступа к боту. Следите за обновлениями в группе: t.me/CampFireGameBotNews`)
    if (block !== null) {
        if (block.isBlocked == true && block.time > Date.now() / 1000) return ctx.reply(`📛 У вас активная блокировка по причине: ${block.reason}.\n⏲️ Оставшееся время: ${Math.trunc((block.time - Date.now()/1000)/60)} мин.`)
        block.isBlocked = false
        block.save()
    }
    const start = Date.now()
    const timeoutPromise = new Promise((resolve, reject) => {
    
        setTimeout(() => {
          reject(new Error('timeout'))
        }, 1000 * 5)
      })

      const nextPromise = next()
      .then(() => {
        const ms = Date.now() - start
        })
      .catch((error) => {
        handleError(error, ctx)
        })

      return Promise.race([timeoutPromise, nextPromise])
        .catch((error) => {
          if (error.message === 'timeout') {
            console.error('timeout', ctx.update)
            return false
          }
    
          return true
        })
    
})

bot.command('start', async (ctx) => {
    if (ctx.payload) {
        let id = ctx.from.id
        let user = await UserModel.findByPk(id);
        if (user.level == 1) {
            let ref = await UserModel.findByPk(ctx.payload)
            let world = await WorldModel.findByPk(1)
            world.balance -= 25000
            ref.money += Number(25000)
            await ref.save()
            await world.save()
            bot.telegram.sendMessage(ref.telegram_id, `${ctx.from.username} зарегистрировался по вашей реферальной ссылке. Получено ¤25.000`)
            console.log("Transaction to Ref")
        } else {
            console.log("Exist")
        }
    }
    return await ctx.reply('Главное меню', Markup
        .keyboard([
            ['😎 Профиль'], // Row1 with 2 buttons
            ['🗄️ Работать', '🌐 Организация', '🎁 Бонус', '🏯 Казино'], // Row2 with 2 buttons
            ['🏗️ Предприятия'],
            ['📦 Контейнеры'],
            ['📢 Вакансии', '🔵 Имущество', '📞 Пригласить'] // Row3 with 3 buttons
        ])
        .resize()
    )
})

bot.hears('Криминал', async (ctx) => {
    await ctx.reply(`Closed`)
    /*await ctx.scene.enter('Crime')*/
})


bot.hears('промка', async(ctx) => {
    generatePromo()
});

bot.hears('▶️ Меню', commands.menu);

bot.hears('Чат', async (ctx) => {
    ctx.reply(`${ctx.message.chat.id}`)
});

bot.hears('😎 Профиль', commands.profile);

bot.command('getprofile', commands.getprofile);

bot.hears('Рандом', async (ctx) => {
    let users = await UserModel.findAll();
    let chosenOne = users.random()
    return ctx.reply(`
      👤 ${chosenOne.username} 
      🆔: ${chosenOne.telegram_id}
      `);

});

bot.hears('💳 Баланс', async (ctx) => {
    let user = await UserModel.findByPk(ctx.from.id);
    return ctx.reply(`
      ⏩ Аккаунт игрока ${user.username}
      &#127380; Игрока: ${user.telegram_id}

      📶 Уровень: ${user.level}
      ⏩ Повышается за различные действия.

      💰 Баланс: 
      ¤${user.money}
    `);
})

bot.hears('🎁 Бонус', commands.bonus)

bot.hears('Гараж', commands.garage)

bot.hears('Гонка', commands.race)

bot.command('pay', commands.pay)

bot.hears('Мир', commands.worldMenu)

bot.hears('📞 Пригласить', commands.referal)

bot.hears('📢 Вакансии', commands.jobs)

bot.action(/job_(1|2|3|4|5|6|7|leave)/, commands.chooseJob)

bot.hears('🏯 Казино', commands.casinoMenu)

bot.hears('🗄️ Работать', commands.work)

bot.hears('Топ', commands.top)

bot.hears('🔵 Имущество', commands.propertyMenu)

bot.action('shopmenu', commands.propertyMenu)

bot.action(/shop_(house|phone|car)/, commands.propertyList)

bot.action(/{"action": "buy"*/, commands.propertyBuy)

bot.hears('Поставщик', commands.hatkeisList)

bot.command('sell', commands.propertySell)

bot.hears('🌐 Организация', commands.organizationMenu)

bot.action('workoff', commands.workoff)

bot.action('покинуть', commands.leaveOrg)

bot.action('cancel', async (ctx) => {
    await ctx.deleteMessage()
    await bot.telegram.answerCbQuery(ctx.callbackQuery.id, `Отмена.`)
})

bot.action('user_leave_business', commands.leaveOrgAccept)

bot.action('payday', commands.payday)

bot.command('orgmessage', commands.orgMessage)

bot.command('materials', commands.materialsBuy)

bot.command('percent', commands.percentSet)

bot.command('business', commands.organizationCreate)

bot.command('invite', commands.invite)

bot.action(/{"type": "business_invite_(accept|refuse)"*/, commands.inviteAction)

bot.command('report', commands.report)

bot.hears('🎰 Слоты', commands.slotsMenu)

bot.action(/slots(1000|5000|25000|50000|100000)/, commands.slotsRun)

bot.hears('Помощь', async (ctx) => {
    return await ctx.replyWithMarkdownV2(`• [Функционал](https://telegra.ph/CampFire-Bot-Info-09-25)\n• [Правила](https://telegra.ph/PRAVILA-BOTA-09-25)`, {
        disable_web_page_preview: true
    })
})

bot.command('promocode', commands.promocodeActivate)

bot.hears('📦 Контейнеры', commands.carContainers)

bot.action(/container_(1|2|3|4|5|6|7|8|9|10)/, commands.chooseContainer)

bot.action(/{"action": "sueta_*/, async (ctx) => {
    let data = ctx.update.callback_query.data;
    data = JSON.parse(data)
    console.log(data.car)
    let user = await UserModel.findByPk(ctx.from.id)
    let property = await PropertyModel.findByPk(ctx.from.id)
    switch(data.action){
        case `sueta_accept`:
            user.money += data.carprice
            await ctx.editMessageText(`➕ ${data.carprice}`)
            break;
        case `sueta_refuse`:
            user.money += Math.round(property.car.price/2)
            property.car = {
                name: data.carname,
                price: data.carprice
            }
            await ctx.editMessageText(`➕ ${data.carname}`)
            break;
    }
    user.save()
    property.save()
})

/////////////////////////////////////Enterprise Update 20.12.2024//////////////////////////////////////////////////

// Обновление меню "Предприятия"
bot.hears('🏗️ Предприятия', async (ctx) => {
    const user = await UserModel.findByPk(ctx.from.id);
    const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
    
    const enterprises = await EnterpriseModel.findAll({
        where: { playerId: user.telegram_id }
    });

    let message = `🏗️ Меню предприятий:\n`;
    message += `У вас: ${enterprises.length} предприятий.\n`;
    message += warehouse 
        ? `🗄️ Единый склад: Доступен (Ёмкость: ${warehouse.capacity} ед.)\n`
        : `🗄️ Единый склад: Не построен.\n`;

    const buttons = [];

    // Добавляем кнопки для предприятий
    buttons.push([{ text: '🏭 Мои предприятия', callback_data: 'my_enterprises' }]);
    buttons.push([{ text: '🛠️ Построить предприятие', callback_data: 'build_enterprise' }]);

    // Кнопка для управления или постройки склада
    if (warehouse) {
        buttons.push([{ text: '🚛 Управление складом', callback_data: 'manage_warehouse' }]);
    } else {
        buttons.push([{ text: '🗄️ Построить склад', callback_data: 'buy_warehouse' }]);
    }
    buttons.push([{ text: '💰 Продать ресурсы', callback_data: 'sell_resources' }])
    // Возвращаем меню с кнопками
    return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize());
});
bot.action('enterprise_menu', async (ctx) => {
    const user = await UserModel.findByPk(ctx.from.id);
    const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
    
    const enterprises = await EnterpriseModel.findAll({
        where: { playerId: user.telegram_id }
    });

    let message = `🏗️ Меню предприятий:\n`;
    message += `У вас: ${enterprises.length} предприятий.\n`;
    message += warehouse 
        ? `🗄️ Единый склад: Доступен (Ёмкость: ${warehouse.capacity} ед.)\n`
        : `🗄️ Единый склад: Не построен.\n`;

    const buttons = [];

    // Добавляем кнопки для предприятий
    buttons.push([{ text: '🏭 Мои предприятия', callback_data: 'my_enterprises' }]);
    buttons.push([{ text: '🛠️ Построить предприятие', callback_data: 'build_enterprise' }]);

    // Кнопка для управления или постройки склада
    if (warehouse) {
        buttons.push([{ text: '🚛 Управление складом', callback_data: 'manage_warehouse' }]);
    } else {
        buttons.push([{ text: '🗄️ Построить склад', callback_data: 'buy_warehouse' }]);
    }
    buttons.push([{ text: '💰 Продать ресурсы', callback_data: 'sell_resources' }])
    // Возвращаем меню с кнопками
    return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
});

// Функция для преобразования типа ресурса в эмодзи
function getEnterpriseEmoji(resourceType) {
    const emojis = {
        wood: '🌳',
        coal: '⛏️',
        oil: '🛢️',
        metall: '⚒️',
        gold: '💰',
        diamond: '💎'
    }
    return emojis[resourceType] || '🏭'
}

bot.action('my_enterprises', async (ctx) => {
    const user = await UserModel.findByPk(ctx.from.id);
    const enterprises = await EnterpriseModel.findAll({
        where: { playerId: user.telegram_id }
    });

    if (enterprises.length === 0) {
        return await ctx.reply('У вас нет предприятий.');
    }
    let metallPrice = 0
    let message = `🏭 Мои предприятия:\n\n`;
    const buttons = [];
    
    for (const enterprise of enterprises) {
        const { id, name, level, efficiency, currentResources, resourceType, warehouseCapacity } = enterprise;
        const resourcePrice = await ResourcePriceModel.findOne({
            where: { resource: resourceType }
        });
        let price = resourcePrice.price * 2 * 10 * 24 * 7 // Стоимость улучшения зависит от уровня
        message += `🔹 [ID: ${id}] ${getEnterpriseEmoji(resourceType)} ${name} st. ${level}\n    └── ${currentResources}/${warehouseCapacity} [${efficiency} ед/ч]\n        └──📈 ${utils.spaces(price)} руб.\n\n`;
        if (resourcePrice.resource == "metall") metallPrice = resourcePrice.price
        const truck = await TruckModel.findOne({ where: { enterpriseId: id } });
        const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });

        const enterpriseButtons = [
            { text: `ID: 📈 ${id}`, callback_data: `upgrade_${id}` },
        ];

        if (!truck) {
            enterpriseButtons.push({ text: `🛻 ID: ${id}`, callback_data: `hire_truck_${id}` });
        }else{
            enterpriseButtons.push({ text: `🚛 ID: ${id}`, callback_data: `upgrade_truck_${id}` });
        }

        enterpriseButtons.push({ text: `💰 ID: ${id}`, callback_data: `sell_all_${id}` });

        if (warehouse) {
            enterpriseButtons.push({ text: `🔄 ID: ${id}`, callback_data: `transfer_from_${id}` });
        }

        buttons.push(enterpriseButtons);
    }
    message += `\n\n📈 - Улучшить\n🛻 - Купить грузовик [~${utils.spaces(metallPrice*700)} руб.]\n🚛 - Улучшить грузовик\n💰 - Продать ресурсы с предприятия\n🔄 - Перевезти все на склад`
    buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]);

    return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
});

// Построение предприятия
bot.action('build_enterprise', async (ctx) => {
    try {
        const user = await UserModel.findByPk(ctx.from.id);
        if (!user) {
            return await ctx.reply('Пользователь не найден.');
        }

        const enterprises = await EnterpriseModel.findAll({
            where: { playerId: user.telegram_id }
        });

        if (enterprises.length >= 5) {
            return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Вы достигли максимального числа предприятий.', {show_alert: true});
        }

        // Получаем текущие цены из базы данных
        const resourcePrices = await ResourcePriceModel.findAll();
        if (!resourcePrices || resourcePrices.length === 0) {
            return await ctx.reply('Цены на ресурсы отсутствуют. Пожалуйста, попробуйте позже.');
        }

        let message = `🛠️ Постройка предприятия:\n`;
        const buttons = [];

        for (const resource of resourcePrices) {
            const resourceName = getReadableType(resource.resource);
            const resourceEmoji = getEnterpriseEmoji(resource.resource);
            message += `${resourceEmoji} ${resourceName}: ${utils.spaces(Math.round(resource.price * 2 * 10 * 24 * 7))} руб.\n`;

            // Генерируем кнопки для каждого ресурса
            buttons.push([
                { text: resourceEmoji, callback_data: `build_${resource.resource}` }
            ]);
        }

        message += '\nВыберите тип предприятия:';
        buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]);
        return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
    } catch (error) {
        console.error('Ошибка в build_enterprise:', error);
        return await ctx.reply('Произошла ошибка при обработке запроса. Попробуйте снова.');
    }
});

// Построение предприятия по выбранному типу
bot.action(/build_(wood|coal|oil|metall|gold|diamond)/, async (ctx) => {
    let user = await UserModel.findByPk(ctx.from.id)
    let data = ctx.update.callback_query.data
    let type = data.split('_')[1]
    

    // Получаем текущие цены из базы данных
    const resourcePrice = await ResourcePriceModel.findOne({
        where: { resource: type }
    });
    let price = resourcePrice.price * 2 * 10 * 24 * 7

    // Проверка, есть ли достаточно денег у пользователя
    if (user.balance < price) {
        return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для постройки предприятия. Необходимо ${price} руб.`, {show_alert: true})
    }

    // Строим предприятие
    let enterpriseName = `${user.username}'s ${getReadableType(type)}` // Название предприятия
    let enterprise = await EnterpriseModel.create({
        name: enterpriseName,
        resourceType: type,
        playerId: user.telegram_id,
        level: 1,
        efficiency: 10,
        warehouseCapacity: 100
    })

    // Снимаем деньги с баланса
    await user.update({ money: user.money - price })

    return await ctx.editMessageText(`Предприятие ${enterprise.name} (ID: ${enterprise.id}) построено!`)
})

// Функция для преобразования типа ресурса в читаемое название
function getReadableType(type) {
    const names = {
        wood: 'Деревообрабатывающее предприятие',
        coal: 'Угольное предприятие',
        oil: 'Нефтяное предприятие',
        metall: 'Металлургическое предприятие',
        gold: 'Золотое предприятие',
        diamond: 'Алмазное предприятие'
    }
    return names[type] || type
}

function getReadableResourceType(type) {
    const names = {
        wood: 'Дерево',
        coal: 'Уголь',
        oil: 'Нефть',
        metall: 'Металл',
        gold: 'Золото',
        diamond: 'Алмазы'
    }
    return names[type] || type
}

bot.action('buy_warehouse', async (ctx) => {
    let user = await UserModel.findByPk(ctx.from.id)
    if (user.status != 'admin') {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Мы работаем над этим.`, {show_alert: true})
    }
    if (user.money < 500000) {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id,`У вас недостаточно средств для покупки склада.`, {show_alert: true})
    }

    await WarehouseModel.create({
        playerId: user.telegram_id,
        capacity: 1000, // Начальная ёмкость
        wood: 0,
        coal: 0,
        oil: 0,
        metall: 0,
        gold: 0,
        diamond: 0
    })

    await user.update({ money: user.money - 500000 })
    return await ctx.reply(`Вы успешно купили единый склад!`)
})

// Управление складом
bot.action('manage_warehouse', async (ctx) => {
    const user = await UserModel.findByPk(ctx.from.id);
    const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });

    if (!warehouse) {
        return await ctx.reply('У вас нет склада для управления.');
    }

    let message = `🚛 Управление складом:\n`;
    message += `Общая ёмкость: ${warehouse.capacity} ед.\n`;
    message += `Хранимые ресурсы:\n`;
    message += `🌲 Дерево: ${warehouse.wood || 0}\n`;
    message += `⛏️ Уголь: ${warehouse.coal || 0}\n`;
    message += `🛢️ Нефть: ${warehouse.oil || 0}\n`;
    message += `⚙️ Металл: ${warehouse.metall || 0}\n`;
    message += `🥇 Золото: ${warehouse.gold || 0}\n`;
    message += `💎 Алмазы: ${warehouse.diamond || 0}\n`;

    const buttons = [
        [{ text: '➕ Перевести ресурсы', callback_data: 'transfer_resources' }]
    ];
    buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]);
    return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
});

bot.action('transfer_resources', async (ctx) => {
    const user = await UserModel.findByPk(ctx.from.id);
    const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });

    if (!warehouse) {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id,'У вас нет единого склада.');
    }

    const enterprises = await EnterpriseModel.findAll({
        where: { playerId: user.telegram_id }
    });

    let message = `➕ Перевозка ресурсов:\n`;
    message += `Общая ёмкость склада: ${warehouse.capacity} ед.\n`;
    message += `Выберите предприятие для перевозки ресурсов:`;

    const buttons = enterprises.map(ent => {
        return [{ text: `🏭 ${ent.name}`, callback_data: `transfer_from_${ent.id}` }];
    });
    buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]);
    return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
});

// Перевозка с конкретного предприятия
bot.action(/transfer_from_(\d+)/, async (ctx) => {
    const enterpriseId = ctx.match[1];
    const enterprise = await EnterpriseModel.findByPk(enterpriseId);

    if (!enterprise) {
        return await ctx.editMessageText('Предприятие не найдено.');
    }

    const { currentResources, resourceType, playerId } = enterprise;

    if (currentResources === 0) {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для перевода.');
    }

    const warehouse = await WarehouseModel.findOne({ where: { playerId } });

    if (!warehouse) {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'У вас нет склада для перевода ресурсов.');
    }

    const freeCapacity = warehouse.capacity - getWarehouseUsedCapacity(warehouse);
    const transferAmount = Math.min(currentResources, freeCapacity);

    if (transferAmount === 0) {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Склад заполнен. Перевод невозможен.');
    }

    // Перевод ресурсов
    warehouse[resourceType] = (warehouse[resourceType] || 0) + transferAmount;
    enterprise.currentResources -= transferAmount;

    await warehouse.save();
    await enterprise.save();

    return await ctx.reply(
        `Успешно переведено ${transferAmount} ед. ${resourceType} с предприятия в склад.`
    );
});

bot.command('ent_rename', async (ctx) => {
    let args = ctx.message.text.split(' ').slice(1)
    if (args.length < 2) {
        return await ctx.reply('Использование: /ent_rename <ID> <Новое название>')
    }

    let enterpriseId = parseInt(args[0])
    let newName = args.slice(1).join(' ')

    let enterprise = await EnterpriseModel.findByPk(enterpriseId)
    if (!enterprise) {
        return await ctx.reply(`Предприятие с ID ${enterpriseId} не найдено.`)
    }

    // Переименовываем предприятие
    await enterprise.update({ name: newName })

    return await ctx.reply(`Предприятие (ID: ${enterprise.id}) переименовано в "${newName}".`)
})

bot.action(/upgrade_(\d+)/, async (ctx) => {
    let user = await UserModel.findByPk(ctx.from.id)
    let enterpriseId = ctx.match[1]
    let enterprise = await EnterpriseModel.findByPk(enterpriseId)

    if (!enterprise) return await ctx.reply(`Предприятие не найдено.`)
    const resourcePrice = await ResourcePriceModel.findOne({
        where: { resource: enterprise.resourceType }
    });
    let upgradeCost = resourcePrice.price * 2 * 10 * 24 * 7 // Стоимость улучшения зависит от уровня
    if (user.money < upgradeCost) {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для прокачки предприятия. Необходимо ${upgradeCost} руб.`)
    }

    // Прокачка: повышение уровня и эффективности
    await enterprise.update({
        level: enterprise.level + 1,
        efficiency: enterprise.efficiency + 10,
        warehouseCapacity: enterprise.warehouseCapacity + 110
    })

    // Снимаем деньги с баланса
    await user.update({ money: user.money - upgradeCost })

    return await ctx.editMessageText(`Предприятие ${enterprise.name} успешно прокачано! Уровень: ${enterprise.level}, Производительность: ${enterprise.efficiency} ед/ч.`)
})

// Показ списка предприятий
bot.action('sell_resources', async (ctx) => {
    const user = await UserModel.findByPk(ctx.from.id);
    const enterprises = await EnterpriseModel.findAll({
        where: { playerId: user.telegram_id }
    });

    if (enterprises.length === 0) {
        return await ctx.reply('❌ У вас нет предприятий для продажи ресурсов.');
    }

    let message = `<b>📜 Список ваших предприятий и их ресурсы:</b>\n\n`;
    enterprises.forEach((enterprise, index) => {
        message += `<b>${index + 1}.</b> ${enterprise.name} (${enterprise.resourceType}): <b>${enterprise.currentResources}</b> единиц\n`;
    });

    message += `\n<b>📦 Продажа ресурсов:</b>\n`;
    message += `• Для продажи ресурсов с предприятия используйте команду:\n<code>/sellres [номер_предприятия] [количество]</code>\n<i>Пример:</i> <code>/sellres 1 50</code>\n\n`;
    message += `• Для продажи ресурсов со склада используйте команду:\n<code>/sellstorage [тип_ресурса (wood/coal/oil/metall/gold/diamond)] [количество]</code>\n<i>Пример:</i> <code>/sellstorage wood 10</code>`;

    return await ctx.reply(message, {
        parse_mode: 'HTML',
        reply_markup: {
            inline_keyboard: [
                [{ text: '↩ Назад', callback_data: 'enterprise_menu' }]
            ]
        }
    });
});


// Обработка продажи ресурсов
bot.command('sellres', async (ctx) => {
    const user = await UserModel.findByPk(ctx.from.id);
    const [enterpriseId, amountToSell] = ctx.message.text.split(' ').slice(1);

    if (!enterpriseId || !amountToSell) {
        return await ctx.reply('Неверный формат команды. Пример: /sellres 1 50');
    }

    const enterprise = await EnterpriseModel.findByPk(enterpriseId, {
        where: { playerId: user.telegram_id }
    });

    if (!enterprise) {
        return await ctx.reply('Предприятие с таким id не найдено.');
    }

    const amount = parseInt(amountToSell, 10);

    if (isNaN(amount) || amount <= 0) {
        return await ctx.reply('Укажите корректное количество для продажи.');
    }

    if (enterprise.currentResources < amount) {
        return await ctx.reply(
            `На предприятии ${enterprise.name} недостаточно ресурсов. Доступно: ${enterprise.currentResources} единиц.`
        );
    }

    const resourcePrice = await ResourcePriceModel.findOne({
        where: { resource: enterprise.resourceType }
    });

    if (!resourcePrice) {
        return await ctx.reply('Не удалось получить цену ресурса.');
    }

    const totalSale = Math.floor(amount * resourcePrice.price);

    // Обновляем данные
    enterprise.currentResources -= amount;
    await enterprise.save();

    user.money += totalSale;
    await user.save();

    // Ослабленная инфляция
    resourcePrice.price = Math.round(
        resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (amount / 10)) // Дробное уменьшение инфляции
    );

    // Гарантируем, что цена не упадет ниже 50% от базовой цены
    resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5));

    await resourcePrice.save();
    updateResourcePricesMessage();
    return await ctx.reply(
        `Вы продали ${amount} единиц ${enterprise.resourceType} с предприятия ${enterprise.name} за ${totalSale} руб.\nТекущая цена за единицу: ${resourcePrice.price.toFixed(0)} руб.`
    );
});


const recoverResourcePrices = async () => {
    const resources = await ResourcePriceModel.findAll();

    for (const resource of resources) {
        // Определяем случайное колебание в диапазоне [-maxFluctuation, maxFluctuation]
        const maxFluctuation = resource.basePrice * 0.03; // 3% от базовой цены
        const priceFluctuation = (Math.random() * 2 - 1) * maxFluctuation;

        // Применяем колебание
        resource.price = Math.round(resource.price + priceFluctuation);

        // Если цена выше базовой, шанс на её снижение
        if (resource.price > resource.basePrice) {
            const chanceToDrop = 0.6; // 60% шанс на снижение
            if (Math.random() < chanceToDrop) {
                resource.price -= Math.round(resource.basePrice * 0.01); // Снижение на 1% базовой цены
            }
        }

        // Если цена ниже базовой, восстанавливаем с учётом recoveryRate
        if (resource.price < resource.basePrice) {
            resource.price = Math.min(
                Math.round(resource.price + resource.basePrice * resource.recoveryRate),
                resource.basePrice // Не превышать базовую цену
            );
        }

        // Гарантируем, что цена остаётся в диапазоне [50% basePrice, 150% basePrice]
        resource.price = Math.max(resource.price, Math.round(resource.basePrice * 0.5)); // Минимум
        resource.price = Math.min(resource.price, Math.round(resource.basePrice * 1.5)); // Максимум
        
        await resource.save(); // Сохраняем после всех корректировок
    }
};

bot.action(/sell_all_(\d+)/, async (ctx) => {
    const enterpriseId = ctx.match[1];
    const enterprise = await EnterpriseModel.findByPk(enterpriseId);

    if (!enterprise) {
        return await ctx.reply('Предприятие не найдено.');
    }

    const { currentResources, resourceType, playerId } = enterprise;
    const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: resourceType } });
    const totalPrice = currentResources * resourcePrice.price;

    if (currentResources === 0) {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для продажи.');
    }

    await ctx.reply(
        `Вы уверены, что хотите продать все ${currentResources} ед. ${resourceType} за ${totalPrice} руб.? Это необратимо!\n\nРекомендуем воспользоваться командой /sell для более гибкого управления продажами.`,
        Markup.inlineKeyboard([
            [
                { text: '✅ Продать всё', callback_data: `confirm_ressell_${enterpriseId}` },
                { text: '❌ Отмена', callback_data: 'cancel' }
            ]
        ])
    );
});

bot.action(/confirm_ressell_(\d+)/, async (ctx) => {
    const enterpriseId = ctx.match[1];
    const enterprise = await EnterpriseModel.findByPk(enterpriseId);

    if (!enterprise) {
        return await ctx.reply('Предприятие не найдено.');
    }

    const { currentResources, resourceType, playerId } = enterprise;
    const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: resourceType } });
    const totalPrice = currentResources * resourcePrice.price;

    if (currentResources === 0) {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для продажи.');
    }

    // Обновление баланса игрока
    const user = await UserModel.findByPk(playerId);
    user.money += totalPrice;
    enterprise.currentResources = 0;

    await user.save();
    await enterprise.save();
    console.log(resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (currentResources / 10)))
    // Ослабленная инфляция
    resourcePrice.price = Math.round(
        resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (currentResources / 10)) // Дробное уменьшение инфляции
    );
    // Гарантируем, что цена не упадет ниже 50% от базовой цены
    resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5));
    
    await resourcePrice.save();
    updateResourcePricesMessage();
    await ctx.editMessageText(`Вы успешно продали ${currentResources} ед. ${resourceType} за ${totalPrice} руб.`);
});

// Продажа ресурсов со склада
bot.command('sellstorage', async (ctx) => {
    const user = await UserModel.findByPk(ctx.from.id);
    const [resourceType, amountToSell] = ctx.message.text.split(' ').slice(1);

    if (!resourceType || !amountToSell) {
        return await ctx.reply('Неверный формат команды. Пример: /sellstorage <тип_ресурса> <количество>');
    }

    const storage = await WarehouseModel.findOne({
        where: { playerId: user.telegram_id }
    });

    if (!storage || !storage[resourceType]) {
        return await ctx.reply(`У вас нет ресурсов типа ${resourceType} на складе.`);
    }

    const amount = parseInt(amountToSell, 10);

    if (isNaN(amount) || amount <= 0) {
        return await ctx.reply('Укажите корректное количество для продажи.');
    }

    if (storage[resourceType] < amount) {
        return await ctx.reply(`На складе недостаточно ресурсов типа ${resourceType}. Доступно: ${storage[resourceType]} единиц.`);
    }

    const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: resourceType } });

    if (!resourcePrice) {
        return await ctx.reply('Не удалось получить цену ресурса.');
    }

    const totalSale = Math.floor(amount * resourcePrice.price);

    // Обновляем данные
    storage[resourceType] -= amount;
    await storage.save();

    user.money += totalSale;
    await user.save();

    // Ослабленная инфляция
    resourcePrice.price = Math.round(
        resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (amount / 10)) // Дробное уменьшение инфляции
    );

    // Гарантируем, что цена не упадет ниже 50% от базовой цены
    resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5));
    
    await resourcePrice.save();
    updateResourcePricesMessage();
    return await ctx.reply(
        `Вы продали ${amount} ед. ${resourceType} со склада за ${totalSale} руб.\nТекущая цена за единицу: ${resourcePrice.price.toFixed(0)} руб.`
    );
});

// Обработка найма грузовика для выбранного предприятия
bot.action(/hire_truck_(\d+)/, async (ctx) => {
    const user = await UserModel.findByPk(ctx.from.id);
    const enterpriseId = ctx.match[1];

    // Находим предприятие
    const enterprise = await EnterpriseModel.findByPk(enterpriseId);

    if (!enterprise || enterprise.playerId != user.telegram_id) {
        return await ctx.reply('Предприятие не найдено или вам не принадлежит.');
    }

    // Проверяем, есть ли уже грузовик для этого предприятия
    const existingTruck = await TruckModel.findOne({
        where: { enterpriseId: enterprise.id }
    });

    if (existingTruck) {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас уже есть грузовик для предприятия ${enterprise.name}.`);
    }
    const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: 'metall' } });
    if (!resourcePrice) {
         return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Не удалось получить цену ресурса.');
    }
    if (user.money < resourcePrice.price*700) {
        return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Недостаточно средств. Стоимость грузовика: ${utils.spaces(resourcePrice.price*700)} руб.`);
   }
    await user.update({ money: user.money - (resourcePrice.price*700) })
    // Создаем новый грузовик
    const newTruck = await TruckModel.create({
        enterpriseId: enterprise.id,
        capacity: 10, // Начальная вместимость
        efficiency: 1 // Начальная эффективность
    });
    return await ctx.reply(
        `Вы успешно наняли грузовик для предприятия ${enterprise.name}!`
    );
});


async function initializePrices() {
    const resources = [
        { resource: 'wood', price: 1000, basePrice: 1000, fluctuationRate: 0.002, recoveryRate: 0.15 },
        { resource: 'coal', price: 2000, basePrice: 2000, fluctuationRate: 0.002, recoveryRate: 0.12 },
        { resource: 'oil', price: 5000, basePrice: 5000, fluctuationRate: 0.001, recoveryRate: 0.1 },
        { resource: 'metall', price: 5000, basePrice: 5000, fluctuationRate: 0.001, recoveryRate: 0.1 },
        { resource: 'gold', price: 10000, basePrice: 10000, fluctuationRate: 0.0005, recoveryRate: 0.08 },
        { resource: 'diamond', price: 25000, basePrice: 25000, fluctuationRate: 0.0004, recoveryRate: 0.05 },
    ];

    for (const resource of resources) {
        await ResourcePriceModel.findOrCreate({
            where: { resource: resource.resource },
            defaults: resource,
        });
    }
}

initializePrices();

// Функция добычи ресурсов
const resourceProduction = async () => {
    try {
        // Получаем все предприятия
        const enterprises = await EnterpriseModel.findAll();

        for (const enterprise of enterprises) {
            const {
                id,
                efficiency,
                warehouseCapacity,
                resourceType,
                currentResources,
                level,
                playerId
            } = enterprise;

            // Расчёт добытых ресурсов
            const producedResources = efficiency * level;

            // Проверяем ёмкость склада предприятия
            if (currentResources + producedResources <= warehouseCapacity) {
                enterprise.currentResources += producedResources;
                await enterprise.save();
                console.log(
                    `Предприятие ${id}: добыто ${producedResources} единиц ${resourceType}.`
                );
            } else {
                console.log(`Предприятие ${id}: склад заполнен.`);
            }
        }
    } catch (error) {
        console.error('Ошибка добычи ресурсов:', error);
    }
};

// Функция транспортировки ресурсов
const resourceTransportation = async () => {
    try {
        // Получаем все предприятия
        const enterprises = await EnterpriseModel.findAll();

        for (const enterprise of enterprises) {
            const {
                id,
                resourceType,
                currentResources,
                playerId
            } = enterprise;

            if (currentResources > 0) {
                // Получаем грузовики, привязанные к предприятию
                const trucks = await TruckModel.findAll({
                    where: { enterpriseId: id }
                });

                if (trucks.length === 0) {
                    console.log(
                        `Предприятие ${id}: нет доступных грузовиков для транспортировки.`
                    );
                    continue;
                }

                // Получаем универсальный склад игрока
                const warehouse = await WarehouseModel.findOne({
                    where: { playerId }
                });

                if (!warehouse) {
                    console.log(
                        `Предприятие ${id}: у игрока ${playerId} нет универсального склада.`
                    );
                    continue;
                }

                // Транспортировка ресурсов
                let totalTransported = 0;
                for (const truck of trucks) {
                    const transportableAmount = Math.min(
                        truck.capacity, // Максимальная вместимость грузовика
                        currentResources, // Доступные ресурсы на предприятии
                        warehouse.capacity - getWarehouseUsedCapacity(warehouse) // Свободное место на складе
                    );

                    if (transportableAmount > 0) {
                        // Обновляем данные склада
                        warehouse[resourceType] =
                            (warehouse[resourceType] || 0) + transportableAmount;

                        // Уменьшаем ресурсы на предприятии
                        enterprise.currentResources -= transportableAmount;

                        await warehouse.save();
                        await enterprise.save();

                        totalTransported += transportableAmount;

                        console.log(
                            `Грузовик ${truck.id} перевёз ${transportableAmount} единиц ${resourceType}.`
                        );
                    }

                    // Прекращаем, если ресурсы закончились
                    if (enterprise.currentResources === 0) break;
                }

                if (totalTransported === 0) {
                    console.log(
                        `Предприятие ${id}: склад заполнен, транспортировка невозможна.`
                    );
                }
            } else {
                console.log(`Предприятие ${id}: нет ресурсов для транспортировки.`);
            }
        }
    } catch (error) {
        console.error('Ошибка транспортировки ресурсов:', error);
    }
};

// Расчёт используемой ёмкости склада
const getWarehouseUsedCapacity = (warehouse) => {
    const resources = ['wood', 'coal', 'oil', 'metall', 'gold', 'diamond'];
    return resources.reduce((sum, resource) => sum + (warehouse[resource] || 0), 0);
};

const CHANNEL_ID = '@campfiregg'; // Замените на username вашего канала
let resourceMessageId = 4; // Хранение ID сообщения

const previousPrices = {}; // Объект для хранения предыдущих цен

const getResourcePricesText = async () => {
    const resources = await ResourcePriceModel.findAll(); // Получаем данные из базы
    let message = '💰 **Актуальные цены на ресурсы:**\n\n';

    resources.forEach((resource) => {
        const currentPrice = resource.price;
        const previousPrice = previousPrices[resource.resource] || currentPrice; // Берем предыдущую цену или текущую, если нет данных

        // Определяем эмодзи изменения цены
        let trendEmoji = '⚖️'; // По умолчанию стабильность
        if (currentPrice > previousPrice) {
            trendEmoji = '📈'; // Рост
        } else if (currentPrice < previousPrice) {
            trendEmoji = '📉'; // Падение
        }

        // Сохраняем текущую цену как предыдущую для следующего сравнения
        previousPrices[resource.resource] = currentPrice;

        // Добавляем строку с ценой и эмодзи
        message += `• ${getEnterpriseEmoji(resource.resource)} ${getReadableResourceType(resource.resource)}: ${trendEmoji} ${utils.spaces(currentPrice)} руб/ед.\n`;
    });

    message += `\n🔁 Последнее обновление цены: ${utils.getCurrentTime()}`;
    return message;
};

// Функция для отправки/обновления сообщения
const updateResourcePricesMessage = async () => {
    const pricesText = await getResourcePricesText();

    try {
        if (resourceMessageId) {
            // Если сообщение существует, обновляем его
            await bot.telegram.editMessageText(CHANNEL_ID, resourceMessageId, null, pricesText, {
                parse_mode: 'Markdown',
            });
        } else {
            // Если сообщения нет, отправляем новое
            const sentMessage = await bot.telegram.sendMessage(CHANNEL_ID, pricesText, {
                parse_mode: 'Markdown',
            });
            resourceMessageId = sentMessage.message_id; // Сохраняем ID нового сообщения
            console.log("ID сообщения с котировками: " + sentMessage.message_id)
        }
    } catch (error) {
        console.error('Ошибка при обновлении сообщения с ценами ресурсов:', error);
    }
};

// Запускаем функцию
updateResourcePricesMessage();
// Запускаем процесс восстановления цен каждые 15 минут
setInterval(recoverResourcePrices, 15 * 60 * 1000);
// Запускаем обновление каждые 15 минут
setInterval(updateResourcePricesMessage, 15 * 60 * 1000);
// Запускаем процессы каждый час
setInterval(resourceProduction, 60 * 60 * 1000);
setInterval(resourceTransportation, 60 * 60 * 1000);


bot.command('force_prod', async (ctx) => {
    resourceProduction() 
    return await ctx.reply(`Принудительно добыто.`)
})

bot.command('force_transport', async (ctx) => {
    resourceTransportation()
    return await ctx.reply(`Принудительно перевезено.`)
})

bot.command('force_hour', async (ctx) => {
    resourceProduction()
    resourceTransportation()
    return await ctx.reply(`Принудительный час.`)
})

/////////////////////////////////////Enterprise Update end//////////////////////////////////////////////////

/////////////////////////////////////Admin Commands//////////////////////////////////////////////////


bot.command('answer', commands.reportAnswer)

bot.command('fastblock', commands.fastblock)

bot.command('createpromocode', commands.createPromo)

bot.command('genpromo', commands.genPromo)

///////////////////////////////////////Functions//////////////////////////////////////////////////////

setInterval(() => {
    var today = new Date();
    let hours = today.getHours();
    if (hours == "0" || hours == "12") {
        //weaponShopUpdate()
        //matPriceUpdate()
    }
    /*if (hours == "9" || hours == "18" || hours == "12") {
        generatePromo()
    }*/
}, 3600000);

start()

bot.launch()