import datetime
import os
from telegram.ext import ConversationHandler, CommandHandler, MessageHandler, filters, CallbackQueryHandler
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
ACTION_CHOICE, DATE_ENTRY, ADD_CONTENT = range(3)

from .basehandler import BaseHandler

class JournalHandler(BaseHandler):
    def __init__(self, entry_string, models):
        self.models = models
        self.entry_string = entry_string
        self.handler = ConversationHandler(
            entry_points=[CommandHandler(entry_string, self.entry_point)],
            states={
                ACTION_CHOICE: [
                    CallbackQueryHandler(self.date_choice, pattern="today|yesterday"),
                    CallbackQueryHandler(self.date_custom, pattern="custom"),
                    CallbackQueryHandler(self.option_delete, pattern="delete")
                    ],
                DATE_ENTRY: [
                    MessageHandler(filters.ALL, self.date_entry),
                    ],
                ADD_CONTENT: [
                    MessageHandler(filters.ALL, self.content_save),
                    ]
            },
            fallbacks=[],
        )

        self.current_model = None


    async def entry_point(self, update, context):
        await super().entry_point(update, context)
        if os.getenv("DOCKERIZED", "false") == "true" and os.getenv("CHAT_ID") != str(update.message.chat_id):
            await update.message.reply_text("You are not authorized to use this bot")
            return ConversationHandler.END


        options = [[
                InlineKeyboardButton("Today", callback_data="today"),
                InlineKeyboardButton("Yesterday", callback_data="yesterday"),
                InlineKeyboardButton("Custom date", callback_data="custom"),
            ],
            [
                InlineKeyboardButton("Delete", callback_data="delete")
            ]
        ]
        keyboard = InlineKeyboardMarkup(options)
        await update.message.reply_text("Please choose an option for the entry:", reply_markup=keyboard)
        return ACTION_CHOICE


    async def date_choice(self, update, context):
        query = update.callback_query
        await query.answer()
        if query.data == "today":
            date = datetime.datetime.now().date()
        elif query.data == "yesterday":
            date = datetime.datetime.now().date() - datetime.timedelta(days=1)
        else:
            raise ValueError("Invalid date choice")

        with self.models.db:
            self.current_model, new = self.models.JournalEntry.get_or_create(
                date = date
            )
        if new:
            count = self.models.JournalEntry.select().count()
            await query.edit_message_text(
                text=f"Journal entry no. {count}. What happened on {self.current_model.date_pretty}?"
            )
        else:
            await query.edit_message_text(text="An entry already exists for this date")
            return ConversationHandler.END
        
        return ADD_CONTENT


    async def date_custom(self, update, context):
        query = update.callback_query
        await query.answer()
        await query.edit_message_text(text="Please enter the date in the format DDMMYYYY")
        return DATE_ENTRY


    async def date_entry(self, update, context):
        date = update.message.text
        
        try:
            date = datetime.datetime.strptime(date, "%d%m%Y").date()
        except ValueError:
            await update.message.reply_text("Please enter the date in the format DDMMYYYY")
            return DATE_ENTRY
        
        if context.chat_data.get("delete", False): # if not set, delete was not chosen
            with self.models.db:
                self.current_model = self.models.JournalEntry.get_or_none(
                    date = date
                )
            if self.current_model:
                await self.delete_entry(update, context)
            else:
                await update.message.reply_text("No entry found for this date")
                context.chat_data["delete"] = False
            return ConversationHandler.END
        else:
            with self.models.db:
                self.current_model, new = self.models.JournalEntry.get_or_create(
                    date = date
                )
            if not new:
                await update.message.reply_text("An entry already exists for this date")
                return ConversationHandler.END
            else:
                count = self.models.JournalEntry.select().count()
                await update.message.reply_text(
                    text=f"Journal entry no. {count}. What happened on {self.current_model.date_pretty}?"
                )
                return ADD_CONTENT


    async def content_save(self, update, context):
        with self.models.db:
            self.current_model.author_id = update.message.from_user.id

            if update.message.text:
                self.current_model.text = update.message.text
            else:
                if update.message.photo:
                    file = await update.message.effective_attachment[-1].get_file()
                else:
                    file = await update.message.effective_attachment.get_file()
                
                file_bytes = await file.download_as_bytearray()
                file_path = file.file_path
                self.current_model.save_media(file_bytes, file_path)

                self.current_model.text = update.message.caption
            
            self.current_model.save()

        await update.message.reply_text(f"Saved entry ✅")
        return ConversationHandler.END


    async def option_delete(self, update, context):
        query = update.callback_query
        await query.answer()
        await query.edit_message_text(text="Please enter the date in the format DDMMYYYY")
        context.chat_data["delete"] = True
        return DATE_ENTRY


    async def delete_entry(self, update, context):
        with self.models.db:
            self.current_model.delete_instance()
        context.chat_data["delete"] = False
        await update.message.reply_text(text="Entry deleted ✅")