const { Telegraf, Scenes, session, Markup, Stage, Composer } = require('telegraf');
const schedule = require('node-schedule');
const { faker, fakerRU } = require('@faker-js/faker');
// Подключаем необходимые библиотеки
const { Op } = require('sequelize');
const sequelize = require('./db'); // Подключение базы данных
// Подключаем обработчики
const utils = require('./utils');
const handlers = require('./handlers');
const {
  phones,
  expToUp,
  UserModel,
  CharacterModel,
  InventoryModel,
  ItemsModel,
  Enemy,
  Location,
  Battle,
  StolenCardsModel,
  WorldModel,
  PropertyModel,
  AFKPropertyModel,
  BusinessModel,
  BlockModel,
  EnterpriseModel,
  WarehouseModel,
  TruckModel,
  ResourcePriceModel,
  SkillsModel,
  DailyModel
} = global.config
const rpg = new Composer();

rpg.use(async (ctx, next) => {
  if (ctx.update.edited_channel_post) return console.log(`[RPG] Channel post updated`);
  let id = ctx.from.id
  let username = ctx.from.username;
  if (username == null) username = ctx.from.id;

  const currentTime = utils.getCurrentTime();

  switch (ctx.updateType) {
    case 'message':
      console.log(`${currentTime}: [RPG] ${username}: ${ctx.update.message.text}`);
      break;

    case 'callback_query':
      console.log(`${currentTime}: [RPG] ${username}: ${ctx.update.callback_query.data}`);
      break;

    case 'edited_message':
      console.log(`${currentTime}: [RPG] ${username} edited: ${ctx.update.edited_message.text}`);
      break;

    default:
      console.log(`${currentTime}: [RPG] Unknown update type:`, ctx.update);
  }

  await next(); // Передаем управление следующему middleware
});

rpg.hears('RPG', async (ctx) => {
  let message = `Меню:\n`;
  const buttons = [];
  buttons.push([{ text: 'Мой Персонаж', callback_data: 'rpg_profile' }]);
  return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize());
});

rpg.action('rpg_profile', async (ctx) => {
  const telegramId = ctx.from.id;

  // Ищем персонажа
  const character = await CharacterModel.findOne({ where: { telegram_id: telegramId } });
  const stolenCards = await StolenCardsModel.findAll({
    where: { userId: character.telegram_id }
  });

  if (!character) {
    return ctx.reply('Персонаж не найден. Создайте нового персонажа, чтобы начать игру!');
  }

  // Формируем профиль
  const profile = `
🎭 Профиль персонажа

👤 Имя: ${character.name || 'Не указано'}
🏆 Уровень: ${character.level} (${character.exp}/${utils.spaces(expToUp[character.level])})

❤️ Здоровье: ${character.hp}/${character.max_hp}
🔥 Стамина: ${character.stamina}/${character.max_stamina}

💪 Сила (F): ${character.force}
🧠 Интеллект (I): ${character.intelligence}
🛡️ Устойчивость (R): ${character.resilience}
🔋 Выносливость (E): ${character.endurance}
➕ Свободные очки F.I.R.E: ${character.firePoints}

💰 Баланс: ${utils.spaces(character.dirtymoney)}Ð
🃏 Украденные карты: ${stolenCards.length}
    `;
  const buttons = [
    [Markup.button.callback('💳 Карточки', 'view_cards')],
    [Markup.button.callback('🎒 Инвентарь', 'inventory')],
  ];

  if (character.firePoints >= 1) {
    buttons.push([Markup.button.callback('➕ Распределить очки', 'fire_distribute')]);
  }
  buttons.push([Markup.button.callback('🔙 В меню', 'crime_menu')]);
  // Отправляем сообщение
  ctx.editMessageText(profile.trim(), Markup.inlineKeyboard(buttons));
});

// Основная команда для вывода кнопок распределения F.I.R.E.
rpg.action('fire_distribute', async (ctx) => {
  // Получаем данные пользователя
  const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
  if (!character) {
    return ctx.reply('Вы ещё не создали персонажа!');
  }

  // Проверяем, есть ли свободные очки
  if (character.firePoints <= 0) {
    return ctx.reply('У вас нет свободных очков для распределения.');
  }

  // Формируем текст сообщения
  const message = `
🔥 Распределение очков F.I.R.E 🔥

У вас есть ${character.firePoints} свободных очков.
Выберите характеристику, чтобы увеличить её уровень:

💪 Сила (F): ${character.force}
🧠 Интеллект (I): ${character.intelligence}
🛡️ Устойчивость (R): ${character.resilience}
🔋 Выносливость (E): ${character.endurance}
  `;

  // Создаём кнопки для каждой характеристики
  const keyboard = Markup.inlineKeyboard([
    Markup.button.callback('💪', 'increase_force'),
    Markup.button.callback('🧠', 'increase_intelligence'),
    Markup.button.callback('🎯', 'increase_resilience'),
    Markup.button.callback('💖', 'increase_endurance'),
  ], { columns: 2 });

  // Отправляем сообщение с кнопками
  await ctx.reply(message, keyboard);
});

// Обработчики для нажатий на кнопки
rpg.action(/^increase_(force|intelligence|resilience|endurance)$/, async (ctx) => {
  const attribute = ctx.match[1]; // Получаем характеристику из callback_data
  const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
  if (!character) {
    return ctx.answerCbQuery('Персонаж не найден.');
  }

  // Проверяем наличие свободных очков
  if (character.firePoints <= 0) {
    return ctx.answerCbQuery('У вас недостаточно очков!');
  }

  // Прокачиваем выбранную характеристику
  switch (attribute) {
    case 'force':
      character.force++;
      break;
    case 'intelligence':
      character.intelligence++;
      break;
    case 'resilience':
      character.resilience++;
      break;
    case 'endurance':
      character.endurance++;
      break;
  }

  // Уменьшаем количество очков и сохраняем изменения
  character.firePoints--;
  await character.save();

  // Отправляем обновлённое сообщение
  const updatedMessage = `
🔥 Распределение очков F.I.R.E 🔥

У вас есть ${character.firePoints} свободных очков.
Выберите характеристику, чтобы увеличить её уровень:

💪 Сила (F): ${character.force}
🧠 Интеллект (I): ${character.intelligence}
🛡️ Устойчивость (R): ${character.resilience}
🔋 Выносливость (E): ${character.endurance}
  `;
  await ctx.editMessageText(updatedMessage, { reply_markup: ctx.update.callback_query.message.reply_markup });

  ctx.answerCbQuery(`Вы увеличили ${attribute.toUpperCase()}!`);
});


const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// Хранилище для отслеживания пользователей, которые уже прошли ввод
const usersCrimeNet = new Set();

rpg.hears('CampFireGG.Crime', async (ctx) => {
  const userId = ctx.from.id;
  const character = await CharacterModel.findOne({ where: { telegram_id: userId } });
  if (!usersCrimeNet.has(userId) && character.level === 1) {
    // Если пользователь вводит команду впервые
    usersCrimeNet.add(userId);
    const username = ctx.from.username || 'User';
    const randomServer = `secure.net-${Math.floor(Math.random() * 99 + 1)}.campfiregg.crime`;
    const sshCommand = `ssh ${username}@${randomServer}`;

    // Сообщение для симуляции
    const lines = [
      `${sshCommand}`,
      `> Connecting to secure servers with RSA key...`,
      `> Authentication in progress...`,
      `> User "${username}" identified.`,
      `> Accessing CampFireGG.Crime...`,
      `> Connection established. Welcome, ${username}.`,
    ];

    // Отправляем первое сообщение
    let sentMessage = await ctx.reply('> Initializing CampFireGG.Crime...');

    // Симуляция показа строки ssh блоками
    let currentText = '';
    let index = 0;

    while (index < lines[0].length) {
      const blockSize = Math.floor(Math.random() * 3) + 2; // Генерируем блок от 2 до 4 символов
      currentText += lines[0].slice(index, index + blockSize); // Добавляем блок текста
      index += blockSize; // Увеличиваем индекс
      await ctx.telegram.editMessageText(sentMessage.chat.id, sentMessage.message_id, undefined, currentText);
      await delay(100); // Задержка между блоками
    }

    // Последующие строки добавляются полностью, по одной
    for (let i = 1; i < lines.length; i++) {
      await delay(1500); // Задержка между строками
      currentText += `\n${lines[i]}`;
      await ctx.telegram.editMessageText(sentMessage.chat.id, sentMessage.message_id, undefined, currentText);
    }

    // Финальное меню после задержки
    await delay(2000);
    const buttons = [
      [Markup.button.callback('💼 Задачи', 'crime_missions')],
      [Markup.button.callback('📊 Профиль', 'rpg_profile')],
    ];

    //buttons.push([Markup.button.callback('💳 Карточки', 'view_cards')]);

    // Добавляем кнопку сообщения, если уровень персонажа равен 1
    if (character && character.level === 1) {
      buttons.push([Markup.button.callback('📩 (1) Сообщение', '1st_message')]);
    }

    await ctx.telegram.editMessageText(
      sentMessage.chat.id,
      sentMessage.message_id,
      undefined,
      `🚨 Добро пожаловать в CampFireGG.Crime 🚨\n\n`,
      Markup.inlineKeyboard(buttons)
    )
  } else {
    // Показываем только меню, если команда уже была введена
    await ctx.reply(
      `🚨 Добро пожаловать в CampFireGG.Crime 🚨\n\n`,
      Markup.inlineKeyboard([
        [Markup.button.callback('💼 Задачи', 'crime_missions')],
        [Markup.button.callback('📊 Профиль', 'rpg_profile')],
        [Markup.button.callback('💰 Магазин', 'shop')],
      ])
    );
  }
});

