import asyncio
import logging
import firebase_admin
import requests
import json
import io
import time
from firebase_admin import credentials
from firebase_admin import db
from firebase_admin import storage
from datetime import datetime
from PIL import Image
from aiogram.methods.send_invoice import SendInvoice
from aiogram import F
from aiogram.filters import Text
from aiogram.types import BufferedInputFile, InputFile, FSInputFile, LabeledPrice, ContentType
from aiogram.types.message import Message
from aiogram.filters.command import Command
from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardMarkup, ReplyKeyboardBuilder
from aiogram.types.inline_keyboard_button import InlineKeyboardButton
from aiogram.types.inline_keyboard_markup import InlineKeyboardMarkup
from aiogram.types.keyboard_button import KeyboardButton
from aiogram import Bot, Dispatcher, types
from googletrans import Translator

logging.basicConfig(level=logging.INFO)
translator = Translator()

data = {}

now = datetime.now()
bot_token = "6171986801:AAGJOdQ_SBhKGHMdJ2hjNn9kOp8aXAm1g3g"
key = 'SshkXza3AxSR9BAMu5oQdnXZTXUajtZXWDle9eSjDTcfwqfmIs50qFj7D5sp'
url = "https://stablediffusionapi.com/api/v3/dreambooth"
# Инициализируем бота и диспетчера
bot = Bot(token=bot_token)
dp = Dispatcher()

paybox_token = ""
robokassa_token = ''

cred = credentials.Certificate(
    "kaledoskop1-da4ec-firebase-adminsdk-ajzxz-d33fb84fb4.json")
default_app = firebase_admin.initialize_app(cred, {
    'databaseURL': 'https://kaledoskop1-da4ec-default-rtdb.firebaseio.com/',
    'storageBucket': 'gs://kaledoskop1-da4ec.appspot.com'
})

bucket = storage.bucket()
user = {
    'main': 'kk'
}
db.reference('/users_database/' + 'main').set(user)
# Задаем ID каналов, на подписку на который нужно проверять пользователя
channel_id1 = '@kodirovannyj_kalejdoskop'
channel_id2 = '@MidjourneyV5_kk'

# Задаем параметры цены
PRICE_20 = LabeledPrice(label="20 генераций", amount=1.2 * 100)
PRICE_40 = LabeledPrice(label="40 генераций", amount=2.2 * 100)
PRICE_80 = LabeledPrice(label="80 генераций", amount=3.5 * 100)
PRICE_200 = LabeledPrice(label="200 генераций", amount=6 * 100)


def chatgpt_channel():
    buttons = [
        [InlineKeyboardButton(text='ChatGPT-4', url='https://t.me/ChatGPT4_kk')],
        [InlineKeyboardButton(text='Midjourney V5', url='https://t.me/MidjourneyV5_kk')]
    ]
    keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
    return keyboard


def checking_5_min(id):
    n = time.time()
    if db.reference('/users_database/').get()[str(id)]['time'] + 120 <= n:
        return True
    else:
        return False


def free_generaions(id):
    n = time.time()
    if db.reference('/users_database/').get()[str(id)]['from_last_free'] + 320 <= n:
        user = {
            'generation': db.reference('/users_database/').get()[str(id)]['generation'] + 5,
            'time': db.reference('/users_database/').get()[str(id)]['time'],
            'from_last_free': time.time(),
            'selected_bot': db.reference('/users_database/').get()[str(id)]['selected_bot']
        }
        db.reference('/users_database/' + str(id)).set(user)
        return True
    else:
        return False


def reply_keyboard():
    buttons = [
        [
            KeyboardButton(text='Инфо ????'),
            KeyboardButton(text='Поддержка ????‍????'),
            KeyboardButton(text='Профиль ????'),
        ],
        [KeyboardButton(text='???? Модели'), ],
        [KeyboardButton(text='Генерации')],
        [KeyboardButton(text='ChatGPT-4 | Midjourney V5')]

    ]
    keyboard = ReplyKeyboardMarkup(keyboard=buttons, resize_keyboard=True)
    return keyboard


def generations_menu():
    buttons = [
        [
            InlineKeyboardButton(text='Бесплатные генерации', callback_data='free_generations')
        ],
        [
            InlineKeyboardButton(text='Покупка генераций', callback_data='buy_generations')
        ]
    ]
    keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
    return keyboard


def model_choose():
    buttons = [
        [
            InlineKeyboardButton(text='Analog-Diffusion', callback_data='analog'),
            InlineKeyboardButton(text='Anime', callback_data='anime')
        ],
        [
            InlineKeyboardButton(text='Realistic Vision', callback_data='realistic'),
            InlineKeyboardButton(text='StableDiffusion', callback_data='midjourney')
        ]
    ]
    keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
    return keyboard


