import asyncio
import logging
import sys
import os

# Добавляем текущую директорию в путь для импортов
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from aiogram import Bot, Dispatcher, types, F
from aiogram.filters import Command
from aiogram.types import Message, CallbackQuery
from aiogram.fsm.context import FSMContext

from config import BOT_TOKEN
from db import (
    create_db, add_user, get_languages,
    get_user_language, set_user_language,
    get_language_text, get_language_buttons,
    handle_referal
)
from handlers.catalog import router as catalog_router  # button1 logic
from handlers.info import router as info_router  # button2 logic
from handlers.cryptobot import router as cryptobot_router  # button13 logic
from handlers.bank_card import router as bank_card_router  # button14 logic
from handlers.ref_sistema import router as ref_sistema_router  # button7 logic
from handlers.popolnit import router as popolnit_router  # button8 logic
from handlers.delivery import router as delivery_router  # button4 logic
from handlers.operator import router as operator_router  # button6 logic
from handlers.my_order import router as my_order_router  # button3 logic
from handlers.jobs import router as jobs_router  # button5 logic

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

bot = Bot(token=BOT_TOKEN)
dp = Dispatcher()

LANG_CB_PREFIX = "set_lang:"
MENU_CB_PREFIX = "menu:"        # menu:button1 ... menu:button9
BACK_KEY = f"{MENU_CB_PREFIX}button9"  # «назад»


def build_language_keyboard(langs: list[str]) -> types.InlineKeyboardMarkup:
    kb = types.InlineKeyboardMarkup(inline_keyboard=[])
    if not langs:
        langs = ["Русский", "O'zbek", "English"]
    for name in langs:
        kb.inline_keyboard.append([
            types.InlineKeyboardButton(text=name, callback_data=f"{LANG_CB_PREFIX}{name}")
        ])
    return kb


def build_main_menu(lang: str) -> types.InlineKeyboardMarkup:
    texts = get_language_buttons(lang)  # {'button1': '...', ...}
    rows_spec = [
        ("button1", "button2"),
        ("button3",),
        ("button4", "button5"),
        ("button6", "button7"),
        ("button8",),
    ]
    inline_rows: list[list[types.InlineKeyboardButton]] = []
    for row in rows_spec:
        row_btns = []
        for key in row:
            label = texts.get(key)
            if label:
                row_btns.append(
                    types.InlineKeyboardButton(text=label, callback_data=f"{MENU_CB_PREFIX}{key}")
                )
        if row_btns:
            inline_rows.append(row_btns)
    return types.InlineKeyboardMarkup(inline_keyboard=inline_rows)


async def send_main_menu(user_id: int, chat_id: int) -> None:
    """
    Присылает главное меню: text1 + кнопки.
    """
    lang = get_user_language(user_id)
    if not lang:
        langs = get_languages()
        kb = build_language_keyboard(langs)
        await bot.send_message(chat_id, "Выберите язык\nLanguage", reply_markup=kb)
        return
    greet = get_language_text(lang, "text1") or "Добро пожаловать!"
    menu_kb = build_main_menu(lang)
    await bot.send_message(chat_id, greet, reply_markup=menu_kb)


@dp.message(Command("start"))
async def start_handler(message: Message):
    user = message.from_user
    user_id = user.id

    try:
        create_db()
        
        # Обработка реферальной ссылки
        referal_id = None
        if len(message.text.split()) > 1:
            referal_param = message.text.split()[1]
            if referal_param.isdigit():
                referal_id = int(referal_param)
                print(f"Referal detected: {referal_id} from user: {user_id}")
        
        # Добавляем пользователя и обрабатываем реферала
        add_user(user_id, user.first_name or "", user.last_name or "", user.username)
        
        # Если есть реферал, обрабатываем его
        if referal_id and referal_id != user_id:
            referal_processed = handle_referal(user_id, referal_id)
            if referal_processed:
                # Отправляем уведомление рефералу
                referal_lang = get_user_language(referal_id)
                text21 = get_language_text(referal_lang, "text21") or "По вашей ссылке зарегистрировался новый пользователь!"
                try:
                    await bot.send_message(referal_id, text21)
                    print(f"Sent referal notification to {referal_id}")
                except Exception as e:
                    print(f"Could not send referal notification: {e}")
        
    except Exception as e:
        logger.error(f"DB init/add_user error: {e}")

    await send_main_menu(user_id, message.chat.id)


