import logging
import random
import json
from telegram import Update, ReplyKeyboardMarkup, ReplyKeyboardRemove
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, ConversationHandler, CallbackContext

TOKEN = '6468624010:AAFIhnhZV10MgYKfJmCIzFWSgGu23jYpuec'

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)

categorias_arquivos = {
    'frutas': 'fruta.json',
    'objetos': 'objeto.json',
    'cores': 'cor.json',
    'animais': 'animal.json',
    'países': 'pais.json',
    'profissões': 'profissao.json',
    'alimentos': 'alimento.json',
    'esportes': 'esporte.json',
    'filmes': 'filme.json',
    'carros': 'carro.json'
}

START, CHOOSE_CATEGORY, PLAYING, PLAY_AGAIN = range(4)

END = ConversationHandler.END

def read_words_from_json(file_name):
    with open(file_name, 'r') as file:
        return json.load(file)

def remove_accents(input_str):
    accents_map = {
        'á': 'a', 'à': 'a', 'ã': 'a', 'â': 'a',
        'é': 'e', 'è': 'e', 'ê': 'e',
        'í': 'i', 'ì': 'i', 'î': 'i',
        'ó': 'o', 'ò': 'o', 'õ': 'o', 'ô': 'o',
        'ú': 'u', 'ù': 'u', 'û': 'u',
        'ç': 'c', 'Á': 'A', 'É': 'E', 'Í': 'I',
        'Ó': 'O', 'Ú': 'U', 'Ñ': 'N',
        'ñ': 'n',
    }
    return ''.join(accents_map.get(char, char) for char in input_str)

def start(update: Update, context: CallbackContext):
    user = update.message.from_user
    categories_keyboard = [[category.capitalize()] for category in categorias_arquivos.keys()]
    reply_markup = ReplyKeyboardMarkup(categories_keyboard, one_time_keyboard=True)
    update.message.reply_text(
        f"Olá, {user.first_name}! Vamos jogar o jogo da Forca. Escolha uma categoria:",
        reply_markup=reply_markup,
    )
    return CHOOSE_CATEGORY

def choose_category(update: Update, context: CallbackContext):
    user_category = update.message.text.lower()
    if user_category in categorias_arquivos:
        context.user_data['categoria'] = user_category
        return play(update, context)
    else:
        update.message.reply_text("Categoria inválida. Por favor, escolha uma das categorias disponíveis.")
        return CHOOSE_CATEGORY

def choose_word(categoria):
    file_name = categorias_arquivos[categoria]
    words = [remove_accents(word) for word in read_words_from_json(file_name)]
    return random.choice(words).upper()

def play(update: Update, context: CallbackContext):
    categoria = context.user_data['categoria']
    word = choose_word(categoria)
    attempts = 8
    guessed_letters = set()
    blanks = ['_' if letter.isalpha() else letter for letter in word]

    context.user_data['word'] = word
    context.user_data['attempts'] = attempts
    context.user_data['guessed_letters'] = guessed_letters
    context.user_data['blanks'] = blanks

    update.message.reply_text(f"Dica: A palavra tem {len(word)} letras: {' '.join(blanks)}")
    return PLAYING

def check_letter(update: Update, context: CallbackContext):
    user_input = update.message.text.strip().upper()

    if len(user_input) == 1:
        letter = user_input
        return check_single_letter(update, context, letter)
    else:
        return check_word(update, context, user_input)

def check_single_letter(update: Update, context: CallbackContext, letter: str):
    letter = remove_accents(letter).upper()

    word = context.user_data['word']
    attempts = context.user_data['attempts']
    guessed_letters = context.user_data['guessed_letters']

    if letter in guessed_letters:
        update.message.reply_text(f"A letra '{letter}' já foi tentada antes.")
    elif any(letter in remove_accents(original_letter).upper() for original_letter in word):
        update.message.reply_text(f"Boa! A letra '{letter}' está na palavra.")
        guessed_letters.add(letter)
    else:
        update.message.reply_text(f"A letra '{letter}' não está na palavra.")
        guessed_letters.add(letter)
        attempts -= 1

    blanks = [original_letter if original_letter in guessed_letters or not original_letter.isalpha() else '_' for original_letter in word]

    if attempts > 0 and '_' in blanks:
        update.message.reply_text(f"Tentativas restantes: {attempts}\n{' '.join(blanks)}")
        context.user_data['attempts'] = attempts
        context.user_data['guessed_letters'] = guessed_letters
    elif '_' not in blanks:
        update.message.reply_text(f"Parabéns! Você adivinhou a palavra '{word}' corretamente.")
        return ask_play_again(update, context)
    else:
        update.message.reply_text(f"Suas tentativas acabaram. A palavra correta era '{word}'.")
        return ask_play_again(update, context)

    return PLAYING

def check_word(update: Update, context: CallbackContext, user_word: str):
    user_word = remove_accents(user_word).upper()

    word = context.user_data['word']
    attempts = context.user_data['attempts']

    if user_word == word:
        update.message.reply_text(f"Parabéns! Você adivinhou a palavra '{word}' corretamente.")
        return ask_play_again(update, context)
    else:
        update.message.reply_text("A palavra está incorreta.")
        attempts -= 1
        context.user_data['attempts'] = attempts

        blanks = [original_letter if original_letter in context.user_data['guessed_letters'] or not original_letter.isalpha() else '_' for original_letter in word]

        if attempts > 0:
            update.message.reply_text(f"Tentativas restantes: {attempts}\n{' '.join(blanks)}")
        else:
            update.message.reply_text(f"Suas tentativas acabaram. A palavra correta era '{word}'.")
            return ask_play_again(update, context)

    return PLAYING

def ask_play_again(update: Update, context: CallbackContext):
    reply_markup = ReplyKeyboardMarkup([['Sim', 'Não']], one_time_keyboard=True)
    update.message.reply_text("Deseja jogar novamente?", reply_markup=reply_markup)
    return PLAY_AGAIN

def check_play_again(update: Update, context: CallbackContext):
    user_answer = update.message.text.lower()

    if user_answer == 'sim':
        update.message.reply_text("Legal! Vamos jogar novamente!")
        return start(update, context)
    else:
        user = update.message.from_user
        categories_keyboard = [[category.capitalize()] for category in categorias_arquivos.keys()]
        reply_markup = ReplyKeyboardMarkup(categories_keyboard, one_time_keyboard=True)
        update.message.reply_text(
            f"{user.first_name}, escolha uma categoria:",
            reply_markup=reply_markup,
        )
        return CHOOSE_CATEGORY

def unknown(update: Update, context: CallbackContext):
    update.message.reply_text("Desculpe, não entendi essa mensagem.")

def main():
    updater = Updater(TOKEN, use_context=True)
    dp = updater.dispatcher

    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('start', start)],
        states={
            CHOOSE_CATEGORY: [MessageHandler(Filters.text & ~Filters.command, choose_category)],
            PLAYING: [MessageHandler(Filters.text & ~Filters.command, check_letter)],
            PLAY_AGAIN: [MessageHandler(Filters.regex(r'^(Sim|Não)$'), check_play_again)],
        },
        fallbacks=[MessageHandler(Filters.command, unknown)],
    )

    dp.add_handler(conv_handler)

    updater.start_polling()
    updater.idle()

if __name__ == '__main__':
    main()