def payment_selection():
    buttons = [
        [
            InlineKeyboardButton(text='Robokassa', callback_data='robokassa'),
            InlineKeyboardButton(text='Paybox', callback_data='paybox')
        ]
    ]
    keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
    return keyboard


def payment_keyboard_paybox():
    buttons = [
        [
            InlineKeyboardButton(text='20 - 1.2$', callback_data='20-gen-paybox'),
            InlineKeyboardButton(text='40 - 2.2$', callback_data='40-gen-paybox'),

        ],
        [
            InlineKeyboardButton(text='80 - 3.5$', callback_data='80-gen-paybox'),
            InlineKeyboardButton(text='200 - 6$', callback_data='200-gen-paybox')
        ]
    ]
    keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
    return keyboard


def payment_keyboard_robokassa():
    buttons = [
        [
            InlineKeyboardButton(text='20 - 1.2$', callback_data='20-gen-robo'),
            InlineKeyboardButton(text='40 - 2.2$', callback_data='40-gen-robo'),

        ],
        [
            InlineKeyboardButton(text='80 - 3.5$', callback_data='80-gen-robo'),
            InlineKeyboardButton(text='200 - 6$', callback_data='200-gen-robo')
        ]
    ]
    keyboard = InlineKeyboardMarkup(inline_keyboard=buttons)
    return keyboard


@dp.callback_query(Text('20-gen-paybox'))
async def gen_20_paybox(message: types.Message):
    await bot.send_invoice(
        chat_id=message.from_user.id,
        title='20 генераций',
        description="Покупка 20 генераций",
        provider_token=paybox_token,
        currency='USD',
        is_flexible=False,
        prices=[PRICE_20],
        start_parameter='20-generation',
        payload="20",
    )


@dp.callback_query(Text('40-gen-paybox'))
async def gen_40_paybox(message: types.Message):
    await bot.send_invoice(
        chat_id=message.from_user.id,
        title='40 генераций',
        description="Покупка 40 генераций",
        provider_token=paybox_token,
        currency='USD',
        is_flexible=False,
        prices=[PRICE_40],
        start_parameter='40-generation',
        payload="40",
    )


@dp.callback_query(Text('80-gen-paybox'))
async def gen_80_paybox(message: types.Message):
    await bot.send_invoice(
        chat_id=message.from_user.id,
        title='80 генераций',
        description="Покупка 80 генераций",
        provider_token=paybox_token,
        currency='USD',
        is_flexible=False,
        prices=[PRICE_80],
        start_parameter='80-generation',
        payload="80",
    )


@dp.callback_query(Text('200-gen-paybox'))
async def gen_200_paybox(message: types.Message):
    await bot.send_invoice(
        chat_id=message.from_user.id,
        title='200 генераций',
        description="Покупка 200 генераций",
        provider_token=paybox_token,
        currency='USD',
        is_flexible=False,
        prices=[PRICE_200],
        start_parameter='200-generation',
        payload="200",
    )


@dp.callback_query(Text('20-gen-robo'))
async def gen_20_robo(message: types.Message):
    await bot.send_invoice(
        chat_id=message.from_user.id,
        title='20 генераций',
        description="Покупка 20 генераций",
        provider_token=robokassa_token,
        currency='USD',
        is_flexible=False,
        prices=[PRICE_20],
        start_parameter='20-generation',
        payload="20",
    )


@dp.callback_query(Text('40-gen-robo'))
async def gen_40_robo(message: types.Message):
    await bot.send_invoice(
        chat_id=message.from_user.id,
        title='40 генераций',
        description="Покупка 40 генераций",
        provider_token=robokassa_token,
        currency='USD',
        is_flexible=False,
        prices=[PRICE_40],
        start_parameter='40-generation',
        payload="40",
    )


@dp.callback_query(Text('80-gen-robo'))
async def gen_80_robo(message: types.Message):
    await bot.send_invoice(
        chat_id=message.from_user.id,
        title='80 генераций',
        description="Покупка 80 генераций",
        provider_token=robokassa_token,
        currency='USD',
        is_flexible=False,
        prices=[PRICE_80],
        start_parameter='80-generation',
        payload="80",
    )


@dp.callback_query(Text('200-gen-robo'))
async def gen_200_robo(message: types.Message):
    await bot.send_invoice(
        chat_id=message.from_user.id,
        title='200 генераций',
        description="Покупка 200 генераций",
        provider_token=robokassa_token,
        currency='USD',
        is_flexible=False,
        prices=[PRICE_200],
        start_parameter='200-generation',
        payload="200",
    )


