from aiogram import Router, types
import aiogram.exceptions
import aiogram.exceptions
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import (
    Message,
    ReplyKeyboardMarkup,
    KeyboardButton,
    InlineKeyboardMarkup,
    InlineKeyboardButton
)
from aiogram import Bot
from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardBuilder
from aiogram.filters.command import Command, CommandObject
from aiogram.filters.callback_data import CallbackData
from core.middleware import AdminMiddleware
from aiogram.types import FSInputFile
from aiogram import F
from typing import Optional
from contextlib import suppress
from aiogram.exceptions import TelegramBadRequest
from source_dir.photoedit import *
from dbase.db import DataBase
import cfg
import urllib.parse as urlib
import uuid, hashlib, json
from datetime import datetime
from core.keyboard import *
from source_dir.photoedit import *
from logger import get_logger
import aiosqlite

LOG = get_logger()

bot = Bot(token=cfg.TOKEN)
db = DataBase(file=cfg.DATABASE_URL)
router = Router()
router.message.outer_middleware(AdminMiddleware())


class Photoeditfsm(StatesGroup):
    get_text = State()

async def get_info_list(key_list, index, menu_id=1):
    value_list = []

    for obj in key_list:
        temp = await db.get_position_info(index=index, value=obj, menu_id=menu_id)
        value_list.append(temp)

    return value_list

@router.message(lambda message: message.text == "🔙Назад")
@router.message(Command("start"))
@router.message(lambda message: message.text == "start")
async def cmd_start(message: Message, state: FSMContext):
    await state.set_state(state=None)
    await message.answer('Добро пожаловать! Выберите меню для редактирования:', reply_markup=menu_selection_kb())