rpg.action('1st_message', async (ctx) => {
  await ctx.answerCbQuery();
  const message = `👤 Сообщение от неизвестного пользователя:
\`\`\`
"Добро пожаловать в CampFireGG.Crime. Если ты здесь, значит, у тебя есть вопросы. Забудь о них. Просто слушай."

🔥 F.I.R.E — твой путь к успеху:
"Каждый из нас что-то может. Кто-то силён, кто-то вынослив, а кто-то дохуя умный. В мире CampFireGG.Crime это называется F.I.R.E. Запомни эти буквы — от них зависит твоя жизнь здесь."

Force: Твоя мощь. Определяет, сколько импакта ты можешь внести. Чем выше, тем проще ликвидировать цель.

Intelligence: Твой интеллект. Чем ты умнее, тем больше шансов, что операция пройдет гладко. А ещё мозги ускоряют твое обучение.

Resilience: Твоя стойкость. Сколько времени тебе нужно, чтобы встать на ноги после провала? Чем выше этот параметр, тем быстрее ты восстанавливаешься.

Endurance: Твоя выносливость. Без неё ты не сможешь много работать, а значит, и много зарабатывать.

💰 Деньги? Грязные. Иначе здесь не бывает.
"Всё, что ты заработаешь здесь, будет грязным. Потратить можно только здесь, но есть способ отмыть деньги и перенести их на свой основной счёт. Всё зависит от твоего желания и возможностей."

💳 Карты? Да, их можно обналичить.
"Карточки — это всегда плюс. Взломал, достал, получил деньги. Всё просто. Главное — не профукай их."

🕶️ Последний совет:
"Каждое действие — это риск. Чем больше ты идёшь на риск, тем больше получаешь. Но если ошибёшься, можешь встрять. Так что думай."

"Добро пожаловать. Удачи тебе, новобранец."
\`\`\`
`;

  await ctx.replyWithMarkdownV2(message, { disable_web_page_preview: true });
});

rpg.action('view_cards', async (ctx) => {
  try {
    // Получаем пользователя по Telegram ID
    const character = await CharacterModel.findByPk(ctx.from.id);

    if (!character) {
      return ctx.reply('Персонаж не найден!');
    }

    // Получаем все украденные карточки для этого пользователя
    const stolenCards = await StolenCardsModel.findAll({
      where: { userId: character.telegram_id }
    });

    if (stolenCards.length === 0) {
      return ctx.reply('У вас нет украденных карточек.');
    }

    const buttons = [];
    let message = 'Ваши украденные карты:\n\n';

    stolenCards.forEach(card => {
      const lastFourDigits = card.cardNumber.slice(-4); // Берем последние 4 цифры карточки
      message += `🔒 Карта: *${lastFourDigits}\n`;

      // Генерация кнопок для брутфорса и покупки за лимит
      buttons.push([
        Markup.button.callback(`💳 *${lastFourDigits}`, `brutecard_${card.id}`),
        //Markup.button.callback(`💰 *${lastFourDigits}`, `limitbuy_${card.id}`)
        Markup.button.callback('🔙 В меню', 'crime_menu'),
      ]);
    });

    // Отправляем сообщение с кнопками
    await ctx.reply(message, Markup.inlineKeyboard(buttons));

  } catch (error) {
    console.error('Ошибка при выводе карточек:', error);
    await ctx.reply('Произошла ошибка при получении ваших карточек.');
  }
});

rpg.action(/limitbuy_/, async (ctx) => {
  try {
    const cardId = ctx.match.input.split('_')[1]; // ID карточки
    const card = await StolenCardsModel.findByPk(cardId); // Получаем карточку

    if (!card) {
      return ctx.answerCbQuery('Карточка не найдена.');
    }

    const character = await CharacterModel.findByPk(ctx.from.id); // Получаем персонажа
    if (!character) {
      return ctx.answerCbQuery('Персонаж не найден.');
    }

    // Получаем 10 случайных предметов из базы
    const items = await ItemsModel.findAll({ limit: 10 });

    // Если у пользователя нет записей о попытках, создаем их
    if (!attempts[ctx.from.id]) {
      attempts[ctx.from.id] = 0;
    }

    // Генерация кнопок с предметами
    const buttons = [];
    items.forEach(item => {
      const buttonText = `${item.name} - ¥${item.price}`;
      buttons.push([Markup.button.callback(buttonText, `purchase_${item.id}_${card.id}`)]);
    });

    await ctx.reply(
      'Выберите товар для покупки:\nПопробуйте угадать лимит карты.\n\n',
      Markup.inlineKeyboard(buttons)
    );
  } catch (error) {
    console.error('Ошибка при обработке покупки через лимит:', error);
  }
});

rpg.action(/purchase_/, async (ctx) => {
  try {
    const [_, itemId, cardId] = ctx.match.input.split('_');
    const item = await ItemsModel.findByPk(itemId);
    const card = await StolenCardsModel.findByPk(cardId);
    const character = await CharacterModel.findByPk(ctx.from.id);

    if (!item || !card || !character) {
      return ctx.answerCbQuery('Ошибка при обработке покупки.');
    }


    // Проверяем, не исчерпаны ли попытки
    if (attempts[ctx.from.id] >= 3) {
      // Сбрасываем попытки и уничтожаем карточку
      delete attempts[ctx.from.id];
      await StolenCardsModel.destroy({ where: { id: cardId } });

      return ctx.editMessageText(
        '❌ Все попытки исчерпаны! Карточка стала недействительной.'
      );
    }

    // Если баланс карты меньше, чем цена товара, увеличиваем количество попыток
    if (card.balance < item.price) {
      attempts[ctx.from.id]++;
      await ctx.answerCbQuery(`Недостаточно средств! Попыток осталось: ${3 - ctx.session.attempts}`);
      return ctx.editMessageText(`Вы выбрали товар за ¥${item.price}, но у вас недостаточно средств.`);
    }

    // Если баланс карты достаточно для покупки, добавляем предмет в инвентарь
    character.InventoryModel.push(item.id);
    await character.save();

    // Если товар электронный, начисляем процент от стоимости на счет
    if (item.type === 'digital') {
      const profit = Math.round(item.price * 0.2);  // 20% от стоимости товара
      character.dirtymoney += profit;
      await character.save();
      await ctx.answerCbQuery(`Вы приобрели ${item.name} и перепродали за ¥${profit}.`);
    } else {
      await ctx.answerCbQuery(`Вы купили ${item.name}.`);
    }

    // Блокируем карту после покупки
    card.destroy({ where: { id: cardId } });
    await card.save();

    // Оповещаем пользователя
    await ctx.editMessageText(`${item.name} успешно куплен! Карта заблокирована.`);
  } catch (error) {
    console.error('Ошибка при обработке покупки:', error);
  }
});

rpg.action(/purchase_fail_/, async (ctx) => {
  try {
    const [_, itemId, cardId] = ctx.match.input.split('_');
    const item = await ItemsModel.findByPk(itemId);
    const card = await StolenCardsModel.findByPk(cardId);

    if (!item || !card) {
      return ctx.answerCbQuery('Ошибка при проверке предмета или карты.');
    }

    await ctx.answerCbQuery('Недостаточно средств для покупки.');
  } catch (error) {
    console.error('Ошибка при обработке неудачной покупки:', error);
  }
});


