"""
Расширенный пример: магазин с формами, валидацией и корзиной
"""

import asyncio

from aiogram import Bot, Dispatcher, BaseMiddleware
from aiogram.types import Message
from aiogram.filters import CommandStart
from aiogram.fsm.storage.memory import MemoryStorage

from ui_router import (
    UIRouter,
    UIRouterExecutor,
    Scene,
    Handler,
    GlobalHandler,
    ActionInstruction,
    ActionType,
    EventType,
    TransitionType,
    MessageContent,
    Keyboard,
    Button,
    Filter,
    Flag,
    FlagGetter,
    DynamicContent,
    ContentTemplate,
)
from ui_router.services import SharedServices
from ui_router.state.storage import InMemoryNavigationStorage
from ui_router.state.variables import InMemoryVariableRepository
from ui_router.events import EventBus, InMemoryEventScheduler


# ============================================================================
# База данных (имитация)
# ============================================================================

PRODUCTS_DB = {
    "prod_1": {"name": "iPhone 15", "price": 89990, "stock": 5},
    "prod_2": {"name": "MacBook Pro", "price": 199990, "stock": 3},
    "prod_3": {"name": "AirPods Pro", "price": 24990, "stock": 10},
}

USERS_DB = {
    123456: {  # user_id
        "balance": 150000,
        "is_vip": True,
        "cart": {},  # product_id: quantity
        "orders": [],
    },
    870344336: {  # user_id
        "balance": 150000,
        "is_vip": True,
        "cart": {},  # product_id: quantity
        "orders": [],
    },
}


# ============================================================================
# Кастомные функции
# ============================================================================


async def get_user_balance(context):
    """Получить баланс пользователя"""
    user_id = context.event_data["event_from_user"].id
    return USERS_DB.get(user_id, {}).get("balance", 0)


async def get_cart_items_count(context):
    """Количество товаров в корзине"""
    user_id = context.event_data["event_from_user"].id
    cart = USERS_DB.get(user_id, {}).get("cart", {})
    return sum(cart.values())


async def get_cart_total(context):
    """Сумма корзины"""
    user_id = context.event_data["event_from_user"].id
    cart = USERS_DB.get(user_id, {}).get("cart", {})
    total = 0
    for prod_id, qty in cart.items():
        product = PRODUCTS_DB.get(prod_id)
        if product:
            total += product["price"] * qty
    return total


async def get_product_name(context):
    """Название выбранного товара"""
    prod_id = context.get_user_input("selected_product")
    product = PRODUCTS_DB.get(prod_id)
    return product["name"] if product else "Неизвестный товар"


async def get_product_price(context):
    """Цена выбранного товара"""
    prod_id = context.get_user_input("selected_product")
    product = PRODUCTS_DB.get(prod_id)
    return product["price"] if product else 0


async def get_product_stock(context):
    """Остаток товара"""
    prod_id = context.get_user_input("selected_product")
    product = PRODUCTS_DB.get(prod_id)
    return product["stock"] if product else 0


async def is_user_vip(context):
    """Проверка VIP статуса"""
    user_id = context.event_data["event_from_user"].id

    return USERS_DB.get(user_id, {}).get("is_vip", False)


async def has_items_in_cart(context):
    """Есть ли товары в корзине"""
    user_id = context.event_data["event_from_user"].id
    cart = USERS_DB.get(user_id, {}).get("cart", {})
    return len(cart) > 0


async def can_afford_cart(context):
    """Хватает ли денег на корзину"""
    balance = await get_user_balance(context)
    cart_total = await get_cart_total(context)
    return balance >= cart_total


async def validate_quantity(value: str, context) -> tuple[bool, str | None]:
    """Валидация количества товара"""
    try:
        qty = int(value)
        if qty < 1:
            return False, "Количество должно быть больше 0"
        if qty > 99:
            return False, "Максимум 99 штук"

        # Проверяем наличие на складе
        prod_id = context.get_user_input("selected_product")
        product = PRODUCTS_DB.get(prod_id)
        if product and qty > product["stock"]:
            return False, f"На складе только {product['stock']} шт."

        return True, None
    except ValueError:
        return False, "Введите число"