@dp.callback_query(Text('paybox'))
async def payment(query: types.CallbackQuery):
    await query.message.edit_text(text='Выберите количевство генераций', reply_markup=payment_keyboard_paybox())


@dp.callback_query(Text('robokassa'))
async def payment(query: types.CallbackQuery):
    await query.message.edit_text(text='Выберите количевство генераций', reply_markup=payment_keyboard_robokassa())


@dp.callback_query(Text('payment'))
async def payment(query: types.CallbackQuery):
    await query.message.edit_text(text='Выберите платежную систему', reply_markup=payment_selection())


@dp.callback_query(Text('anime'))
async def info_menu(query: types.CallbackQuery):
    user = {
        'selected_bot': 'anything-v4'
    }
    db.reference('/users_database/' + str(query.from_user.id)).update(user)
    await query.message.answer('Успешно выбран бот: Anime')


@dp.callback_query(Text('analog'))
async def info_menu(query: types.CallbackQuery):
    user = {
        'selected_bot': 'pastel-mixed'
    }
    db.reference('/users_database/' + str(query.from_user.id)).update(user)
    await query.message.answer('Успешно выбран бот: Analog-Diffusion')


@dp.callback_query(Text('realistic'))
async def info_menu(query: types.CallbackQuery):
    user = {
        'selected_bot': 'realistic-vision-v13'
    }
    db.reference('/users_database/' + str(query.from_user.id)).update(user)
    await query.message.answer('Успешно выбран бот: Realistic Vision')


@dp.callback_query(Text('midjourney'))
async def info_menu(query: types.CallbackQuery):
    user = {
        'selected_bot': 'midjourney'
    }
    db.reference('/users_database/' + str(query.from_user.id)).update(user)
    await query.message.answer('Успешно выбран бот: StableDiffusion')


@dp.callback_query(Text('buy_generations'))
async def info_menu(query: types.CallbackQuery):
    await query.message.answer('Покупка генераций:', reply_markup=payment_selection())


@dp.callback_query(Text('free_generations'))
async def free_generations(query: types.CallbackQuery):
    if free_generaions(query.from_user.id):
        await query.message.answer('Успешно добавлено 3 генерации на ваш аккаунт.')
    else:
        await query.message.answer('С момента последнего взятия генераций, не прошло 24 часа.')


@dp.message(F.text == 'ChatGPT-4 | Midjourney V5')
async def info_menu(message: types.Message):
    await message.answer('Каналы ChatGpt-4 | Midjourney V5', reply_markup=chatgpt_channel())


@dp.message(F.text == 'Генерации')
async def models_menu(message: types.Message):
    await message.answer('Меню генераций:', reply_markup=generations_menu())


@dp.message(F.text == '???? Модели')
async def models_menu(message: types.Message):
    await message.answer('Модели:', reply_markup=model_choose())


@dp.message(F.text == 'Инфо ????')
async def info_menu(message: types.Message):
    await message.answer(
        'text'
    )


@dp.message(F.text == 'Профиль ????')
async def info_generations_menu(message: types.Message):
    await message.answer(
        f'На вашем аккаунте осталось - {db.reference("/users_database/").get()[str(message.from_user.id)]["generation"]} генераций')


@dp.message(F.text == 'Поддержка ????‍????')
async def info_generations_menu(message: types.Message):
    await message.answer('Support')


# Команда для старта бота
@dp.message(Command('start'))
async def start_command(message: types.Message):
    if str(message.from_user.id) not in db.reference('/users_database/').get():
        user = {
            'generation': 3,
            'time': 0,
            'from_last_free': 0,
            'selected_bot': 'midjourney',
        }
        db.reference('/users_database/' + str(message.from_user.id)).set(user)
    await message.reply(
        "Я бот, который может генерировать изображения благодаря ИИ. Чтобы начать, отправь мне свой запрос.",
        reply_markup=reply_keyboard())


@dp.message(Command('buy'))
async def start_command(message: types.Message):
    await message.reply(
        "Покупка генераций:",
        reply_markup=payment_selection())


@dp.message(Command('profile'))
async def start_command(message: types.Message):
    await message.answer(
        f'На вашем аккаунте осталось - {db.reference("/users_database/").get()[str(message.from_user.id)]["generation"]} генераций\nВыбран режим: MidJourney_{db.reference("/users_database/").get()[str(message.from_user.id)]["selected_bot"]}')