// Обработка попытки взлома карточки
rpg.action(/brutecard_/, async (ctx) => {
  const cardId = ctx.match.input.split('_')[1]; // Получаем ID карточки из callback_data
  const card = await StolenCardsModel.findByPk(cardId); // Ищем карточку в базе данных
  const inventory = await InventoryModel.findAll({ where: { telegram_id: ctx.from.id } }); // Загружаем предметы из инвентаря

  if (!card) {
    return ctx.answerCbQuery('Карточка не найдена.');
  }

  // Проверяем наличие "Эмулятора картридера" в инвентаре
  const emulator = inventory.find((item) => item.text_id === 'cardreader_emulator');
  if (!emulator) {
    return ctx.reply('Для запуска брутфорса вам нужен "Эмулятор картридера".');
  }

  // Удаляем "Эмулятор картридера" из инвентаря
  await InventoryModel.destroy({ where: { id: emulator.id } });

  const buttonsCount = 10; // Количество кнопок
  const winButton = utils.rand(1, buttonsCount); // Выбираем случайную кнопку для успешного пина
  const maxAttempts = 3; // Максимальное количество попыток

  // Если у пользователя нет записей о попытках, создаем их
  if (!attempts[ctx.from.id]) {
    attempts[ctx.from.id] = 0;
  }

  // Генерация кнопок
  const buttons = [];
  let fakePin = 1234
  for (let i = 1; i <= buttonsCount; i++) {
    if (i === winButton) {
      // Если это победная кнопка (правильный ПИН)
      buttons.push({ text: `${card.pin}`, callback_data: `brute_success_${cardId}` });
    } else {
      fakePin = faker.finance.pin()
      // Если это неудачная кнопка (случайный ПИН)
      buttons.push({ text: `${fakePin}`, callback_data: `brute_fail_${cardId}_${i}` });
    }
  }

  // Разбиваем кнопки на строки по 5 кнопок
  const rows = [];
  while (buttons.length > 0) {
    rows.push(buttons.splice(0, 5)); // Разбиваем на подмассивы по 5 кнопок
  }

  // Сортируем кнопки случайным образом
  const keyboard = Markup.inlineKeyboard(
    rows.sort(() => Math.random() - 0.5).map((row) => row) // Сортируем строки кнопок случайным образом
  );

  // Отправляем сообщение с клавиатурой
  await ctx.reply(
    `💳 Брутфорс карты\n
  ━━━━━━━━━━━━━━━━━━━━
  ${card.bankName.toUpperCase()}
  ━━━━━━━━━━━━━━━━━━━━
  Номер: ${card.cardNumber}
  CVV: ${card.cvv}
  Владелец: ${card.holderName.toUpperCase()}
  Срок действия: ${card.expiresDate}
  ━━━━━━━━━━━━━━━━━━━━
  
  Попробуйте подобрать правильный ПИН-код. У вас есть ${maxAttempts - attempts[ctx.from.id]} попыток.
  
  "Эмулятор картридера" был использован.`,
    keyboard
  );

});


// Обработка неудачной попытки взлома
rpg.action(/brute_fail_/, async (ctx) => {
  const cardId = ctx.match.input.split('_')[2];
  const maxAttempts = 3;  // Максимальное количество попыток

  // Увеличиваем количество попыток
  attempts[ctx.from.id]++;

  // Проверяем, не исчерпаны ли попытки
  if (attempts[ctx.from.id] >= maxAttempts) {
    // Сбрасываем попытки и уничтожаем карточку
    delete attempts[ctx.from.id];
    await StolenCardsModel.destroy({ where: { id: cardId } });

    return ctx.editMessageText(
      '❌ Все попытки исчерпаны! Карточка стала недействительной.'
    );
  }

  // Ответ на нажатие кнопки
  ctx.answerCbQuery(`❌ Неправильный ПИН. Попыток осталось: ${maxAttempts - attempts[ctx.from.id]}`);

  // Обновляем клавиатуру
  const card = await StolenCardsModel.findByPk(cardId);
  const buttonsCount = 10;
  const winButton = utils.rand(1, buttonsCount);
  const buttons = [];
  let fakePin = 1234

  for (let i = 1; i <= buttonsCount; i++) {
    fakePin = faker.finance.pin()
    if (i === winButton) {
      buttons.push({ text: `${card.pin}`, callback_data: `brute_success_${cardId}` });
    } else {
      buttons.push({ text: `${fakePin}`, callback_data: `brute_fail_${cardId}_${i}` });
    }
  }

  const rows = [];
  while (buttons.length > 0) {
    rows.push(buttons.splice(0, 5));
  }

  const keyboard = Markup.inlineKeyboard(
    rows.sort(() => Math.random() - 0.5).map((row) => row)
  );

  // Обновляем сообщение с клавиатурой
  await ctx.editMessageText(
    `💳 Брутфорс карты\n
  ━━━━━━━━━━━━━━━━━━━━
  ${card.bankName.toUpperCase()}
  ━━━━━━━━━━━━━━━━━━━━
  Номер: ${card.cardNumber}
  CVV: ${card.cvv}
  Владелец: ${card.holderName.toUpperCase()}
  Срок действия: ${card.expiresDate}
  ━━━━━━━━━━━━━━━━━━━━
  
  Попробуйте подобрать правильный ПИН-код. У вас есть ${maxAttempts - attempts[ctx.from.id]} попыток.`,
    keyboard
  );
});

// Обработка успешной попытки взлома
rpg.action(/brute_success_/, async (ctx) => {

  const cardId = ctx.match.input.split('_')[2];
  const card = await StolenCardsModel.findByPk(cardId);
  if (!card) {
    return ctx.answerCbQuery('Карточка не найдена.');
  }
  delete attempts[ctx.from.id];
  const amount = card.balance;  // Сумма денег за карточку
  const character = await CharacterModel.findByPk(ctx.from.id);

  // Увеличиваем грязные деньги пользователя
  character.dirtymoney += amount;
  await character.save();

  // Удаляем карточку
  await card.destroy();

  // Отправляем сообщение о выигрыше
  await ctx.editMessageText(
    `💳 Брутфорс карты\n
  ━━━━━━━━━━━━━━━━━━━━
  ${card.bankName.toUpperCase()}
  ━━━━━━━━━━━━━━━━━━━━
  Номер: ${card.cardNumber}
  CVV: ${card.cvv}
  Владелец: ${card.holderName.toUpperCase()}
  Срок действия: ${card.expiresDate}
  ━━━━━━━━━━━━━━━━━━━━
  
  ✅ Взлом успешен! Вы получили Ð${amount}.`
  );
});




// Обработчики кнопок
rpg.action('crime_missions', async (ctx) => {
  await ctx.answerCbQuery();
  await ctx.editMessageText(`💼 **Задачи:**\n Для карманных краж тебе не нужно ничего, главное не попадись.\n А вот после ограбления магазина в переулке не спрячешься, без тачки на миссию нельзя.`,
    Markup.inlineKeyboard([
      [{ text: 'Карманные кражи [1 lvl.]', callback_data: `POCKET_ACTION` }],
      [{ text: 'Магазин [5 lvl.]', callback_data: `SHOP_ACTION` }],
      //[{text: 'Банкомат', callback_data: `WIP`}], 
      // [{text: 'Банковское отделение', callback_data: `WIP`}], 
      //[{text: 'Угон', callback_data: `WIP`}], 
      // [{text: 'Ювелирка', callback_data: `WIP`}], 
      //[{text: 'Банк', callback_data: `WIP`}],
      [{ text: '🔙 В меню', callback_data: `crime_menu` }]
    ]),
  );
});

rpg.action(`POCKET_ACTION`, async (ctx) => {
  let user = await UserModel.findByPk(ctx.from.id)
  let character = await CharacterModel.findByPk(ctx.from.id);
  let pocketsteal = character.pocketstealcd
  if (character.level < 1) return ctx.editMessageText('Доступно с 1 уровня!')
  if (character.stamina < 10) return ctx.editMessageText('Вы устали!')
  let cooldown = utils.setCooldown(character, 3600, pocketsteal)
  if (character.pocketstealcd > cooldown.currentTime) return ctx.editMessageText(`📛 Данное действие будет доступно через ${cooldown.timeLeftInMinutes} мин.`);
  character.pocketstealcd = cooldown.endTime
  character.stamina -= 10
  character.save()
  ctx.editMessageText('Выберите объект', Markup.inlineKeyboard([
    [
      { text: 'Карман', callback_data: `POCKET_TARGET` },
      { text: 'Бумажник', callback_data: `POCKET_WALLET` },
      { text: 'Сумка', callback_data: `POCKET_BAG` }
    ]
  ]))
});

rpg.action(`POCKET_TARGET`, async (ctx) => {
  ctx.editMessageText('В кармане обнаружено', Markup.inlineKeyboard([
    [
      { text: 'Деньги', callback_data: `MONEY_IN_POCKET` },
      { text: 'Телефон', callback_data: `PHONE` }
    ]
  ]))
});

rpg.action(`MONEY_IN_POCKET`, async (ctx) => {
  // Получаем пользователя и его персонажа
  //let user = await UserModel.findByPk(ctx.from.id);
  let character = await CharacterModel.findByPk(ctx.from.id);

  if (!character) {
    return ctx.editMessageText('У вас нет персонажа. Создайте его перед началом.');
  }

  // Расчёт шанса на успешную кражу
  let baseChance = 40; // Базовый шанс
  let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
  let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
  if (randomRoll > chance) {
    Exp(ctx, character, 1)
    return ctx.editMessageText('Вы были замечены во время кражи.');
  }
  // Успешная кража
  let moneyIn = utils.rand(5, 1000);
  Exp(ctx, character, character.intelligence + 3)
  character.dirtymoney += moneyIn;
  await character.save();
  return ctx.editMessageText(`Вы успешно украли Ð${utils.spaces(moneyIn)} из кармана.`);
});


rpg.action(`PHONE`, async (ctx) => {
  let character = await CharacterModel.findByPk(ctx.from.id);
  //let user = await UserModel.findByPk(ctx.from.id)
  let property = await PropertyModel.findByPk(ctx.from.id);
  // Расчёт шанса на успешную кражу
  let baseChance = 20; // Базовый шанс
  let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
  let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
  if (chance < randomRoll) {
    Exp(ctx, character, 1)
    return ctx.editMessageText('Вы были замечены во время кражи.')
  }
  let randPhone = utils.rand(1, 10)
  if (property.mobile.name) {
    let dirtyMoney = Math.round(phones[randPhone].price / 100 * 70)
    Exp(ctx, character, character.intelligence + 10)
    character.dirtymoney += dirtyMoney
    return await ctx.reply(`Вы сбыли украденный ${phones[randPhone].name} за Ð${utils.spaces(dirtyMoney)}`)
  }
  property.mobile = phones[randPhone]
  await character.save()
  await property.save()
  return ctx.editMessageText(`Вы успешно украли ${phones[randPhone].name} из кармана.`)
});

