import os
import logging
import logging.config
from functools import partial
from dotenv import load_dotenv
from telegram import Bot, ReplyKeyboardMarkup, ReplyKeyboardRemove
from telegram.ext import (Updater, CommandHandler, MessageHandler,
                          RegexHandler, ConversationHandler, Filters)
from redis import Redis

from tg_logging import create_logger
from quiz_tools import get_question_and_answer, format_answer, format_question


QUESTION, ATTEMPT = range(2)


def main():
    class LoggerTelegramBot(logging.Handler):
        def emit(self, record):
            log_entry = self.format(record)
            bot.send_message(chat_id=chat_id_tg_admin, text=log_entry)

    dictLogConfig = {
        'version': 1,
        'handlers': {
            'handler': {
                '()': LoggerTelegramBot,
                'formatter': 'formatter'
                }
        },
        'loggers': {
            'tg_logger': {
                'handlers': ['handler'],
                'level': 'INFO'
            }
        },
        'formatters': {
            'formatter': {
                'format': '%(asctime)s - %(levelname)s - %(message)s'
            }
        }
    }

    load_dotenv()
    chat_id_tg_admin = os.getenv('CHAT_ID_TG_ADMIN')
    bot = Bot(token=os.getenv('TOKEN_TG'))
    logging.config.dictConfig(dictLogConfig)
    logger = logging.getLogger('tg_logger')
    handler = LoggerTelegramBot()
    logger.addHandler(handler)
    rediser = Redis(
                host=os.getenv('REDIS_HOST'),
                port=os.getenv('REDIS_PORT'),
                db=0,
                password=os.getenv('REDIS_PWD'))
    updater = Updater(token_tg)
    dp = updater.dispatcher
    logger.info(dp)
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('start', start)],
        states={
            QUESTION: [
                RegexHandler('^Выход$', do_exit),
                MessageHandler(Filters.text, partial(handle_new_question, rediser))],
            ATTEMPT: [
                RegexHandler('^Выход$', do_exit),
                RegexHandler('^(Новый вопрос|Другой вопрос)$', partial(handle_new_question, rediser)),
                RegexHandler('^Показать ответ$', partial(display_answer, rediser)),
                MessageHandler(Filters.text, partial(handle_attempt, rediser))],
        },
        fallbacks=[CommandHandler('cancel', do_exit)]
    )
    dp.add_handler(conv_handler)
    updater.start_polling()
    updater.idle()


def do_reply(update, text, keyboard=None):
    if keyboard is None:
        markup = ReplyKeyboardRemove()
        return update.message.reply_text(text, reply_markup=markup)
    markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    return update.message.reply_text(text, reply_markup=markup)


def start(bot, update):
    do_reply(update, 'Привет знатоку в чате-викторине! Начинаем?', [['Да!']])
    return QUESTION


def handle_new_question(rediser, bot, update):
    new_question, new_answer = get_question_and_answer()
    chat_id = update.message.chat_id
    rediser.set(chat_id, new_answer)
    do_reply(update, format_question(new_question))
    return ATTEMPT


def display_answer(rediser, bot, update):
    chat_id = update.message.chat_id
    answer = rediser.get(chat_id).decode()
    do_reply(update, answer, [['Новый вопрос', 'Выход']])
    return QUESTION


def handle_attempt(rediser, bot, update):
    chat_id = update.message.chat_id
    attempt = update.message.text.strip().lower()
    answer = rediser.get(chat_id).decode()
    if attempt == format_answer(answer):
        text = 'Правильно! \n\n {}'.format(answer)
        reply_keyboard = [['Новый вопрос', 'Выход']]
    else:
        text = 'Неверно! Попробуйте еще раз.'
        reply_keyboard = [['Показать ответ', 'Другой вопрос', 'Выход']]
    do_reply(update, text, reply_keyboard)
    return ATTEMPT


def do_exit(bot, update):
    text = 'До скорой встречи! Желаете начать заново? Жмите /start'
    do_reply(update, text)
    return ConversationHandler.END


if __name__ == '__main__':
    main()

