## Prompt for Neural Network Code Generation

**Objective:**

Modify the existing Python Telegram bot code to implement a new key management system using a single `key.txt` file and enhance the admin notification system.

**Existing Code:**

[Insert the provided Python code here]

**Specific Changes:**

1. **Key Storage:**
   - Replace the current system of multiple key files (e.g., `keys_20.txt`, `keys_60.txt`) with a single file named `key.txt`.
   - This file will store only one key at a time.
   - When a user purchases a key, the bot should:
     - Read the key from `key.txt`.
     - Send the key to the user.
     - Remove the key from `key.txt`.
     - Send a message to the admin (`@samuray_tag`) indicating that the key has been issued and needs to be replenished.

2. **Admin Notification:**
   - When a user makes a purchase (both keys and virtuals), the admin (`@samuray_tag`) should receive a notification with the following information:
     - Order ID.
     - User's Telegram username.
     - Type of purchase (key or virtual).
     - Details of the purchase (e.g., key duration, virtual quantity, server).
   - Include an inline button labeled "Issue Item" with the callback data `confirm_<order_id>`.
   - When the admin clicks "Issue Item":
     - If it's a key purchase:
       - Follow the steps outlined in point 1 for key issuance and file management.
     - If it's a virtual purchase:
       - Issue the virtuals (existing logic).
       - Send a confirmation message to the user.
       - Send a confirmation message to the admin.

**Code Requirements:**

- **Complete Code:** Generate the complete modified Python code, including all necessary imports, functions, and error handling.
- **Ready to Execute:** The code should be ready to run without requiring any further modifications.
- **Self-Sufficient:** The code should not rely on any external libraries or files beyond those already present in the existing code.
- **Error Handling:** Implement robust error handling to prevent crashes and provide informative messages to the user and admin in case of issues (e.g., no key available in `key.txt`, invalid user input).
- **Structure and Documentation:** Maintain a well-structured code with clear comments explaining the purpose and functionality of different sections.
- **Optimization:** Ensure the code is efficient and avoids unnecessary resource consumption.

**Keywords and Phrases:**

- "Complete code"
- "Ready to execute"
- "Self-sufficient"
- "Error handling"
- "Well-structured"
- "Documented"
- "Optimized"
- "Single key file"
- "Admin notification"
- "Issue item button"
- "Key replenishment"

**Example Implementation Hints (Not exhaustive):**

- For key storage, you can use file operations (e.g., `open()`, `read()`, `write()`) to manage the `key.txt` file.
- Consider using a try-except block to handle potential `FileNotFoundError` if `key.txt` doesn't exist.
- When sending messages to the admin, use the `chat_id=f"@{ADMIN}"` parameter in the `bot.send_message()` function.
- For inline buttons, utilize the `types.InlineKeyboardMarkup()` and `types.InlineKeyboardButton()` classes from the `telebot` library.

**Expected Output:**

The complete and modified Python code that implements the specified changes, adhering to the code requirements and incorporating the suggested keywords and phrases. 