rpg.action(`POCKET_WALLET`, async (ctx) => {
  ctx.editMessageText('В бумажнике обнаружено', Markup.inlineKeyboard([
    [
      { text: 'Деньги', callback_data: `MONEY_IN_WALLET` },
      { text: 'Карточка', callback_data: `CARD_IN_WALLET` }
    ]
  ]))
});

rpg.action(`MONEY_IN_WALLET`, async (ctx) => {
  //let user = await UserModel.findByPk(ctx.from.id)
  let character = await CharacterModel.findByPk(ctx.from.id);
  // Расчёт шанса на успешную кражу
  let baseChance = 35; // Базовый шанс
  let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
  let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
  if (chance < randomRoll) {
    Exp(ctx, character, 1)
    return ctx.editMessageText('Вы были замечены во время кражи.')
  }
  let moneyIn = utils.rand(1000, 10000)
  Exp(ctx, character, character.intelligence + 5)
  character.dirtymoney += moneyIn
  character.save()
  return ctx.editMessageText(`Вы успешно украли Ð${utils.spaces(moneyIn)} из бумажника.`)
});

rpg.action(`CARD_IN_WALLET`, async (ctx) => {
  //let user = await UserModel.findByPk(ctx.from.id)
  let character = await CharacterModel.findByPk(ctx.from.id);
  let baseChance = 20; // Базовый шанс
  let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
  let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
  if (chance < randomRoll) {
    Exp(ctx, character, 2)
    return ctx.editMessageText('Вы были замечены во время кражи.')
  }
  Exp(ctx, character, character.intelligence + 7)
  generateCard(ctx.from.id)
  character.save()
  return ctx.editMessageText(`Вы успешно украли 💳 из бумажника.`)
});

rpg.action(`POCKET_BAG`, async (ctx) => {
  //let user = await UserModel.findByPk(ctx.from.id)
  let character = await CharacterModel.findByPk(ctx.from.id);
  let baseChance = 20; // Базовый шанс
  let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
  let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
  if (chance < randomRoll) {
    Exp(ctx, character, 1)
    return ctx.editMessageText('Вы были замечены во время кражи.')
  }
  let times = utils.rand(2, 20)
  let moneyIn = 0
  let text = ``
  let values = 0

  for (i = 1; i <= times; i++) {
    randomize = utils.rand(1, 100)
    switch (randomize) {
      case 2:
        values = utils.rand(10000, 50000)
        moneyIn += values
        text += `+ Ð${utils.spaces(values)}\n`
        break;
      case 7:
        values = utils.rand(10000, 100000)
        moneyIn += values
        text += `+ Ð${utils.spaces(values)}\n`
        break;
      default:
        values = utils.rand(100, 3000)
        moneyIn += values
        text += `+ Ð${utils.spaces(values)}\n`
        break;
    }
  }
  Exp(ctx, character, character.intelligence + times)
  character.dirtymoney += moneyIn
  character.save()
  return ctx.editMessageText(`Вы успешно украли сумку и сбыли все ценности из нее:\n${text}\nОбщий куш: Ð${utils.spaces(moneyIn)}`)
});

rpg.action('crime_menu', async (ctx) => {
  await ctx.answerCbQuery();
  await ctx.editMessageText(
    `💻 CampFireGG.Crime Menu`,
    Markup.inlineKeyboard([
      [Markup.button.callback('💼 Задачи', 'crime_missions')],
      [Markup.button.callback('📊 Профиль', 'rpg_profile')],
      [Markup.button.callback('💰 Магазин', 'shop')],
    ])
  );
});

rpg.action('SHOP_ACTION', async (ctx) => {
  let user = await UserModel.findByPk(ctx.from.id)
  let character = await CharacterModel.findByPk(ctx.from.id);
  let property = await PropertyModel.findByPk(ctx.from.id);
  if (character.level < 5) return ctx.editMessageText('Доступно с 5 уровня!')
  if (property.car1 == 0) return ctx.editMessageText('Для данного задания нужна тачка.')
  if (character.stamina < 25) return ctx.editMessageText('Вы устали!')
  let shoprobcd = character.shoprobcd
  let cooldown = utils.setCooldown(character, 3600, shoprobcd)
  if (character.shoprobcd > cooldown.currentTime) return ctx.editMessageText(`📛 Данное действие будет доступно через ${cooldown.timeLeftInMinutes} мин.`);
  character.shoprobcd = cooldown.endTime
  character.stamina -= 25
  character.save()
  return ctx.editMessageText('Стадии:', Markup.inlineKeyboard([
    [{ text: 'Взлом кассы', callback_data: `SHOP_CASH_BREAK` }],
    [{ text: 'Разбить кассу', callback_data: `SHOP_CASH_SMASH` }]
  ]))
});

rpg.action(`SHOP_CASH_BREAK`, async (ctx) => {
  let character = await CharacterModel.findByPk(ctx.from.id);
  let baseChance = 20; // Базовый шанс
  let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
  let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
  let cashIn = utils.rand(1000, 10000)
  let timer = 1000
  if (chance < randomRoll) {
    const keyboard = generateKeyboard();
    ctx.deleteMessage()
    return ctx.reply('Касса закрыта, вы начали взлом замка:', keyboard);
    //ctx.editMessageText('Вы начали взлом кассы.');
    //return ctx.scene.enter('LOCKPICK')
  }
  for (i = 0; i < utils.rand(character.endurance, character.endurance + 15); i++) {
    setTimeout(() => {
      cashIn += utils.rand(1000, 10000)
      ctx.editMessageText(`⏏️ Вы достали из кассы: Ð${utils.spaces(cashIn)}`)
    }, timer)
    timer += 500
  }
  setTimeout(() => {
    Exp(ctx, character, character.intelligence + 25)
    character.dirtymoney += cashIn
    character.save()
    return ctx.editMessageText(`Вы достали из кассы Ð${utils.spaces(cashIn)}, пора валить.`, Markup.inlineKeyboard([
      [{ text: 'Завершить ограбление', callback_data: `SHOP_END` }]
    ]))
  }, timer + 300)
});

rpg.action(`SHOP_CASH_SMASH`, async (ctx) => {
  let character = await CharacterModel.findByPk(ctx.from.id);
  let baseChance = 20; // Базовый шанс
  let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
  let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
  let cashIn = utils.rand(1000, 10000)
  let timer = 1000
  if (chance < randomRoll) {
    Exp(ctx, character, 1)
    return ctx.editMessageText('Вы разбили кассовый аппарат, и сработала сигнализация. Вы сбежали.')
  }
  ctx.editMessageText('Вы разбили кассовый аппарат, и сработала сигнализация.')
  for (i = 0; i < utils.rand(character.endurance, character.endurance + 8); i++) {
    setTimeout(() => {
      cashIn += utils.rand(500, 5000)
      ctx.editMessageText(`⏏️ Вы в спешке достали из кассы: Ð${utils.spaces(cashIn)}`)
    }, timer)
    timer += 500
  }
  setTimeout(() => {
    Exp(ctx, character, character.intelligence + 10)
    character.dirtymoney += cashIn
    character.save()
    return ctx.editMessageText(`Вы в спешке достали из кассы Ð${utils.spaces(cashIn)}, пора валить.`, Markup.inlineKeyboard([
      [{ text: 'Завершить ограбление', callback_data: `SHOP_END` }]
    ]))
  }, timer + 300)
});

rpg.action(`SHOP_CASH_BREAK_SUCCESS`, async (ctx) => {
  let user = await UserModel.findByPk(ctx.from.id)
  let character = await CharacterModel.findByPk(ctx.from.id);
  delete attempts[ctx.from.id];
  let cashIn = utils.rand(1000, 10000)
  let timer = 100
  for (i = 0; i < utils.rand(character.endurance, character.endurance + 15); i++) {
    setTimeout(() => {
      cashIn += utils.rand(3000, 10000)
      ctx.editMessageText(`⏏️ Вы достали из кассы: Ð${utils.spaces(cashIn)}`)
    }, timer)
    timer += 500
  }
  setTimeout(() => {
    Exp(ctx, character, character.intelligence + 30)
    character.dirtymoney += cashIn
    character.save()
    return ctx.editMessageText(`Вы достали из кассы Ð${utils.spaces(cashIn)}, пора валить.`, Markup.inlineKeyboard([
      [{ text: 'Завершить ограбление', callback_data: `SHOP_END` }]
    ]))
  }, timer + 300)
});

rpg.action(`SHOP_END`, async (ctx) => {
  return ctx.editMessageText('Ограбление завершено!')
});

const attempts = {}; // Храним количество попыток взлома для каждого пользователя