async def validate_email(value: str, context) -> tuple[bool, str | None]:
    """Валидация email"""
    import re

    pattern = r"^[\w\.-]+@[\w\.-]+\.\w+$"
    if re.match(pattern, value):
        return True, None
    return False, "Неверный формат email"


# ============================================================================
# Кастомные действия
# ============================================================================


async def action_add_to_cart(context, params) -> None:
    """Добавить товар в корзину"""
    user_id = context.event_data["event_from_user"].id
    prod_id = context.get_user_input("selected_product")
    quantity = int(context.get_user_input("product_quantity", 1))

    if user_id not in USERS_DB:
        USERS_DB[user_id] = {"balance": 0, "is_vip": False, "cart": {}, "orders": []}

    cart = USERS_DB[user_id]["cart"]
    cart[prod_id] = cart.get(prod_id, 0) + quantity

    print(f"Added {quantity}x {prod_id} to cart for user {user_id}")


async def action_clear_cart(context, params) -> None:
    """Очистить корзину"""
    user_id = context.event_data["event_from_user"].id
    if user_id in USERS_DB:
        USERS_DB[user_id]["cart"] = {}


async def action_process_order(context, params) -> None:
    """Обработать заказ"""
    user_id = context.event_data["event_from_user"].id

    if user_id not in USERS_DB:
        return

    cart = USERS_DB[user_id]["cart"]
    total = await get_cart_total(context)

    # Списываем средства
    USERS_DB[user_id]["balance"] -= total

    # Создаём заказ
    order = {
        "id": len(USERS_DB[user_id]["orders"]) + 1,
        "items": cart.copy(),
        "total": total,
    }
    USERS_DB[user_id]["orders"].append(order)

    # Очищаем корзину
    USERS_DB[user_id]["cart"] = {}

    # Уменьшаем остатки
    for prod_id, qty in cart.items():
        if prod_id in PRODUCTS_DB:
            PRODUCTS_DB[prod_id]["stock"] -= qty

    print(f"Order #{order['id']} processed for user {user_id}")


# ============================================================================
# UI схема
# ============================================================================