code for edit:
```
import logging
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
    Updater,
    CommandHandler,
    CallbackQueryHandler,
    MessageHandler,
    Filters,
    ConversationHandler,
    CallbackContext,
)
import random
import time
import os

# --- Config ---
TOKEN = 'YOUR_BOT_TOKEN'  # Replace with your bot's token
ADMIN_USERNAME = 'samuray_tag'  # Replace with the admin's username
PAYMENT_DETAILS = '4177 7777 8888 0900'  # Payment details

# --- Logging ---
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)
logger = logging.getLogger(__name__)

# --- Constants for ConversationHandler states ---
CHOOSING_CATEGORY, CHOOSING_KEY_DURATION, WAITING_FOR_PAYMENT_KEY, \
CHOOSING_SERVER, WAITING_FOR_VIRTS_AMOUNT, WAITING_FOR_PAYMENT_VIRTS = range(6)

# --- Global variables ---
KEY_DURATIONS = [20, 60, 200, 600, 2000, 6000]  # Available key durations
SERVERS = ['RED', 'GREEN', 'BLUE']  # Available servers

# --- Handlers ---
def start(update: Update, context: CallbackContext) -> int:
    """Handle the /start command and display categories."""
    keyboard = [
        [InlineKeyboardButton("Вирты", callback_data='virts')],
        [InlineKeyboardButton("Ключи", callback_data='keys')]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    update.message.reply_text(
        "Привет! 👋 Добро пожаловать в наш магазин. Выберите, что вас интересует:",
        reply_markup=reply_markup
    )
    return CHOOSING_CATEGORY

def choose_category(update: Update, context: CallbackContext) -> int:
    """Handle the selection of a category."""
    query = update.callback_query
    query.answer()
    choice = query.data

    if choice == 'keys':
        return choose_key_duration(update, context)
    elif choice == 'virts':
        return choose_server(update, context)

def choose_key_duration(update: Update, context: CallbackContext) -> int:
    """Display available key durations."""
    keyboard = []
    for duration in KEY_DURATIONS:
        keyboard.append([InlineKeyboardButton(
            f"{duration} часов", callback_data=f"key_time_{duration}"
        )])
    reply_markup = InlineKeyboardMarkup(keyboard)
    if update.callback_query:
        update.callback_query.message.reply_text(
            "Выберите время действия ключа:",
            reply_markup=reply_markup
        )
    else:
        update.message.reply_text(
            "Выберите время действия ключа:",
            reply_markup=reply_markup
        )
    return CHOOSING_KEY_DURATION

def handle_key_duration(update: Update, context: CallbackContext) -> int:
    """Process the selected key duration."""
    query = update.callback_query
    query.answer()
    data = query.data
    duration = data.split('_')[2]  # Extract duration from callback_data
    context.user_data['duration'] = duration
    keys_file = f'keys_{duration}.txt'

    if os.path.isfile(keys_file) and os.path.getsize(keys_file) > 0:
        # Keys are available
        order_number = generate_order_number()
        context.user_data['order_number'] = order_number
        context.user_data['order_type'] = 'key'
        context.user_data['cost'] = 50  # Assuming fixed cost
        message = (
            f"Вы выбрали ключ на {duration} часов. Стоимость: 50 рублей.\n"
            f"Для оплаты переведите 50 рублей на реквизиты: {PAYMENT_DETAILS}.\n"
            f"ОБЯЗАТЕЛЬНО укажите в комментарии к платежу номер вашего заказа: #{order_number}.\n"
            "Без комментария оплата не будет засчитана!"
        )
        query.message.reply_text(message)
        return WAITING_FOR_PAYMENT_KEY
    else:
        # Keys are out of stock
        query.message.reply_text(
            f"Извините, ключи на {duration} часов временно закончились."
        )
        return ConversationHandler.END

def choose_server(update: Update, context: CallbackContext) -> int:
    """Display available servers for 'Virts'."""
    keyboard = []
    for server in SERVERS:
        keyboard.append([InlineKeyboardButton(
            server, callback_data=f"server_{server}"
        )])
    reply_markup = InlineKeyboardMarkup(keyboard)
    if update.callback_query:
        update.callback_query.message.reply_text(
            "Выберите сервер:",
            reply_markup=reply_markup
        )
    else:
        update.message.reply_text(
            "Выберите сервер:",
            reply_markup=reply_markup
        )
    return CHOOSING_SERVER

def handle_server_choice(update: Update, context: CallbackContext) -> int:
    """Process the selected server."""
    query = update.callback_query
    query.answer()
    data = query.data
    server = data.split('_')[1]
    context.user_data['server'] = server
    query.message.reply_text("Введите желаемое количество виртов:")
    return WAITING_FOR_VIRTS_AMOUNT

def handle_virts_amount(update: Update, context: CallbackContext) -> int:
    """Process the entered amount of 'Virts'."""
    amount_text = update.message.text.strip()
    if amount_text.isdigit():
        amount = int(amount_text)
        context.user_data['amount'] = amount
        cost = amount * 30 / 1000000  # Assuming price formula
        cost = round(cost, 2)
        context.user_data['cost'] = cost
        order_number = generate_order_number()
        context.user_data['order_number'] = order_number
        context.user_data['order_type'] = 'virts'
        server = context.user_data.get('server')
        message = (
            f"Вы заказали {amount} виртов для сервера {server}.\n"
            f"Стоимость: {cost} рублей.\n"
            f"Для оплаты переведите {cost} рублей на реквизиты: {PAYMENT_DETAILS}.\n"
            f"ОБЯЗАТЕЛЬНО укажите в комментарии к платежу номер вашего заказа: #{order_number}.\n"
            "Без комментария оплата не будет засчитана!"
        )
        update.message.reply_text(message)
        return WAITING_FOR_PAYMENT_VIRTS
    else:
        update.message.reply_text("Некорректный ввод. Пожалуйста, введите число.")
        return WAITING_FOR_VIRTS_AMOUNT

def generate_order_number() -> str:
    """Generate a unique order number."""
    return f"{int(time.time())}{random.randint(1000, 9999)}"

def payment_confirmed(update: Update, context: CallbackContext):
    """Simulate payment confirmation and notify admin."""
    # In a real implementation, this function should check for actual payment.
    order_number = context.user_data.get('order_number')
    username = update.effective_user.username or update.effective_user.full_name
    order_type = context.user_data.get('order_type')

    # Notify admin
    keyboard = [
        [InlineKeyboardButton(
            "Выдать товар", callback_data=f"confirm_{order_number}"
        )]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    message = (
        f"#{order_number} Пользователь {username} произвел оплату. Выдать товар?"
    )

    # Send message to admin
    context.bot.send_message(
        chat_id=f"@{ADMIN_USERNAME}",
        text=message,
        reply_markup=reply_markup
    )

    update.message.reply_text("Оплата подтверждена. Пожалуйста, ожидайте выдачи товара.")
    return ConversationHandler.END

def admin_confirm_delivery(update: Update, context: CallbackContext):
    """Handle admin's confirmation to deliver the goods."""
    query = update.callback_query
    query.answer()
    data = query.data
    if not data.startswith('confirm_'):
        query.message.reply_text("Некорректный запрос.")
        return

    order_number = data.split('_')[1]
    # In a real implementation, order details should be retrieved from a database.

    # For this example, we'll use context.user_data (which is not persistent)
    # This is a placeholder and should be replaced with actual order retrieval logic
    order_type = context.user_data.get('order_type')
    username = update.effective_user.username or update.effective_user.full_name

    if order_type == 'key':
        duration = context.user_data.get('duration')
        keys_file = f'keys_{duration}.txt'

        if os.path.isfile(keys_file):
            with open(keys_file, 'r') as f:
                keys = f.readlines()

            if keys:
                key = keys[0].strip()
                # Remove the used key from the file
                with open(keys_file, 'w') as f:
                    f.writelines(keys[1:])

                # Send the key to the user
                user_id = update.effective_user.id
                context.bot.send_message(
                    chat_id=user_id,
                    text=f"Ваш ключ: {key}"
                )
                # Log the transaction
                log_message = f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {username} получил ключ на {duration} часов."
                log_transaction(log_message)
                # Notify admin
                query.message.reply_text(f"Ключ выдан пользователю {username}.")
            else:
                query.message.reply_text(f"Ключи на {duration} часов закончились.")
        else:
            query.message.reply_text(f"Файл {keys_file} не найден.")
    elif order_type == 'virts':
        amount = context.user_data.get('amount')
        server = context.user_data.get('server')
        user_id = update.effective_user.id

        # Send confirmation to the user
        context.bot.send_message(
            chat_id=user_id,
            text="Вирты выданы. Приятной игры!"
        )
        # Log the transaction
        log_message = f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {username} получил {amount} виртов на сервере {server}."
        log_transaction(log_message)
        # Notify admin
        query.message.reply_text(f"Вирты выданы пользователю {username}.")
    else:
        query.message.reply_text("Некорректный тип заказа.")

def log_transaction(message: str):
    """Log the transaction in a log file."""
    with open('transaction_log.txt', 'a') as log_file:
        log_file.write(message + '\n')

def cancel(update: Update, context: CallbackContext) -> int:
    """Cancel the current operation."""
    update.message.reply_text("Операция отменена.")
    return ConversationHandler.END

def main():
    """Start the bot and handle updates."""
    updater = Updater(TOKEN)
    dp = updater.dispatcher

    # Define the conversation handler
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('start', start)],
        states={
            CHOOSING_CATEGORY: [
                CallbackQueryHandler(choose_category)
            ],
            CHOOSING_KEY_DURATION: [
                CallbackQueryHandler(handle_key_duration, pattern='^key_time_')
            ],
            WAITING_FOR_PAYMENT_KEY: [
                MessageHandler(Filters.text & ~Filters.command, payment_confirmed)
            ],
            CHOOSING_SERVER: [
                CallbackQueryHandler(handle_server_choice, pattern='^server_')
            ],
            WAITING_FOR_VIRTS_AMOUNT: [
                MessageHandler(Filters.text & ~Filters.command, handle_virts_amount)
            ],
            WAITING_FOR_PAYMENT_VIRTS: [
                MessageHandler(Filters.text & ~Filters.command, payment_confirmed)
            ],
        },
        fallbacks=[CommandHandler('cancel', cancel)],
    )

    dp.add_handler(conv_handler)

    # Handler for admin's confirmation
    dp.add_handler(CallbackQueryHandler(admin_confirm_delivery, pattern='^confirm_'))

    # Start the bot
    updater.start_polling()

    # Run the bot until you press Ctrl-C
    updater.idle()

if __name__ == '__main__':
    main()```