import uuid

from fastapi import APIRouter

from app.api.deps import AdminDep, BotDep, PageDep, SessionDep, UserDep
from app.api.serializers import dump, dump_list
from app.core.response import paginated, success
from app.schemas import (
    BankCardOut,
    OrderOut,
    TelegramUserIn,
    TransactionOut,
    UserOut,
    UserUpdate,
    WalletAdjust,
    WalletOut,
)
from app.services import (
    MessageService,
    OrderService,
    SettingsService,
    SupportService,
    UserService,
    WalletService,
)

router = APIRouter(tags=["users"])


@router.post("/telegram/start")
async def telegram_start(payload: TelegramUserIn, session: SessionDep, _: BotDep) -> dict:
    """Register (or refresh) the Telegram user and return everything /start needs."""
    user, is_new = await UserService(session).get_or_create(**payload.model_dump())
    balance = await WalletService(session).balance(user.id)
    return success(
        {
            "user": dump(UserOut, user),
            "balance": str(balance),
            "is_new": is_new,
            "menu": await MessageService(session).menu(),
            "settings": await SettingsService(session).public(),
        }
    )


@router.get("/users/me")
async def get_me(user: UserDep, session: SessionDep) -> dict:
    wallet = await WalletService(session).get_wallet(user.id)
    orders = await OrderService(session).recent(user.id, limit=5)
    return success(
        {
            "user": dump(UserOut, user),
            "wallet": dump(WalletOut, wallet),
            "recent_orders": dump_list(OrderOut, orders),
        }
    )


@router.get("/users")
async def list_users(session: SessionDep, _: AdminDep, page_params: PageDep) -> dict:
    users, total = await UserService(session).search(
        page_params.page, page_params.size, page_params.search
    )
    return success(
        paginated(dump_list(UserOut, users), total, page_params.page, page_params.size)
    )


@router.get("/users/{user_id}")
async def get_user(user_id: uuid.UUID, session: SessionDep, _: AdminDep) -> dict:
    service = UserService(session)
    user = await service.get(user_id)
    wallet = await WalletService(session).get_wallet(user.id)
    orders, _total = await OrderService(session).search(1, 20, user_id=user.id)
    cards = await SupportService(session).list_cards(user.id)
    return success(
        {
            "user": dump(UserOut, user),
            "wallet": dump(WalletOut, wallet),
            "orders": dump_list(OrderOut, orders),
            "bank_cards": dump_list(BankCardOut, cards),
        }
    )


@router.put("/users/{user_id}")
async def update_user(
    user_id: uuid.UUID, payload: UserUpdate, session: SessionDep, _: AdminDep
) -> dict:
    service = UserService(session)
    user = await service.get(user_id)
    updated = await service.update_profile(user, **payload.model_dump(exclude_unset=True))
    return success(dump(UserOut, updated), "updated")


# -- wallet ---------------------------------------------------------
@router.get("/wallet")
async def get_wallet(user: UserDep, session: SessionDep) -> dict:
    wallet = await WalletService(session).get_wallet(user.id)
    return success(dump(WalletOut, wallet))


@router.get("/wallet/transactions")
async def wallet_transactions(user: UserDep, session: SessionDep, page_params: PageDep) -> dict:
    items, total = await WalletService(session).history(user.id, page_params.page, page_params.size)
    return success(
        paginated(dump_list(TransactionOut, items), total, page_params.page, page_params.size)
    )


@router.get("/admin/wallet/{user_id}/transactions")
async def admin_wallet_transactions(
    user_id: uuid.UUID, session: SessionDep, _: AdminDep, page_params: PageDep
) -> dict:
    items, total = await WalletService(session).history(user_id, page_params.page, page_params.size)
    return success(
        paginated(dump_list(TransactionOut, items), total, page_params.page, page_params.size)
    )


@router.post("/admin/wallet/adjust")
async def adjust_wallet(payload: WalletAdjust, session: SessionDep, _: AdminDep) -> dict:
    transaction = await WalletService(session).adjust(
        payload.user_id, payload.amount, payload.description or "admin adjustment"
    )
    return success(dump(TransactionOut, transaction), "wallet_adjusted")