rpg.action(/lock_*/, async (ctx) => {
  const userId = ctx.from.id;
  const buttonId = ctx.update.callback_query.data;

  // Если пользователя нет в списке попыток, добавляем его
  if (!attempts[userId]) {
    attempts[userId] = 0;
  }

  // Увеличиваем количество попыток
  attempts[userId] += 1;

  // Проверяем, не исчерпаны ли попытки
  if (attempts[userId] >= 5) {
    delete attempts[userId]; // Сбрасываем попытки после провала
    return ctx.editMessageText('Взлом провалился. Замок остается нетронутым.');
  }

  // Ответ на нажатие кнопки
  ctx.answerCbQuery(`Штифт не сдвинулся. Попыток осталось: ${5 - attempts[userId]}`);
  removeButton(ctx, buttonId);
});

rpg.action('inventory', async (ctx) => {
  try {
    const character = await CharacterModel.findByPk(ctx.from.id);

    if (!character) {
      return ctx.reply('Персонаж не найден!');
    }

    // Загружаем предметы из инвентаря
    const inventory = await InventoryModel.findAll({ where: { telegram_id: ctx.from.id } });

    if (inventory.length === 0) {
      return ctx.reply('Ваш инвентарь пуст.');
    }

    let message = '*Ваш инвентарь:*\n\n';

    // Группируем предметы по их состоянию (снаряженные/обычные)
    const equippedItems = inventory.filter((item) => item.equipped);
    const unequippedItems = inventory.filter((item) => !item.equipped);

    if (equippedItems.length > 0) {
      message += '🛡️ Снаряженные предметы:\n';
      equippedItems.forEach((item) => {
        message += `- ${item.name} (${item.type})\n`;
      });
      message += '\n';
    }

    if (unequippedItems.length > 0) {
      message += '🎒 Предметы в инвентаре:\n';
      unequippedItems.forEach((item) => {
        message += `- ${item.name} (${item.type})\n`;
      });
      message += '\n';
    }

    // Кнопки для взаимодействия
    const buttons = [
      ...unequippedItems.map((item) =>
        Markup.button.callback(`🔎 ${item.name}`, `view_item_${item.id}`)
      ),
      ...equippedItems.map((item) =>
        Markup.button.callback(`🚫 Снять ${item.name}`, `unequip_item_${item.id}`)
      ),
    ];
    buttons.push(Markup.button.callback('🔙 В меню', 'crime_menu'));

    await ctx.editMessageText(message, Markup.inlineKeyboard(buttons, { columns: 2 }));
  } catch (error) {
    console.error('Ошибка при выводе инвентаря:', error);
    await ctx.reply('Произошла ошибка при отображении вашего инвентаря.');
  }
});

rpg.action(/view_item_(\d+)/, async (ctx) => {
  const itemId = parseInt(ctx.match[1], 10);
  const item = await InventoryModel.findByPk(itemId);

  if (!item || item.telegram_id != ctx.from.id) {
    return ctx.reply('Этот предмет не найден в вашем инвентаре.');
  }

  const character = await CharacterModel.findByPk(ctx.from.id);

  if (!character) {
    return ctx.reply('Персонаж не найден.');
  }

  if (item.equipped) {
    return ctx.reply(`${item.name} уже снаряжен.`);
  }
  const buttons = []
  let message = `ℹ️ ${item.name}\n`
  message += `  📜 ${item.description}\n\n  〰️Редкость: ${item.rarity}\n  🔤Тип: ${item.type}`
  if (!item.equipped) {
    buttons.push([Markup.button.callback(`🎯 Использовать ${item.name}`, `use_item_${item.id}`)]);
  }
  if (item.equipped && item.canBeEquipped) {
    buttons.push([Markup.button.callback(`🚫 Снять ${item.name}`, `unequip_item_${item.id}`)]);
  }

  await ctx.replyWithMarkdown(message, Markup.inlineKeyboard(buttons, { columns: 2 }));
});

rpg.action(/use_item_(\d+)/, async (ctx) => {
  const itemId = parseInt(ctx.match[1], 10);
  const item = await InventoryModel.findByPk(itemId);

  if (!item || item.telegram_id != ctx.from.id) {
    return ctx.reply('Этот предмет не найден в вашем инвентаре.');
  }

  const character = await CharacterModel.findByPk(ctx.from.id);

  if (!character) {
    return ctx.reply('Персонаж не найден.');
  }

  if (item.equipped) {
    return ctx.reply(`${item.name} уже снаряжен.`);
  }

  if (!item.canBeEquipped) {
    return ctx.answerCbQuery(`🚫 ${item.name} нельзя сейчас использовать.`);
  }

  // Применяем эффекты предмета
  if (item.effectData) {
    const resultMessages = processEffects(character, item.effectData, true);
    await ctx.answerCbQuery(resultMessages, { show_alert: true });
  }

  if (item.canBeEquipped && item.type != 'consumable') {
    item.equipped = true;
    await item.save();
    ctx.reply(`Вы снарядили ${item.name}.`);
  }
  if (item.canBeEquipped && item.type == 'consumable') {
    await InventoryModel.destroy({ where: { id: item.id } });
    ctx.reply(`Вы использовали ${item.name}.`);
  }
});

rpg.action(/unequip_item_(\d+)/, async (ctx) => {
  const itemId = parseInt(ctx.match[1], 10);
  const character = await CharacterModel.findByPk(ctx.from.id);
  const item = await InventoryModel.findByPk(itemId);

  if (!item || item.telegram_id != ctx.from.id) {
    return ctx.answerCbQuery('Этот предмет не найден в вашем инвентаре.');
  }

  if (!item.equipped) {
    return ctx.answerCbQuery(`${item.name} не снаряжен.`);
  }

  if (item.effectData) {
    const resultMessages = processEffects(character, item.effectData, false);
    await ctx.editMessageText(resultMessages);
  }

  item.equipped = false;
  await item.save();

  ctx.answerCbQuery(`Вы успешно сняли ${item.name}.`);
});

rpg.action('shop', async (ctx) => {
  // Получаем текущую запись мира
  const world = await WorldModel.findOne({ where: { id: 1 } });
  if (!world) {
    return ctx.reply('Магазин недоступен.');
  }

  // Получаем ID предметов, доступных в магазине
  const { itemsInCrimeShop } = world;

  if (!itemsInCrimeShop || itemsInCrimeShop.length === 0) {
    return ctx.reply('Магазин пуст!');
  }

  // Загружаем только те предметы, ID которых есть в массиве
  const items = await ItemsModel.findAll({ where: { id: itemsInCrimeShop } });

  if (items.length === 0) {
    return ctx.reply('Магазин пуст!');
  }

  let message = 'Добро пожаловать в магазин! Здесь вы можете купить предметы:\n\n';

  // Генерируем кнопки, каждая кнопка будет в отдельной строке
  const buttons = items.map((item) => [
    Markup.button.callback(`${item.name} - ${item.price}₽`, `buy_item_${item.id}`)
  ]);
  buttons.push([Markup.button.callback('🔙 В меню', 'crime_menu')]);

  // Отправляем сообщение с клавиатурой
  await ctx.editMessageText(message, Markup.inlineKeyboard(buttons));
});

rpg.action(/buy_item_(\d+)/, async (ctx) => {
  const itemId = parseInt(ctx.match[1], 10);
  const item = await ItemsModel.findByPk(itemId);
  const inventory = await InventoryModel.findAll({ where: { telegram_id: ctx.from.id } });

  if (inventory.length >= 15) {
    return ctx.answerCbQuery('Инвентарь полон.', { show_alert: true });
  }

  if (!item) {
    return ctx.reply('Предмет не найден.');
  }

  const character = await CharacterModel.findByPk(ctx.from.id);

  if (!character) {
    return ctx.reply('Персонаж не найден.');
  }

  if (character.balance < item.price) {
    return ctx.answerCbQuery('У вас недостаточно средств для покупки этого предмета.', { show_alert: true });
  }

  // Снимаем деньги с баланса
  character.dirtymoney -= item.price;

  // Добавляем предмет в инвентарь
  await InventoryModel.create({
    telegram_id: ctx.from.id,
    name: item.name,
    text_id: item.text_id,
    description: item.description,
    effectData: item.effectData,
    price: item.price,
    rarity: item.rarity,
    type: item.type,
    duration: item.duration,
    canBeEquipped: item.canBeEquipped,
    equipped: false
  });

  await character.save();
  ctx.answerCbQuery(`Вы успешно купили ${item.name} за ${item.price}₽!`, { show_alert: true });
});

////////////////////////////////////////////////////////////////////////////////////////////

CharacterModel.prototype.addEquippedItem = async function (item) {
  // Проверяем, находится ли предмет в инвентаре персонажа
  const inventoryItem = await InventoryModel.findOne({
    where: { telegram_id: this.telegram_id, id: item.id },
  });

  if (!inventoryItem) {
    throw new Error('Предмет не найден в вашем инвентаре.');
  }

  // Проверяем, не снаряжен ли уже этот предмет
  if (inventoryItem.equipped) {
    throw new Error('Этот предмет уже снаряжен.');
  }

  // Снаряжаем предмет
  inventoryItem.equipped = true;
  await inventoryItem.save();

  // Применяем эффекты предмета
  let resultMessages = [];
  if (inventoryItem.effectData) {
    resultMessages = processEffects(this, inventoryItem.effectData, true);
    await this.save(); // Сохраняем изменения в характеристиках персонажа
  }

  return resultMessages;
};

