import logging
import random
import json
import os
import telegram
from telegram import Update, ReplyKeyboardMarkup, ParseMode
from telegram.ext import Updater, CommandHandler, CallbackContext, MessageHandler, Filters

# Defina o token do seu bot aqui
TOKEN = '6332248399:AAHmP8FjIPYx1gCpeIJmSsdAgor11H2k0cw'

# Configuração do logger (opcional, mas útil para depuração)
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)

# Dicionário para armazenar os números aleatórios e o estado do jogo para cada chat_id
game_data = {}

# Lista de dicionários para armazenar os melhores jogadores (cada jogador com 'user_id' e 'attempts')
top_players = []

# Caminho completo do arquivo para salvar os dados dos melhores jogadores
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
TOP_PLAYERS_FILE = os.path.join(BASE_DIR, 'top_players.json')

# Função para exibir o menu principal
def main_menu(update: Update, context: CallbackContext):
    chat_id = update.effective_chat.id
    keyboard = ReplyKeyboardMarkup([["Jogar", "Melhores Jogadores"]], one_time_keyboard=True)
    context.bot.send_message(chat_id=chat_id, text="Escolha uma opção:", reply_markup=keyboard)

# Função para iniciar o jogo
def start_game(update: Update, context: CallbackContext):
    chat_id = update.effective_chat.id
    # Gerar um número aleatório entre 0 e 500
    random_number = random.randint(0, 500)
    game_data[chat_id] = {
        'random_number': random_number,
        'playing': True,
        'attempts': 0
    }
    context.bot.send_message(chat_id=chat_id, text="Vou pensar em um número entre 0 e 500. Tente adivinhar!")

# Função para atualizar a lista de melhores jogadores
def update_top_players(user_id, attempts):
    # Verifica se o jogador já está na lista
    for player in top_players:
        if player['user_id'] == user_id:
            # Atualiza apenas se a nova tentativa for menor
            player['attempts'] = min(player['attempts'], attempts)
            return
    # Se não estiver na lista, adiciona o novo jogador
    top_players.append({'user_id': user_id, 'attempts': attempts})

# Função para lidar com as tentativas do usuário
def guess_number(update: Update, context: CallbackContext):
    chat_id = update.effective_chat.id
    user_guess = int(update.message.text)
    game_info = game_data.get(chat_id)

    if game_info is None or not game_info['playing']:
        context.bot.send_message(chat_id=chat_id, text="Por favor, inicie o jogo usando 'Jogar'.")
        return

    random_number = game_info['random_number']
    attempts = game_info['attempts']

    if user_guess == random_number:
        attempts += 1
        context.bot.send_message(chat_id=chat_id, text="Parabéns! Você acertou o número em {} tentativas!".format(attempts))

        # Atualiza a pontuação do jogador na lista top_players apenas se for a menor quantidade de tentativas
        update_top_players(update.effective_user.id, attempts)

        # Criar teclado personalizado com as opções "Jogar" e "Melhores Jogadores"
        keyboard = ReplyKeyboardMarkup([["Jogar", "Melhores Jogadores"]], one_time_keyboard=True)
        context.bot.send_message(chat_id=chat_id, text="Deseja jogar novamente?", reply_markup=keyboard)

        # Define o estado do jogo como False para aguardar a resposta do usuário
        game_data[chat_id]['playing'] = False
        game_data[chat_id]['attempts'] = attempts

        # Chama a função para salvar os melhores jogadores no arquivo
        save_top_players()

    elif user_guess < random_number:
        context.bot.send_message(chat_id=chat_id, text="Tente um número maior.")
        game_data[chat_id]['attempts'] += 1
    else:
        context.bot.send_message(chat_id=chat_id, text="Tente um número menor.")
        game_data[chat_id]['attempts'] += 1

# Função para exibir os melhores jogadores (top 10)
def show_top_players(update: Update, context: CallbackContext):
    chat_id = update.effective_chat.id

    if not top_players:
        context.bot.send_message(chat_id=chat_id, text="Ainda não há jogadores na lista de melhores.")
    else:
        top_players_text = "🏆 Top 10 dos Melhores Jogadores: 🏆\n\n"

        # Ordena a lista de jogadores com base no número de tentativas (ou infinito, caso não haja tentativas registradas)
        sorted_top_players = sorted(top_players, key=lambda x: x.get('attempts', float('inf')))[:10]

        for idx, player in enumerate(sorted_top_players, 1):
            try:
                player_name = context.bot.get_chat(player['user_id']).username
            except telegram.error.BadRequest:
                player_name = "Anônimo"
            player_attempts = player.get('attempts', 'Sem tentativas registradas')
            top_players_text += f"{idx}. @{player_name}: {player_attempts} tentativas\n"

        context.bot.send_message(chat_id=chat_id, text=top_players_text, parse_mode=ParseMode.MARKDOWN)

# Função para salvar os melhores jogadores em um arquivo
def save_top_players():
    with open(TOP_PLAYERS_FILE, 'w') as f:
        json.dump(top_players, f)

# Função para carregar os melhores jogadores do arquivo
def load_top_players():
    global top_players
    try:
        with open(TOP_PLAYERS_FILE, 'r') as f:
            top_players = json.load(f)
    except FileNotFoundError:
        top_players = []

# Função para lidar com a resposta do usuário após o jogo
def handle_response(update: Update, context: CallbackContext):
    chat_id = update.effective_chat.id
    response = update.message.text.lower()
    if response == "jogar":
        # Reiniciar o jogo se o usuário escolher "Jogar"
        start_game(update, context)
    elif response == "melhores jogadores":
        # Atualiza a lista dos melhores jogadores e exibe
        load_top_players()
        show_top_players(update, context)
    else:
        context.bot.send_message(chat_id=chat_id, text="Por favor, escolha uma opção válida.")

# Função principal para executar o bot
def main():
    load_top_players()  # Carregar os melhores jogadores do arquivo (se existir)

    updater = Updater(TOKEN, use_context=True)

    dp = updater.dispatcher

    # Handlers
    dp.add_handler(CommandHandler("start", main_menu))
    dp.add_handler(CommandHandler("jogar", start_game))
    dp.add_handler(CommandHandler("melhoresjogadores", show_top_players))
    dp.add_handler(MessageHandler(Filters.text & ~Filters.command & ~Filters.regex(r'^Jogar|Melhores Jogadores$'), guess_number))
    dp.add_handler(MessageHandler(Filters.text & ~Filters.command & Filters.regex(r'^Jogar|Melhores Jogadores$'), handle_response))

    updater.start_polling()

    try:
        updater.idle()
    finally:
        # Salvar os melhores jogadores antes de encerrar o bot
        save_top_players()

if __name__ == '__main__':
    main()