@router.callback_query(PhotoeditingCallbackFactory.filter())
async def photoedit_callback_factory(callback: types.CallbackQuery, callback_data: PhotoeditingCallbackFactory, state:FSMContext):
    menu_id = callback_data.menu_id if callback_data.menu_id else 1
    
    if callback_data.act == 'select_menu':
        async with aiosqlite.connect(db.file) as conn:
            cursor = await conn.execute(f'SELECT COUNT(*) FROM position WHERE menu_id = {menu_id}')
            count = await cursor.fetchone()
            await cursor.close()
            
            if count[0] == 0:
                if menu_id == 1:
                    cursor = await conn.execute(f'''
                        INSERT INTO position (position, menu_id, up_text, main_text, celsius_text, price_text, 
                                            up_font, main_font, celsius_font, price_font, 
                                            up_xy, main_xy, celsius_xy, price_xy)
                        SELECT position, ?, up_text, main_text, celsius_text, price_text,
                               up_font, main_font, celsius_font, price_font,
                               up_xy, main_xy, celsius_xy, price_xy
                        FROM position WHERE menu_id = 1 AND position <= 20
                    ''', (menu_id,))
                else:  # menu_id == 2 or 3
                    cursor = await conn.execute(f'''
                        INSERT INTO position (position, menu_id, up_text, main_text, celsius_text, price_text, 
                                            up_font, main_font, celsius_font, price_font, 
                                            up_xy, main_xy, celsius_xy, price_xy)
                        SELECT position, ?, up_text, main_text, celsius_text, price_text,
                               up_font, main_font, celsius_font, price_font,
                               up_xy, main_xy, celsius_xy, price_xy
                        FROM position WHERE menu_id = 1 AND (position <= 16 OR position >= 18)
                    ''', (menu_id,))
                await conn.commit()
                await cursor.close()
        
        await state.update_data(current_menu_id=menu_id)
        
        await callback.message.delete()

        if menu_id == 1:
            path = f"{cfg.SOURCE_DIR}/source.png"
        elif menu_id == 2:
            path = f"{cfg.SOURCE_DIR}/source-promotion.png"
        else:  # menu_id == 3
            path = f"{cfg.SOURCE_DIR}/source-promotion-2.png"
        document = FSInputFile(path=path)
        test = await callback.message.answer_document(document)
        
        await state.update_data(photo_mes_id=test.message_id)
        
        await callback.message.answer(f'Вы выбрали Меню {menu_id}. Нажмите на кнопки соответствующих позиций для редактирования', 
                                    reply_markup=position_numbers_kb_with_menu(menu_id))
    
    elif callback_data.act == 'change_menu':
        await callback.message.delete()
        await callback.message.answer('Выберите меню для редактирования:', reply_markup=menu_selection_kb())
    
    elif callback_data.act == 'start':
        await callback.message.delete()

        path = f"{cfg.SOURCE_DIR}/source.png"
        document = FSInputFile(path=path)
        test = await callback.message.answer_document(document)


        await state.update_data(photo_mes_id = test.message_id)

        await callback.message.answer('Нажмите на кнопки соответствующих позиций для редактирования', reply_markup=position_numbers_kb())

    elif callback_data.act == 'generate':
        data = await state.get_data()

        await bot.delete_message(chat_id=callback.from_user.id, message_id=data['photo_mes_id'])

        await generate_image(menu_id=menu_id)

        # path = "demo.jpg"
        # photo = FSInputFile(path=path)

        await callback.message.delete()

        
        document = FSInputFile(f'{cfg.SOURCE_DIR}/demo.png')
        await callback.message.answer_document(document)

    elif callback_data.act == 'default':
        await set_default_params(menu_id=menu_id)
        with suppress(TelegramBadRequest):
            await callback.message.edit_text(f'Настройки для Меню {menu_id} выставлены по умолчанию\n\nНажмите на кнопки соответствующих позиций для редактирования', 
                                          reply_markup=position_numbers_kb_with_menu(menu_id))
            
    elif callback_data.act == 'edit_up':
        index = callback_data.num

        key_list = ['up_text', 'up_font', 'up_xy']

        value_list = await get_info_list(key_list=key_list, index=index, menu_id=menu_id)

        with suppress(TelegramBadRequest):
            await callback.message.edit_text(
text=f'''
Вы редактируете {index} позицию (Меню {menu_id})
∟Верхний текст
<b>Текущие значения:</b> 
<b>Текст:</b> {value_list[0]}
<b>Размер шрифта:</b> {value_list[1]}
<b>Расположение:</b> {value_list[2]}
''', parse_mode='HTML', reply_markup=editing_params_with_menu(index=callback_data.num, param=callback_data.param, menu_id=menu_id))

    elif callback_data.act == 'edit_main':
        index = callback_data.num

        key_list = ['main_text', 'main_font', 'main_xy']

        value_list = await get_info_list(key_list=key_list, index=index, menu_id=menu_id)

        with suppress(TelegramBadRequest):
            await callback.message.edit_text(
text=f'''
Вы редактируете {index} позицию (Меню {menu_id})
∟Основной текст
<b>Текущие значения:</b> 
<b>Текст:</b> {value_list[0]}
<b>Размер шрифта:</b> {value_list[1]}
<b>Расположение:</b> {value_list[2]}
''', parse_mode='HTML', reply_markup=editing_params_with_menu(index=callback_data.num, param=callback_data.param, menu_id=menu_id))
            
    elif callback_data.act == 'edit_cel':
        index = callback_data.num

        key_list = ['celsius_text', 'celsius_font', 'celsius_xy']

        value_list = await get_info_list(key_list=key_list, index=index, menu_id=menu_id)

        with suppress(TelegramBadRequest):
            await callback.message.edit_text(
text=f'''
Вы редактируете {index} позицию (Меню {menu_id})
∟Градус
<b>Текущие значения:</b> 
<b>Текст:</b> {value_list[0]}
<b>Размер шрифта:</b> {value_list[1]}
<b>Расположение:</b> {value_list[2]}
''', parse_mode='HTML', reply_markup=editing_params_with_menu(index=callback_data.num, param=callback_data.param, menu_id=menu_id))

    elif callback_data.act == 'edit_price':
        index = callback_data.num

        key_list = ['price_text', 'price_font', 'price_xy']

        value_list = await get_info_list(key_list=key_list, index=index, menu_id=menu_id)

        with suppress(TelegramBadRequest):
            await callback.message.edit_text(
text=f'''
Вы редактируете {index} позицию (Меню {menu_id})
∟Стоимость
<b>Текущие значения:</b> 
<b>Текст:</b> {value_list[0]}
<b>Размер шрифта:</b> {value_list[1]}
<b>Расположение:</b> {value_list[2]}
''', parse_mode='HTML', reply_markup=editing_params_with_menu(index=callback_data.num, param=callback_data.param, menu_id=menu_id))
            

    elif callback_data.act == 'edit_text':
        if callback_data.param:
            await state.update_data(now_editing = f'{callback_data.param}_text_{callback_data.num}_{menu_id}')

        await state.update_data(mes_to_edit = callback.message)
        await state.set_state(Photoeditfsm.get_text)
        
        with suppress(TelegramBadRequest):
            await callback.message.edit_text('Введите значение ', reply_markup=back(index=callback_data.num, param=callback_data.param, menu_id=menu_id))

    elif callback_data.act == 'edit_font':

        if callback_data.param:
            await state.update_data(now_editing = f'{callback_data.param}_font_{callback_data.num}_{menu_id}')

        await state.update_data(mes_to_edit = callback.message)
        await state.set_state(Photoeditfsm.get_text)

        with suppress(TelegramBadRequest):
            await callback.message.edit_text('Введите значение размера шрифта', reply_markup=back(index=callback_data.num, param=callback_data.param, menu_id=menu_id))
        
    elif callback_data.act == 'edit_xy':

        if callback_data.param:
            await state.update_data(now_editing = f'{callback_data.param}_xy_{callback_data.num}_{menu_id}')

        await state.update_data(mes_to_edit = callback.message)
        await state.set_state(Photoeditfsm.get_text)

        with suppress(TelegramBadRequest):
            await callback.message.edit_text('Введите значение в формате "x, y"\nПример: 100, 200', reply_markup=back(index=callback_data.num, param=callback_data.param, menu_id=menu_id))


    elif callback_data.act == 'back_to_number':
        await callback.message.delete()

        await callback.message.answer(f'Нажмите на кнопки соответствующих позиций для редактирования (Меню {menu_id})', reply_markup=position_numbers_kb_with_menu(menu_id))

    elif callback_data.act == 'back_to_position':
        index = callback_data.num

        key_list = ['up_text', 'main_text', 'celsius_text', 'price_text']
        value_list = []

        for obj in key_list:
            temp = await db.get_position_info(index=index, value=obj, menu_id=menu_id)
            value_list.append(temp)


        with suppress(TelegramBadRequest):
            await callback.message.edit_text(
text=f'''
Вы редактируете {index} позицию (Меню {menu_id})
<b>Текущие значения:</b> 
<b>Верхний текст:</b> {value_list[0]}
<b>Основной текст:</b> {value_list[1]}
<b>Градус:</b> {value_list[2]}
<b>Стоимость:</b> {value_list[3]}
''', parse_mode='HTML', reply_markup=editing_position_with_menu(index=index, menu_id=menu_id))
            
    elif callback_data.act == 'back_to_params':
        index = callback_data.num
        param = callback_data.param

        key_list = [f'{param}_text', f'{param}_font', f'{param}_xy']

        value_list = await get_info_list(key_list=key_list, index=index, menu_id=menu_id)

        with suppress(TelegramBadRequest):
            await callback.message.edit_text(
text=f'''
Вы редактируете {index} позицию (Меню {menu_id})
<b>Текущие значения:</b> 
<b>Текст:</b> {value_list[0]}
<b>Размер шрифта:</b> {value_list[1]}
<b>Расположение:</b> {value_list[2]}
''', parse_mode='HTML', reply_markup=editing_params_with_menu(index=callback_data.num, param=callback_data.param, menu_id=menu_id))

    elif callback_data.act == 'clear':
        data = await state.get_data()

        now_editing = data['now_editing']

        now_editing_ = now_editing.split('_')

        index = now_editing_[2]
        param = now_editing_[0]
        menu_id = int(now_editing_[3]) if len(now_editing_) > 3 else 1

        await db.clear_position(index=index, key=f'{now_editing_[0]}_{now_editing_[1]}', menu_id=menu_id)

        key_list = [f'{param}_text', f'{param}_font', f'{param}_xy']

        value_list = await get_info_list(key_list=key_list, index=index, menu_id=menu_id)

        with suppress(TelegramBadRequest):
            await callback.message.edit_text(
text=f'''
Вы редактируете {index} позицию (Меню {menu_id})
<b>Текущие значения:</b> 
<b>Текст:</b> {value_list[0]}
<b>Размер шрифта:</b> {value_list[1]}
<b>Расположение:</b> {value_list[2]}
''', parse_mode='HTML', reply_markup=editing_params_with_menu(index=index, param=param, menu_id=menu_id))


    elif callback_data.num:
        index = callback_data.num

        key_list = ['up_text', 'main_text', 'celsius_text', 'price_text']
        value_list = []

        for obj in key_list:
            temp = await db.get_position_info(index=index, value=obj, menu_id=menu_id)
            value_list.append(temp)


        with suppress(TelegramBadRequest):
            await callback.message.edit_text(
text=f'''
Вы редактируете {index} позицию (Меню {menu_id})
<b>Текущие значения:</b> 
<b>Верхний текст:</b> {value_list[0]}
<b>Основной текст:</b> {value_list[1]}
<b>Градус:</b> {value_list[2]}
<b>Стоимость:</b> {value_list[3]}
''', parse_mode='HTML', reply_markup=editing_position_with_menu(index=index, menu_id=menu_id))


@router.message(Photoeditfsm.get_text)
async def fsm_get_up_text(message: Message, state: FSMContext):
    await state.set_state(state=None)

    data = await state.get_data()

    mes_to_edit = data['mes_to_edit']

    now_editing = data['now_editing']

    now_editing_ = now_editing.split('_')

    index = now_editing_[2]
    param = now_editing_[0]
    menu_id = int(now_editing_[3]) if len(now_editing_) > 3 else 1

    await db.update_position(index=index, key=f'{now_editing_[0]}_{now_editing_[1]}', value=message.text, menu_id=menu_id)

    await message.delete()

    key_list = [f'{param}_text', f'{param}_font', f'{param}_xy']

    value_list = await get_info_list(key_list=key_list, index=index, menu_id=menu_id)

    with suppress(TelegramBadRequest):
        await mes_to_edit.edit_text(
text=f'''
Вы редактируете {index} позицию (Меню {menu_id})
<b>Текущие значения:</b> 
<b>Текст:</b> {value_list[0]}
<b>Размер шрифта:</b> {value_list[1]}
<b>Расположение:</b> {value_list[2]}
''', parse_mode='HTML', reply_markup=editing_params_with_menu(index=index, param=param, menu_id=menu_id))