CharacterModel.prototype.removeEquippedItem = async function (item) {
  // Проверяем, находится ли предмет в инвентаре персонажа
  const inventoryItem = await InventoryModel.findOne({
    where: { telegram_id: this.telegram_id, id: item.id },
  });

  if (!inventoryItem || !inventoryItem.equipped) {
    throw new Error('Этот предмет не снаряжен.');
  }

  // Снимаем предмет
  inventoryItem.equipped = false;
  await inventoryItem.save();

  // Убираем эффекты предмета
  let resultMessages = [];
  if (inventoryItem.effectData) {
    resultMessages = processEffects(this, inventoryItem.effectData, false);
    await this.save(); // Сохраняем изменения в характеристиках персонажа
  }

  return resultMessages;
};

const processEffects = (character, effects, isEquipping) => {
  let messages = [];

  effects.forEach((effect) => {
    if (!isEquipping) {
      // Снимаем эффекты
      switch (effect.type) {
        case 'damage_boost':
          character.force = Math.max(0, character.force - effect.amount);
          character.save()
          messages.push(`Ваш урон уменьшен на ${effect.amount}.`);
          break;

        case 'max_health_boost':
          character.max_hp = Math.max(1, character.max_hp - effect.amount);
          character.save()
          messages.push(`Ваше максимальное здоровье уменьшено на ${effect.amount}.`);
          break;

        case 'stamina_penalty':
          character.max_stamina += effect.amount;
          character.save()
          messages.push(`Ваша выносливость увеличена на ${effect.amount}.`);
          break;

        case 'intelligence_boost':
          character.intelligence -= Math.max(0, character.intelligence - effect.amount);
          character.save()
          messages.push(`Ваш интеллект уменьшена на ${effect.amount}.`);
          break;

        default:
          messages.push('Неизвестный эффект при снятии.');
      }
    } else {
      // Применяем эффекты
      switch (effect.type) {
        case 'heal':
          character.hp = Math.min(character.max_hp, character.hp + effect.amount);
          character.save()
          messages.push(`Вы восстановили ${effect.amount} HP.`);
          break;

        case 'damage_boost':
          character.force += effect.amount;
          character.save()
          messages.push(`Ваша сила увеличена на ${effect.amount}.`);
          break;

        case 'max_health_boost':
          character.max_hp += effect.amount;
          character.save()
          messages.push(`Ваше максимальное здоровье увеличено на ${effect.amount}.`);
          break;

        case 'stamina_penalty':
          character.max_stamina -= effect.amount;
          character.save()
          messages.push(`Ваша выносливость уменьшена на ${effect.amount}.`);
          break;

        case 'stamina_recover':
          character.stamina = Math.min(character.max_stamina, character.stamina + effect.amount);
          character.save()
          messages.push(`Вы восстановили ${effect.amount} стамины.`);
          break;

        case 'intelligence_boost':
          character.intelligence += effect.amount;
          character.save()
          messages.push(`Ваш интеллект увеличен на ${effect.amount}.`);
          break;

        default:
          messages.push('Неизвестный эффект при снаряжении.');
      }
    }
  });

  return messages.join('\n');
};

function generateKeyboard() {
  const buttonsCount = 10;
  const buttons = [];
  const winButton = utils.rand(1, 10);

  for (let i = 1; i <= buttonsCount; i++) {
    if (i === winButton) {
      buttons.push({ text: `🔒`, callback_data: `SHOP_CASH_BREAK_SUCCESS` });
    } else {
      buttons.push({ text: `🔒`, callback_data: `lock_${i}` });
    }
  }

  const rows = [];
  while (buttons.length > 0) {
    rows.push(buttons.splice(0, 5)); // Разбиваем на подмассивы по 5 кнопок
  }
  console.log(rows)
  return {
    reply_markup: {
      inline_keyboard: rows,
    },
  };
}

function removeButton(ctx, buttonId) {
  const keyboard = ctx.update.callback_query.message.reply_markup.inline_keyboard;

  for (let row of keyboard) {
    for (let i = 0; i < row.length; i++) {
      if (row[i].callback_data === buttonId) {
        row[i].text = `🔓`;
        break;
      }
    }
  }

  ctx.editMessageText('Взлом замка:', Markup.inlineKeyboard(keyboard).resize());
}

// Восстановление здоровья (HP)
async function recoverHealth() {
  const characters = await CharacterModel.findAll({
    where: {
      hp: {
        [Op.lt]: 100, // Восстанавливаем только тем, у кого HP меньше 100
      },
    },
  });

  for (const character of characters) {
    const recoveryRate = character.resilience; // Восстановление 10 HP за интервал
    character.hp = Math.min(character.hp + recoveryRate, 100); // Не превышаем максимум
    await character.save();
  }
}

// Восстановление выносливости (стамины)
async function recoverStamina() {
  const characters = await CharacterModel.findAll({
    where: {
      stamina: {
        [Op.lt]: 100, // Восстанавливаем только тем, у кого стамина меньше 100
      },
    },
  });

  for (const character of characters) {
    const recoveryRate = character.endurance; // Восстановление 5 стамины за интервал
    character.stamina = Math.min(character.stamina + recoveryRate, 100); // Не превышаем максимум
    await character.save();
  }
}

const reduceStealedCards = async () => {
  try {
    const characters = await CharacterModel.findAll();

    for (const character of characters) {
      const stolenCards = await StolenCardsModel.findAll({
        where: { userId: character.telegram_id }
      });

      if (stolenCards.length > 0) {
        // Для каждой карточки уменьшаем баланс на половину
        for (const card of stolenCards) {
          card.balance = Math.ceil(card.balance / 2); // Баланс делим на 2 и округляем вверх
          await card.save(); // Сохраняем изменения карточки
        }

        // Удаляем половину карточек
        const cardsToDelete = Math.ceil(stolenCards.length / 2);
        const cardsToRemove = stolenCards.slice(0, cardsToDelete);

        for (const card of cardsToRemove) {
          await card.destroy(); // Удаляем карточки
        }

        console.log(`Карточки для персонажа ${character.name} успешно обновлены.`);
      }
    }

    console.log('Карточки всех игроков успешно обновлены.');
  } catch (error) {
    console.error('Ошибка при обновлении карточек:', error);
  }
};


async function generateCard(userId, balance) {
  if (!Number(balance)) {
    balance = faker.finance.amount({ dec: 0 }) * 100
    console.log('Random balance: ' + balance)
  } else {
    balance = Math.floor(balance);
    console.log('Set balance: ' + balance)
  }
  const cardNumber = `${faker.finance.creditCardNumber()}`; // Генерация номера карты
  const pin = `${faker.finance.pin()}`; // Четырехзначный ПИН
  const cvv = `${faker.finance.creditCardCVV()}`; // Трехзначный CVV
  const holderName = `${faker.person.firstName()} ${faker.person.lastName()}`; // Имя и фамилия
  const bankName = faker.company.name(); // Название банка
  const expiresDate = `${Math.floor(Math.random() * 12) + 1}/${2025 + Math.floor(Math.random() * 5)}`; // Срок действия

  await StolenCardsModel.create({
    userId,
    balance,
    cardNumber,
    pin,
    cvv,
    holderName,
    bankName,
    expiresDate,
  });
}

async function Exp(ctx, character, experience) {
  character.exp += experience
  await ctx.sendMessage(`❇️ +${experience} exp.`)
  await character.save()
  for (i in expToUp) {
    if (character.exp >= expToUp[character.level]) {
      character.exp -= expToUp[character.level]
      character.level += 1
      character.firePoints += 1
      await character.save()
      await ctx.sendMessage(`⤴️ Уровень вашего персонажа повысился до ${character.level}!`)
    }
  }
}

// Периодическое выполнение задач
function startRecoveryIntervals() {
  const interval = 60000; // 1 мин Интервал в миллисекундах (например, 1 минута)
  setInterval(recoverHealth, interval);
  setInterval(recoverStamina, interval);
}

// Планируем выполнение задачи каждый день в 12 ночи
schedule.scheduleJob('0 0 * * *', reduceStealedCards);

rpg.command('force_reduce', async (ctx) => {
  reduceStealedCards()
  return await ctx.reply(`Принудительно`)
})

rpg.command('steal_card', async (ctx) => {
  await generateCard(ctx.from.id)
  ctx.reply('💳 Вы украли новую карточку! Проверьте её в вашем инвентаре.');
});


startRecoveryIntervals()




const fillEnemies = async () => {
  const enemies = [
    { name: "Бандит", description: "Обычный бандит с ножом", level: 1, hp: 50, damage: 10, loot: [1, 2], rarity: 1 },
    { name: "Вор", description: "Мелкий воришка", level: 1, hp: 30, damage: 5, loot: [3], rarity: 1 },
    { name: "Собака", description: "Голодная дворняга", level: 1, hp: 40, damage: 8, loot: [], rarity: 2 },
    { name: "Амбал-бандит", description: "Сильный и опасный бандит", level: 3, hp: 120, damage: 25, loot: [4, 5], rarity: 3 },
  ];

  for (const enemy of enemies) {
    await Enemy.create(enemy);
  }
  console.log("Enemies filled.");
};