@dp.callback_query(F.data.startswith(LANG_CB_PREFIX))
async def on_language_chosen(cb: CallbackQuery):
    lang = cb.data[len(LANG_CB_PREFIX):].strip()
    user_id = cb.from_user.id

    langs = get_languages()
    if langs and lang not in langs:
        await cb.answer("Этот язык пока недоступен.", show_alert=True)
        return

    if not set_user_language(user_id, lang):
        await cb.answer("Не удалось сохранить язык. Попробуйте позже.", show_alert=True)
        return

    try:
        await cb.message.delete()  # удаляем старое сообщение с выбором языка
    except Exception:
        pass

    await send_main_menu(user_id, cb.message.chat.id)
    await cb.answer()


# Возврат «назад» в главное меню (button9) — очищаем состояние и показываем главное меню
@dp.callback_query(F.data == BACK_KEY)
async def go_back_to_main(cb: CallbackQuery, state: FSMContext):
    try:
        await cb.message.delete()  # удаляем экран каталога (или другой раздел)
    except Exception:
        pass
    await state.clear()
    await send_main_menu(cb.from_user.id, cb.message.chat.id)
    await cb.answer()


# Фолбэк: ЛОВИТ ВСЕ menu:* КРОМЕ button1, button2, button3, button4, button5, button6, button7, button8 и button9 (назад)
@dp.callback_query(
    F.data.startswith(MENU_CB_PREFIX)
    & (F.data != f"{MENU_CB_PREFIX}button1")
    & (F.data != f"{MENU_CB_PREFIX}button2")  # Исключаем button2 из фолбэка
    & (F.data != f"{MENU_CB_PREFIX}button3")  # Исключаем button3 из фолбэка
    & (F.data != f"{MENU_CB_PREFIX}button4")  # Исключаем button4 из фолбэка
    & (F.data != f"{MENU_CB_PREFIX}button5")  # Исключаем button5 из фолбэка
    & (F.data != f"{MENU_CB_PREFIX}button6")  # Исключаем button6 из фолбэка
    & (F.data != f"{MENU_CB_PREFIX}button7")  # Исключаем button7 из фолбэка
    & (F.data != f"{MENU_CB_PREFIX}button8")  # Исключаем button8 из фолбэка
    & (F.data != BACK_KEY)
)
async def menu_fallback(cb: CallbackQuery):
    key = cb.data[len(MENU_CB_PREFIX):]
    logging.info(f"Fallback for key={key} from user={cb.from_user.id}")

    # удаляем старое сообщение и присылаем новое
    try:
        await cb.message.delete()
    except Exception:
        pass
    await bot.send_message(cb.message.chat.id, "Скоро будет доступно.")
    await cb.answer()


async def main():
    create_db()
    dp.include_router(catalog_router)  # button1
    dp.include_router(info_router)  # button2
    dp.include_router(cryptobot_router)  # button13
    dp.include_router(bank_card_router)  # button14
    dp.include_router(ref_sistema_router)  # button7
    dp.include_router(popolnit_router)  # button8
    dp.include_router(delivery_router)  # button4
    dp.include_router(operator_router)  # button6
    dp.include_router(my_order_router)  # button3
    dp.include_router(jobs_router)  # button5
    logging.info("Bot started")
    await dp.start_polling(bot)


if __name__ == "__main__":
    asyncio.run(main())