# pre checkout  (must be answered in 10 seconds)
@dp.pre_checkout_query(lambda query: True)
async def pre_checkout_query(pre_checkout_q: types.PreCheckoutQuery):
    await bot.answer_pre_checkout_query(pre_checkout_q.id, ok=True)


# successful payment
@dp.message(F.successful_payment)
async def successful_payment(message: types.Message):
    print("УСПЕШНАЯ ОПЛАТА:")
    user = {
        'generation': db.reference('/users_database/').get()[str(message.from_user.id)]['generation'] + int(
            message.successful_payment.invoice_payload),
        'time': time.time(),
        'from_last_free': db.reference('/users_database/').get()[str(message.from_user.id)]['from_last_free'],
        'selected_bot': db.reference('/users_database/').get()[str(message.from_user.id)]['selected_bot']
    }
    db.reference('/users_database/' + str(message.from_user.id)).set(user)
    await bot.send_message(message.from_user.id,
                           f"Платеж на сумму {message.successful_payment.total_amount // 100} {message.successful_payment.invoice_payload} прошел успешно!!!")


# Обработчик текстовых сообщений
@dp.message(F.text)
async def text_message_handler(message: types.Message):
    # Проверяем, подписан ли пользователь на канал
    text = message.text
    translation = translator.translate(text, dest='en')
    text = translation.text
    is_subscribed = await bot.get_chat_member(channel_id1, message.from_user.id)
    is_subscribed2 = await bot.get_chat_member(channel_id2, message.from_user.id)
    if is_subscribed.status == "left" or is_subscribed2.status == 'left':
        await message.reply(f"Чтобы генерировать картинки, подпишитесь на наш канал. {channel_id1} и {channel_id2}")
        return

    if db.reference('/users_database/').get()[str(message.from_user.id)]['generation'] <= 0:
        await message.reply('Простите, не хватает генераций')
        return
    if not checking_5_min(message.from_user.id):
        await message.reply('С момента последней генерации, не прошло 2 минут. Пожалуйста подождите')
        return
    await message.answer('Произвожу генерацию... Время ожидания до 2 мин')
    headers = {}
    payload = {
        "key": key,
        "model_id": db.reference('/users_database/' + str(message.from_user.id)).get()['selected_bot'],
        "prompt": text,
        "negative_prompt": "painting, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, deformed, ugly, blurry, bad anatomy, bad proportions, extra limbs, cloned face, skinny, glitchy, double torso, extra arms, extra hands, mangled fingers, missing lips, ugly face, distorted face, extra legs, anime",
        "width": "512",
        "height": "512",
        "samples": "2",
        "num_inference_steps": "40",
        "scheduler": "UniPCMultistepScheduler",
        "safety_checker": "yes",
        "seed": "null",
        "guidance_scale": 7.5,
        "webhook": "null",
        "track_id": "null"
    }
    response = requests.request("POST", url, headers=headers, data=payload)
    if json.loads(response.text)['status'] == 'processing':
        await asyncio.sleep(int(json.loads(response.text)['eta'] + 1))
        payload = {
            'key': key,
            'request_id': json.loads(response.text)['id']
        }
        response = requests.request('POST', 'https://stablediffusionapi.com/api/v4/dreambooth/fetch', headers={},
                                    data=payload)
    print(response)
    w = json.loads(response.text)
    print(w)
    # for res in w['output']:
    #     if i == 1:
    #         x = 0
    #         y = 0
    #         r.append(res)
    #     elif i == 2:
    #         x = 512
    #         y = 0
    #         r.append(res)
    #     elif i == 3:
    #         x = 0
    #         y = 512
    #         r.append(res)
    #     elif i == 4:
    #         x = 512
    #         y = 512
    #         r.append(res)
    #     resp = requests.get(res)
    #     ima = Image.open(io.BytesIO(resp.content))
    #     img.paste(ima, (x, y))
    #     i += 1
    # img_byte_arr = io.BytesIO()
    # img.save(img_byte_arr, format='PNG')
    # img_byte_arr = img_byte_arr.getvalue()
    # p = BufferedInputFile(img_byte_arr, 'photo.png')
    user = {
        'generation': db.reference('/users_database/').get()[str(message.from_user.id)]['generation'] - 1,
        'time': time.time(),
    }
    db.reference('/users_database/' + str(message.from_user.id)).update(user)
    await bot.send_photo(chat_id=message.from_user.id, photo=w['output'][0])
    await bot.send_photo(chat_id=message.from_user.id, photo=w['output'][1])


async def main():
    await dp.start_polling(bot)


if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(main())