const fillLocations = async () => {
  const locations = [
    {
      name: "Заброшенный склад",
      description: "Темный склад с кучей мусора.",
      enemies: [1, 2, 3],
      level: 1,
      loot: [6, 7],
      rarity: 1
    },
    {
      name: "Лесопосадка",
      description: "Густой лес с опасными тропами.",
      enemies: [2, 3, 4],
      level: 2,
      loot: [8, 9],
      rarity: 2
    },
  ];

  for (const location of locations) {
    await Location.create(location);
  }
  console.log("Locations filled.");
};

const generateBattles = async () => {
  const locations = await Location.findAll();

  for (const location of locations) {
    // Проверяем количество битв для текущей локации
    const existingBattlesCount = await Battle.count({ where: { location: location.id, status: 'inactive' } });

    if (existingBattlesCount >= 10) {
      console.log(`Пропущена локация ${location.id}, уже есть 10 битв.`);
      continue; // Пропускаем локацию, если уже есть 10 битв
    }

    const enemies = location.enemies;
    const generatedEnemies = enemies.map((enemyId) => {
      const rarity = Math.random();
      return rarity < 0.7 ? enemyId : null; // Шанс 70% для обычных врагов
    }).filter(Boolean);

    for (const enemyId of generatedEnemies) {
      const enemy = await Enemy.findByPk(enemyId);
      if (!enemy) continue;

      // Проверяем, нужно ли создавать битвы (не превышать лимит в 10)
      const currentBattlesCount = await Battle.count({ where: { location: location.id, status: 'inactive' } });
      if (currentBattlesCount >= 5) {
        console.log(`Достигнут лимит битв для локации ${location.id}.`);
        break;
      }

      await Battle.create({
        enemy: enemy.id,
        location: location.id,
        character: null,
        enemy_hp: enemy.hp,
        status: "inactive",
        logs: [],
      });
    }
  }
  console.log("Battles generated.");
};


generateBattles()
schedule.scheduleJob('0 * * * *', generateBattles); // Каждый час в начале часа
rpg.command("locations", async (ctx) => {
  const locations = await Location.findAll();
  if (!locations.length) {
    return ctx.reply("Нет доступных локаций для исследования.");
  }

  const locationButtons = locations.map((location) => ({
    text: location.name,
    callback_data: `viewlocation_${location.id}`,
  }));

  const keyboard = Markup.inlineKeyboard(
    locationButtons.map((button) => [button]) // Одна кнопка на строку
  );

  await ctx.reply("Выберите локацию для исследования:", keyboard);
});

rpg.action(/viewlocation_\d+/, async (ctx) => {
  const locationId = ctx.match[0].split("_")[1];
  const location = await Location.findByPk(locationId);

  if (!location) {
    return ctx.reply("Локация не найдена.");
  }

  const lootItems = location.loot.length
    ? location.loot.map((id) => `#${id}`).join(", ")
    : "Нет";

  const description = `🏞️ ${location.name}\n\n${location.description}\n\nУровень: ${location.level}\nДобыча: ${lootItems}\n`;
  const keyboard = Markup.inlineKeyboard([
    [{ text: "Исследовать", callback_data: `explore_${location.id}` }],
    [{ text: "Охота", callback_data: `hunt_location_${location.id}` }],
  ]);

  await ctx.reply(description, keyboard);
});

rpg.action(/hunt_location_\d+/, async (ctx) => {
  const locationId = ctx.match[0].split('_')[2]; // Получаем ID локации
  const location = await Location.findByPk(locationId);

  if (!location) {
    return ctx.reply("Локация не найдена.");
  }

  const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
  if (!character) {
    return ctx.reply("Ваш персонаж не найден.");
  }

  const inventory = await InventoryModel.findAll({ where: { telegram_id: ctx.from.id } });
  const hasGrenadeLow = inventory.some((item) => item.text_id === "grenade_low");
  const hasGrenadeMedium = inventory.some((item) => item.text_id === "grenade_medium");
  const hasGrenadeHard = inventory.some((item) => item.text_id === "grenade_hard");

  const enemyIds = location.enemies || [];
  if (enemyIds.length === 0) {
    return ctx.reply("В этой локации сейчас нет врагов. Попробуйте позже.");
  }

  const activeBattles = await Battle.findAll({
    where: { location: location.id, status: "inactive" },
  });

  if (activeBattles.length === 0) {
    return ctx.reply("В этой локации сейчас нет активных врагов. Попробуйте позже.");
  }

  const activeEnemyIds = activeBattles.map((battle) => battle.enemy);
  const enemies = await Enemy.findAll({ where: { id: activeEnemyIds } });

  if (enemies.length === 0) {
    return ctx.reply("В этой локации сейчас нет врагов.");
  }

  const buttons = activeBattles.map((battle) => {
    const enemy = enemies.find((e) => e.id === battle.enemy);
    return {
      text: `${enemy.name} (HP: ${battle.enemy_hp})`,
      callback_data: `start_battle_${battle.id}`,
    };
  });

  if (hasGrenadeLow || hasGrenadeMedium || hasGrenadeHard) {
    buttons.push({
      text: "💣 Использовать гранату",
      callback_data: `use_grenade_${locationId}`,
    });
  }

  const keyboard = Markup.inlineKeyboard(buttons.map((btn) => [btn]));

  await ctx.reply(
    `🔍 Локация: ${location.name}\n\nВыберите врага для охоты:`,
    keyboard
  );
});

// Использование гранаты
rpg.action(/use_grenade_\d+/, async (ctx) => {
  const locationId = ctx.match[0].split('_')[2];
  const location = await Location.findByPk(locationId);

  if (!location) {
    return ctx.reply("Локация не найдена.");
  }

  const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
  if (!character) {
    return ctx.reply("Ваш персонаж не найден.");
  }

  const inventory = await InventoryModel.findAll({ where: { telegram_id: ctx.from.id } });
  const grenade =
    inventory.find((item) => item.text_id === "grenade_hard") ||
    inventory.find((item) => item.text_id === "grenade_medium") ||
    inventory.find((item) => item.text_id === "grenade_low");

  if (!grenade) {
    return ctx.reply("У вас нет гранаты для использования.");
  }

  const activeBattles = await Battle.findAll({
    where: { location: location.id, status: "inactive" },
  });

  if (activeBattles.length === 0) {
    return ctx.reply("В этой локации нет активных врагов.");
  }

  // Урон гранаты
  const damage =
    grenade.text_id === "grenade_hard"
      ? 50
      : grenade.text_id === "grenade_medium"
      ? 30
      : 10;

  let message = `💥 Вы использовали гранату (${grenade.text_id}) и нанесли ${damage} урона всем врагам!`;

  for (const battle of activeBattles) {
    battle.enemy_hp -= damage;
    battle.logs.push(`💣 Враг получил ${damage} урона от гранаты.`);

    if (battle.enemy_hp <= 0) {
      battle.status = "completed";
      battle.logs.push("💀 Враг был убит гранатой.");
    }

    await battle.save({ fields: ["enemy_hp", "logs", "status"] });
  }

  // Удаляем гранату из инвентаря
  await InventoryModel.destroy({ where: { id: grenade.id } });

  await ctx.reply(message);
});


rpg.action(/start_battle_\d+/, async (ctx) => {
  const battleId = ctx.match[0].split('_')[2]; // Получаем ID битвы
  const battle = await Battle.findByPk(battleId);
  const enemy = await Enemy.findByPk(battle.enemy);

  if (!battle || battle.status !== 'inactive') {
    return ctx.reply("Этот враг уже сражается с другим игроком или сражение завершено.");
  }

  const existingBattle = await Battle.findOne({
    where: { character: ctx.from.id, status: 'active' },
  });

  if (existingBattle) {
    return ctx.reply("Вы уже участвуете в другом сражении!");
  }

  const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
  if (!character) {
    return ctx.reply("Ваш персонаж не найден. Создайте его, чтобы начать играть!");
  }

  battle.status = 'active';
  battle.character = ctx.from.id;
  await battle.save();

  await startBattle(ctx, character, enemy, battle);
});

const startBattle = async (ctx, character, enemy, battle) => {
  await ctx.reply(
    `⚔️ Начинается сражение!\n\nВаш противник: ${enemy.name}\n🛡️ Уровень: ${enemy.level}\n❤️ Здоровье: ${enemy.hp}\n\nВы готовы?`,
    Markup.inlineKeyboard([[{ text: "Атаковать", callback_data: `attack_${battle.id}` }]])
  );
};

const enemyTurn = async (ctx, character, battle) => {
  const enemy = await Enemy.findByPk(battle.enemy);

  const dodgeChance = Math.min(character.resistance * 0.05, 0.5);
  const isDodged = Math.random() < dodgeChance;

  if (isDodged) {
    battle.logs.push(`💨 ${character.name} уклонились от атаки противника!`);
    return await battle.save({ fields: ["logs"] });
  }

  const damage = enemy.damage;
  character.hp -= damage;

  if (character.hp <= 0) {
    battle.status = "inactive";
    battle.logs.push(
      `💔 Противник нанес ${character.name} ${damage} урона!\n\n${character.name} потерпел поражение от ${enemy.name}.`
    );
    return await battle.save({ fields: ["logs", "status"] });
  }

  await character.save();
  await battle.logs.push(`💔 Противник нанес ${character.name} ${damage} урона. У ${character.name} осталось ${character.hp} HP.`);
  await battle.save({ fields: ["logs"] });
};