advanced_schema = UIRouter(
    name="shop_advanced",
    version="1.0.0",
    initial_scene="main_menu",
    custom_functions={
        "get_user_balance": "example_advanced.get_user_balance",
        "get_cart_items_count": "example_advanced.get_cart_items_count",
        "get_cart_total": "example_advanced.get_cart_total",
        "get_product_name": "example_advanced.get_product_name",
        "get_product_price": "example_advanced.get_product_price",
        "get_product_stock": "example_advanced.get_product_stock",
        "is_user_vip": "example_advanced.is_user_vip",
        "has_items_in_cart": "example_advanced.has_items_in_cart",
        "can_afford_cart": "example_advanced.can_afford_cart",
        "validate_quantity": "example_advanced.validate_quantity",
        "validate_email": "example_advanced.validate_email",
        "action_add_to_cart": "example_advanced.action_add_to_cart",
        "action_clear_cart": "example_advanced.action_clear_cart",
        "action_process_order": "example_advanced.action_process_order",
    },
    global_handlers=[
        GlobalHandler(
            name="cancel",
            event_type=EventType.MESSAGE,
            filters=[Filter(type="command", commands=["cancel"])],
            priority=10,
            interrupt_propagation=True,
            actions=[
                ActionInstruction(
                    type=ActionType.SEND_MESSAGE,
                    content=MessageContent(text="❌ Отменено"),
                ),
                ActionInstruction(
                    type=ActionType.GOTO_SCENE,
                    scene_id="main_menu",
                ),
            ],
        ),
    ],
    scenes=[
        # ====================================================================
        # Главное меню
        # ====================================================================
        Scene(
            id="main_menu",
            name="Главное меню",
            flags=[
                Flag(name="balance", getter=FlagGetter(type="function", function="get_user_balance")),
                Flag(name="cart_count", getter=FlagGetter(type="function", function="get_cart_items_count")),
            ],
            default_content=MessageContent(
                text=DynamicContent(
                    type="template",
                    template=ContentTemplate(
                        template="🏪 <b>Apple Store</b>\n\n💰 Баланс: {balance:,} ₽\n🛒 В корзине: {cart_count} шт.",
                        flags=["balance", "cart_count"],
                    ),
                ),
            ),
            default_keyboard=Keyboard(
                buttons=[
                    [Button(text="📱 Каталог", callback_action="goto_catalog")],
                    [Button(text="🛒 Корзина", callback_action="goto_cart")],
                    [Button(text="📦 Мои заказы", callback_action="goto_orders")],
                    [Button(text="⚙️ Настройки", callback_action="goto_settings")],
                ],
            ),
            handlers=[
                Handler(
                    name="goto_catalog",
                    event_type=EventType.CALLBACK,
                    actions=[
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="catalog",
                            transition=TransitionType.EDIT_SMART,
                        ),
                    ],
                ),
                Handler(
                    name="goto_cart",
                    event_type=EventType.CALLBACK,
                    actions=[
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="cart",
                            transition=TransitionType.EDIT_SMART,
                        ),
                    ],
                ),
                Handler(
                    name="goto_orders",
                    event_type=EventType.CALLBACK,
                    actions=[
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="orders",
                            transition=TransitionType.EDIT_SMART,
                        ),
                    ],
                ),
                Handler(
                    name="goto_settings",
                    event_type=EventType.CALLBACK,
                    actions=[
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="settings",
                            transition=TransitionType.EDIT_SMART,
                        ),
                    ],
                ),
            ],
        ),
        # ====================================================================
        # Каталог
        # ====================================================================
        Scene(
            id="catalog",
            name="Каталог",
            default_content=MessageContent(
                text="📱 <b>Каталог товаров</b>\n\nВыберите товар:",
            ),
            default_keyboard=Keyboard(
                buttons=[
                    [
                        Button(
                            text="iPhone 15 - 89,990 ₽",
                            callback_action="select_product",
                            callback_params={"selected_product": "prod_1"},
                        )
                    ],
                    [
                        Button(
                            text="MacBook Pro - 199,990 ₽",
                            callback_action="select_product",
                            callback_params={"selected_product": "prod_2"},
                        )
                    ],
                    [
                        Button(
                            text="AirPods Pro - 24,990 ₽",
                            callback_action="select_product",
                            callback_params={"selected_product": "prod_3"},
                        )
                    ],
                    [Button(text="◀️ Назад", callback_action="go_back")],
                ],
            ),
            handlers=[
                Handler(
                    name="select_product",
                    event_type=EventType.CALLBACK,
                    actions=[
                        # Параметры уже сохранены автоматически из callback_params
                        # prod_id -> selected_product
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="product_detail",
                            transition=TransitionType.EDIT_SMART,
                        ),
                    ],
                ),
                Handler(
                    name="go_back",
                    event_type=EventType.CALLBACK,
                    actions=[ActionInstruction(type=ActionType.BACK)],
                ),
            ],
        ),
        # ====================================================================
        # Детали товара
        # ====================================================================
        Scene(
            id="product_detail",
            name="Детали товара",
            flags=[
                Flag(name="prod_name", getter=FlagGetter(type="function", function="get_product_name")),
                Flag(name="prod_price", getter=FlagGetter(type="function", function="get_product_price")),
                Flag(name="prod_stock", getter=FlagGetter(type="function", function="get_product_stock")),
            ],
            default_content=MessageContent(
                text=DynamicContent(
                    type="template",
                    template=ContentTemplate(
                        template="📱 <b>{prod_name}</b>\n\n💰 Цена: {prod_price:,} ₽\n📦 В наличии: {prod_stock} шт.",
                        flags=["prod_name", "prod_price", "prod_stock"],
                    ),
                ),
            ),
            default_keyboard=Keyboard(
                buttons=[
                    [Button(text="🛒 Добавить в корзину", callback_action="add_to_cart")],
                    [Button(text="◀️ Назад", callback_action="go_back")],
                ],
            ),
            handlers=[
                Handler(
                    name="add_to_cart",
                    event_type=EventType.CALLBACK,
                    actions=[
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="enter_quantity",
                            transition=TransitionType.EDIT_SMART,
                        ),
                    ],
                ),
                Handler(
                    name="go_back",
                    event_type=EventType.CALLBACK,
                    actions=[ActionInstruction(type=ActionType.BACK)],
                ),
            ],
        ),
        # ====================================================================
        # Ввод количества
        # ====================================================================
        Scene(
            id="enter_quantity",
            name="Ввод количества",
            expect_input=True,
            input_validator="validate_quantity",
            flags=[
                Flag(name="prod_name", getter=FlagGetter(type="function", function="get_product_name")),
                Flag(name="prod_stock", getter=FlagGetter(type="function", function="get_product_stock")),
            ],
            default_content=MessageContent(
                text=DynamicContent(
                    type="template",
                    template=ContentTemplate(
                        template="🔢 Введите количество <b>{prod_name}</b>\n\n📦 Доступно: {prod_stock} шт.",
                        flags=["prod_name", "prod_stock"],
                    ),
                ),
            ),
            handlers=[
                Handler(
                    name="save_quantity",
                    event_type=EventType.MESSAGE,
                    filters=[Filter(type="text")],
                    actions=[
                        ActionInstruction(
                            type=ActionType.SAVE_INPUT,
                            save_as="product_quantity",
                        ),
                        ActionInstruction(
                            type=ActionType.CUSTOM,
                            function="action_add_to_cart",
                        ),
                        ActionInstruction(
                            type=ActionType.SEND_MESSAGE,
                            content=MessageContent(text="✅ Товар добавлен в корзину!"),
                        ),
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="main_menu",
                        ),
                    ],
                ),
            ],
        ),
        # ====================================================================
        # Корзина
        # ====================================================================
        Scene(
            id="cart",
            name="Корзина",
            flags=[
                Flag(name="cart_count", getter=FlagGetter(type="function", function="get_cart_items_count")),
                Flag(name="cart_total", getter=FlagGetter(type="function", function="get_cart_total")),
            ],
            default_content=MessageContent(
                text=DynamicContent(
                    type="template",
                    template=ContentTemplate(
                        template="🛒 <b>Корзина</b>\n\nТоваров: {cart_count} шт.\nСумма: {cart_total:,} ₽",
                        flags=["cart_count", "cart_total"],
                    ),
                ),
            ),
            default_keyboard=Keyboard(
                buttons=[
                    [Button(text="✅ Оформить заказ", callback_action="checkout")],
                    [Button(text="🗑 Очистить корзину", callback_action="clear_cart")],
                    [Button(text="◀️ Назад", callback_action="go_back")],
                ],
            ),
            handlers=[
                Handler(
                    name="checkout",
                    event_type=EventType.CALLBACK,
                    conditions=["has_items_in_cart", "can_afford_cart"],
                    actions=[
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="checkout",
                            transition=TransitionType.EDIT_SMART,
                        ),
                    ],
                ),
                Handler(
                    name="clear_cart",
                    event_type=EventType.CALLBACK,
                    actions=[
                        ActionInstruction(
                            type=ActionType.CUSTOM,
                            function="action_clear_cart",
                        ),
                        ActionInstruction(
                            type=ActionType.SEND_MESSAGE,
                            content=MessageContent(text="🗑 Корзина очищена"),
                        ),
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="main_menu",
                        ),
                    ],
                ),
                Handler(
                    name="go_back",
                    event_type=EventType.CALLBACK,
                    actions=[ActionInstruction(type=ActionType.BACK)],
                ),
            ],
        ),
        # ====================================================================
        # Оформление заказа
        # ====================================================================
        Scene(
            id="checkout",
            name="Оформление",
            flags=[
                Flag(name="cart_total", getter=FlagGetter(type="function", function="get_cart_total")),
                Flag(name="balance", getter=FlagGetter(type="function", function="get_user_balance")),
            ],
            default_content=MessageContent(
                text=DynamicContent(
                    type="template",
                    template=ContentTemplate(
                        template="✅ <b>Оформление заказа</b>\n\n"
                        "Сумма: {cart_total:,} ₽\n"
                        "Ваш баланс: {balance:,} ₽\n\n"
                        "Подтвердите заказ:",
                        flags=["cart_total", "balance"],
                    ),
                ),
            ),
            default_keyboard=Keyboard(
                buttons=[
                    [Button(text="✅ Подтвердить", callback_action="confirm_order")],
                    [Button(text="❌ Отменить", callback_action="cancel_order")],
                ],
            ),
            handlers=[
                Handler(
                    name="confirm_order",
                    event_type=EventType.CALLBACK,
                    actions=[
                        ActionInstruction(
                            type=ActionType.CUSTOM,
                            function="action_process_order",
                        ),
                        ActionInstruction(
                            type=ActionType.SEND_MESSAGE,
                            content=MessageContent(text="🎉 Заказ успешно оформлен!"),
                        ),
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="main_menu",
                        ),
                    ],
                ),
                Handler(
                    name="cancel_order",
                    event_type=EventType.CALLBACK,
                    actions=[
                        ActionInstruction(
                            type=ActionType.GOTO_SCENE,
                            scene_id="main_menu",
                        ),
                    ],
                ),
            ],
        ),
        # Заглушки для других сцен
        Scene(
            id="orders",
            name="Мои заказы",
            default_content=MessageContent(text="📦 Список заказов пуст"),
            default_keyboard=Keyboard(
                buttons=[[Button(text="◀️ Назад", callback_action="go_back")]],
            ),
            handlers=[
                Handler(
                    name="go_back",
                    event_type=EventType.CALLBACK,
                    actions=[ActionInstruction(type=ActionType.BACK)],
                ),
            ],
        ),
        Scene(
            id="settings",
            name="Настройки",
            default_content=MessageContent(text="⚙️ Настройки"),
            default_keyboard=Keyboard(
                buttons=[[Button(text="◀️ Назад", callback_action="go_back")]],
            ),
            handlers=[
                Handler(
                    name="go_back",
                    event_type=EventType.CALLBACK,
                    actions=[ActionInstruction(type=ActionType.BACK)],
                ),
            ],
        ),
    ],
)