[((45, 4, 45, 17), 'dotenv.load_dotenv', 'load_dotenv', ({}, {}), '()', False, 'from dotenv import load_dotenv\n'), ((46, 23, 46, 52), 'os.getenv', 'os.getenv', ({(46, 33, 46, 51): '"""CHAT_ID_TG_ADMIN"""'}, {}), "('CHAT_ID_TG_ADMIN')", False, 'import os\n'), ((48, 4, 48, 44), 'logging.config.dictConfig', 'logging.config.dictConfig', ({(48, 30, 48, 43): 'dictLogConfig'}, {}), '(dictLogConfig)', False, 'import logging\n'), ((49, 13, 49, 43), 'logging.getLogger', 'logging.getLogger', ({(49, 31, 49, 42): '"""tg_logger"""'}, {}), "('tg_logger')", False, 'import logging\n'), ((57, 14, 57, 31), 'telegram.ext.Updater', 'Updater', ({(57, 22, 57, 30): 'token_tg'}, {}), '(token_tg)', False, 'from telegram.ext import Updater, CommandHandler, MessageHandler, RegexHandler, ConversationHandler, Filters\n'), ((83, 13, 83, 64), 'telegram.ReplyKeyboardMarkup', 'ReplyKeyboardMarkup', (), '', False, 'from telegram import Bot, ReplyKeyboardMarkup, ReplyKeyboardRemove\n'), ((93, 31, 93, 56), 'quiz_tools.get_question_and_answer', 'get_question_and_answer', ({}, {}), '()', False, 'from quiz_tools import get_question_and_answer, format_answer, format_question\n'), ((81, 17, 81, 38), 'telegram.ReplyKeyboardRemove', 'ReplyKeyboardRemove', ({}, {}), '()', False, 'from telegram import Bot, ReplyKeyboardMarkup, ReplyKeyboardRemove\n'), ((96, 21, 96, 50), 'quiz_tools.format_question', 'format_question', ({(96, 37, 96, 49): 'new_question'}, {}), '(new_question)', False, 'from quiz_tools import get_question_and_answer, format_answer, format_question\n'), ((111, 18, 111, 39), 'quiz_tools.format_answer', 'format_answer', ({(111, 32, 111, 38): 'answer'}, {}), '(answer)', False, 'from quiz_tools import get_question_and_answer, format_answer, format_question\n'), ((47, 20, 47, 41), 'os.getenv', 'os.getenv', ({(47, 30, 47, 40): '"""TOKEN_TG"""'}, {}), "('TOKEN_TG')", False, 'import os\n'), ((53, 21, 53, 44), 'os.getenv', 'os.getenv', ({(53, 31, 53, 43): '"""REDIS_HOST"""'}, {}), "('REDIS_HOST')", False, 'import os\n'), ((54, 21, 54, 44), 'os.getenv', 'os.getenv', ({(54, 31, 54, 43): '"""REDIS_PORT"""'}, {}), "('REDIS_PORT')", False, 'import os\n'), ((56, 25, 56, 47), 'os.getenv', 'os.getenv', ({(56, 35, 56, 46): '"""REDIS_PWD"""'}, {}), "('REDIS_PWD')", False, 'import os\n'), ((61, 22, 61, 52), 'telegram.ext.CommandHandler', 'CommandHandler', ({(61, 37, 61, 44): '"""start"""', (61, 46, 61, 51): 'start'}, {}), "('start', start)", False, 'from telegram.ext import Updater, CommandHandler, MessageHandler, RegexHandler, ConversationHandler, Filters\n'), ((72, 19, 72, 52), 'telegram.ext.CommandHandler', 'CommandHandler', ({(72, 34, 72, 42): '"""cancel"""', (72, 44, 72, 51): 'do_exit'}, {}), "('cancel', do_exit)", False, 'from telegram.ext import Updater, CommandHandler, MessageHandler, RegexHandler, ConversationHandler, Filters\n'), ((64, 16, 64, 53), 'telegram.ext.RegexHandler', 'RegexHandler', ({(64, 29, 64, 43): '"""^Выход$"""', (64, 45, 64, 52): 'do_exit'}, {}), "('^Выход$', do_exit)", False, 'from telegram.ext import Updater, CommandHandler, MessageHandler, RegexHandler, ConversationHandler, Filters\n'), ((67, 16, 67, 53), 'telegram.ext.RegexHandler', 'RegexHandler', ({(67, 29, 67, 43): '"""^Выход$"""', (67, 45, 67, 52): 'do_exit'}, {}), "('^Выход$', do_exit)", False, 'from telegram.ext import Updater, CommandHandler, MessageHandler, RegexHandler, ConversationHandler, Filters\n'), ((65, 45, 65, 82), 'functools.partial', 'partial', ({(65, 53, 65, 72): 'handle_new_question', (65, 74, 65, 81): 'rediser'}, {}), '(handle_new_question, rediser)', False, 'from functools import partial\n'), ((68, 86, 68, 123), 'functools.partial', 'partial', ({(68, 94, 68, 113): 'handle_new_question', (68, 115, 68, 122): 'rediser'}, {}), '(handle_new_question, rediser)', False, 'from functools import partial\n'), ((69, 62, 69, 94), 'functools.partial', 'partial', ({(69, 70, 69, 84): 'display_answer', (69, 86, 69, 93): 'rediser'}, {}), '(display_answer, rediser)', False, 'from functools import partial\n'), ((70, 45, 70, 77), 'functools.partial', 'partial', ({(70, 53, 70, 67): 'handle_attempt', (70, 69, 70, 76): 'rediser'}, {}), '(handle_attempt, rediser)', False, 'from functools import partial\n')]