rpg.action(/attack_\d+/, async (ctx) => {
  const battleId = ctx.match[0].split("_")[1];
  const battle = await Battle.findByPk(battleId);

  if (!battle || battle.status !== "active") {
    return ctx.reply("Сражение завершено или не существует.");
  }

  const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
  if (!character || battle.character != ctx.from.id) {
    return ctx.reply("Это не ваша битва.");
  }

  const enemy = await Enemy.findByPk(battle.enemy);
  if (!enemy) {
    return ctx.reply("Противник не найден.");
  }

  // Генерация кнопок
  const buttons = generateBattleButtons(character, battle);
  const keyboard = Markup.inlineKeyboard(buttons);
  // Логи битвы
  const logs = battle.logs || [];
  const logMessage = logs.slice(-5).map((log) => `• ${log}`).join("\n");

  // Сообщение с информацией
  await ctx.editMessageText(
    `⚔️ Сражение с ${enemy.name}\n\n` +
    `❤️ Здоровье врага: ${battle.enemy_hp}/${enemy.hp}\n` +
    `⚔️ Урон врага: ${enemy.damage}\n\n` +
    `📜 Логи битвы:\n${logMessage || "Пока ничего не произошло."}\n\n` +
    `🎯 Выберите цель для атаки:`,
    keyboard
  );
});

// Обработка попадания
rpg.action(/hit_\d+/, async (ctx) => {
  const battleId = ctx.match[0].split("_")[1];
  const battle = await Battle.findByPk(battleId);

  if (!battle || battle.status !== "active") {
    return ctx.reply("Сражение завершено или не существует.");
  }

  const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
  if (!character || battle.character != ctx.from.id) {
    return ctx.reply("Это не ваша битва.");
  }

  const enemy = await Enemy.findByPk(battle.enemy);
  if (!enemy) {
    return ctx.reply("Противник не найден.");
  }

  // Урон
  const damage = Math.floor(Math.random() * (character.force || 10)) + 1;
  battle.enemy_hp -= damage;

  // Логи
  battle.logs = battle.logs || [];
  battle.logs.push(`${character.name} нанес ${damage} урона врагу.`);
  await battle.save({ fields: ["enemy_hp", "logs"] });

  // Проверка на победу
  if (battle.enemy_hp <= 0) {
    battle.status = "completed";
    await battle.save();
    return ctx.editMessageText(`🎉 ${character.name} победил ${enemy.name}!`);
  }

  await battle.save();

  // Обновление сообщения с новыми кнопками
  const buttons = generateBattleButtons(character, battle); // Генерация новых кнопок
  const keyboard = Markup.inlineKeyboard(buttons);

  const logs = battle.logs.slice(-5).map((log) => `• ${log}`).join("\n");

  await ctx.editMessageText(
    `⚔️ Сражение с ${enemy.name}\n\n` +
    `❤️ Здоровье врага: ${battle.enemy_hp}/${enemy.hp}\n` +
    `⚔️ Урон врага: ${enemy.damage}\n\n` +
    `📜 Логи битвы:\n${logs || "Пока ничего не произошло."}\n\n` +
    `🎯 Выберите цель для атаки:`,
    keyboard
  );
});

function generateBattleButtons(character, battle) {
  const totalButtons = 10;
  const intelligenceFactor = Math.min(character.intelligence || 1, totalButtons - 2); // Уменьшаем на 2 для кнопки критического удара и гарантированного промаха
  const buttons = [];

  // Генерация кнопок с уроном от атаки
  for (let i = 0; i < intelligenceFactor; i++) {
    buttons.push({
      text: `🎯`,
      callback_data: `hit_${battle.id}`,
    });
  }

  // Генерация кнопки с критическим уроном
  buttons.push({
    text: `💥`,
    callback_data: `critical_${battle.id}`,
  });

  // Гарантированная кнопка промаха
  buttons.push({
    text: "❌",
    callback_data: `miss_${battle.id}`,
  });

  // Заполнение оставшихся кнопок (если не хватает до totalButtons)
  while (buttons.length < totalButtons) {
    buttons.push({
      text: "❌",
      callback_data: `miss_${battle.id}`,
    });
  }

  // Перетасовывание кнопок
  const shuffledButtons = buttons.sort(() => Math.random() - 0.5);

  // Разбиение кнопок на 2 строки (по 5 кнопок в каждой строке)
  const rows = [];
  for (let i = 0; i < shuffledButtons.length; i += 5) {
    rows.push(shuffledButtons.slice(i, i + 5));
  }

  return rows;
}



// Обработка критического удара
rpg.action(/critical_\d+/, async (ctx) => {
  const battleId = ctx.match[0].split("_")[1];
  const battle = await Battle.findByPk(battleId);

  if (!battle || battle.status !== "active") {
    return ctx.reply("Сражение завершено или не существует.");
  }

  const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
  if (!character || battle.character != ctx.from.id) {
    return ctx.reply("Это не ваша битва.");
  }

  const enemy = await Enemy.findByPk(battle.enemy);
  if (!enemy) {
    return ctx.reply("Противник не найден.");
  }

  // Критический урон
  const damage = Math.floor((character.force || 10) * 2);
  battle.enemy_hp -= damage;

  // Логи
  battle.logs = battle.logs || [];
  battle.logs.push(`Критический удар! ${character.name} нанес ${damage} урона врагу.`);

  // Проверка на победу
  if (battle.enemy_hp <= 0) {
    battle.status = "completed";
    await battle.save();
    return ctx.editMessageText(
      `🎉 ${character.name} победил ${enemy.name}!\n\n📜 Логи битвы:\n${battle.logs.slice(-5).map((log) => `• ${log}`).join("\n")}`
    );
  }

  await battle.save({ fields: ["enemy_hp", "logs"] });

  // Генерация новых кнопок
  const buttons = generateBattleButtons(character, battle);
  const keyboard = Markup.inlineKeyboard(buttons);

  const logs = battle.logs.slice(-5).map((log) => `• ${log}`).join("\n");

  await ctx.editMessageText(
    `⚔️ Сражение с ${enemy.name}\n\n` +
    `❤️ Здоровье врага: ${battle.enemy_hp}/${enemy.hp}\n` +
    `⚔️ Урон врага: ${enemy.damage}\n\n` +
    `📜 Логи битвы:\n${logs || "Пока ничего не произошло."}\n\n` +
    `🎯 Выберите цель для атаки:`,
    keyboard
  );
});


// Обработка промаха
rpg.action(/miss_\d+/, async (ctx) => {
  const battleId = ctx.match[0].split("_")[1];
  const battle = await Battle.findByPk(battleId);

  if (!battle || battle.status !== "active") {
    return ctx.reply("Сражение завершено или не существует.");
  }

  const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
  if (!character || battle.character != ctx.from.id) {
    return ctx.reply("Это не ваша битва.");
  }

  const enemy = await Enemy.findByPk(battle.enemy);
  if (!enemy) {
    return ctx.reply("Противник не найден.");
  }

  // Логи
  battle.logs = battle.logs || [];
  battle.logs.push(`${character.name} промахнулся.`);
  await enemyTurn(ctx, character, battle);
  await battle.save({ fields: ["enemy_hp", "logs"] });

  // Генерация новых кнопок
  const buttons = generateBattleButtons(character, battle);
  const keyboard = Markup.inlineKeyboard(buttons);

  const logs = battle.logs.slice(-5).map((log) => `• ${log}`).join("\n");
  if (character.hp <= 0) {
    return ctx.editMessageText(
      `💔 ${character.name} потерпел поражение от ${enemy.name}!\n\n📜 Логи битвы:\n${logs}`
    );
  }
  await ctx.editMessageText(
    `⚔️ Сражение с ${enemy.name}\n\n` +
    `❤️ Здоровье врага: ${battle.enemy_hp}/${enemy.hp}\n` +
    `⚔️ Урон врага: ${enemy.damage}\n\n` +
    `📜 Логи битвы:\n${logs || "Пока ничего не произошло."}\n\n` +
    `🎯 Выберите цель для атаки:`,
    keyboard
  );
});




const fillItemsTable = async () => {
  try {
    const items = [];

    // Генерируем 10 случайных предметов
    for (let i = 0; i < 10; i++) {
      const item = {
        name: fakerRU.commerce.productName(), // Название товара
        description: fakerRU.lorem.sentence(), // Описание товара
        price: fakerRU.commerce.price({ dec: 0 }), // Цена товара
        rarity: 1, // Редкость (от 1 до 5)
        type: 'other', // Тип предмета
      };

      items.push(item);
    }

    // Вставляем все 10 предметов в таблицу
    await ItemsModel.bulkCreate(items);
    console.log('Таблица предметов успешно заполнена!');
  } catch (error) {
    console.error('Ошибка при заполнении таблицы предметов:', error);
  }
};

// Запускаем функцию
//fillItemsTable();









module.exports = rpg;