# ============================================================================
# Запуск
# ============================================================================


async def main() -> None:
    bot = Bot(token="5923234043:AAE0NIq1_dNVHVXrkcVG0sz-4mZWAQyQR28")
    storage = MemoryStorage()
    dp = Dispatcher(storage=storage)

    # Создаём SharedServices - общие компоненты для всех роутеров
    shared = SharedServices(
        navigation_storage=InMemoryNavigationStorage(),
        variable_repository=InMemoryVariableRepository(),
        event_bus=EventBus(),
        event_scheduler=InMemoryEventScheduler(event_callback=lambda e: None),
    )

    # Создаём UI роутер с новым API
    ui_router = UIRouterExecutor(schema=advanced_schema, shared=shared)

    # Регистрация функций
    ui_router.registry.getters.register("get_user_balance", get_user_balance)
    ui_router.registry.getters.register("get_cart_items_count", get_cart_items_count)
    ui_router.registry.getters.register("get_cart_total", get_cart_total)
    ui_router.registry.getters.register("get_product_name", get_product_name)
    ui_router.registry.getters.register("get_product_price", get_product_price)
    ui_router.registry.getters.register("get_product_stock", get_product_stock)

    ui_router.registry.conditions.register("is_user_vip", is_user_vip)
    ui_router.registry.conditions.register("has_items_in_cart", has_items_in_cart)
    ui_router.registry.conditions.register("can_afford_cart", can_afford_cart)

    ui_router.registry.validators.register("validate_quantity", validate_quantity)
    ui_router.registry.validators.register("validate_email", validate_email)

    ui_router.registry.actions.register("action_add_to_cart", action_add_to_cart)
    ui_router.registry.actions.register("action_clear_cart", action_clear_cart)
    ui_router.registry.actions.register("action_process_order", action_process_order)

    dp.include_router(ui_router.get_router())

    class CallbackDataLogMiddleware(BaseMiddleware):
        async def __call__(self, handler, event, data):
            print(event.data)
            return await handler(event, data)

    dp.callback_query.middleware(CallbackDataLogMiddleware())

    @dp.message(CommandStart())
    async def start(message: Message, **kwargs) -> None:
        # Сохраняем user_id для доступа в функциях

        await ui_router.start(message.from_user.id, message, **kwargs)

    print("Бот запущен!")
    await dp.start_polling(bot)


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