from typing import Annotated

from fastapi import Depends, Header, Query
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.config import settings
from app.core.database import get_session
from app.core.exceptions import UnauthorizedError
from app.models import Admin, User
from app.services import AuthService, UserService

SessionDep = Annotated[AsyncSession, Depends(get_session)]


async def get_bot(x_bot_token: Annotated[str | None, Header()] = None) -> bool:
    """Static shared-secret auth used by the Telegram bot process."""
    if not x_bot_token or x_bot_token != settings.bot_api_token:
        raise UnauthorizedError("invalid_bot_token")
    return True


BotDep = Annotated[bool, Depends(get_bot)]


async def get_current_admin(
    session: SessionDep, authorization: Annotated[str | None, Header()] = None
) -> Admin:
    if not authorization or not authorization.lower().startswith("bearer "):
        raise UnauthorizedError("missing_token")
    token = authorization.split(" ", 1)[1].strip()
    return await AuthService(session).current_admin(token)


AdminDep = Annotated[Admin, Depends(get_current_admin)]


async def get_current_user(
    session: SessionDep,
    _: BotDep,
    x_telegram_id: Annotated[int | None, Header()] = None,
    telegram_id: Annotated[int | None, Query()] = None,
) -> User:
    """Bot-facing endpoints identify the user by Telegram id."""
    value = x_telegram_id or telegram_id
    if not value:
        raise UnauthorizedError("missing_telegram_id")
    return await UserService(session).get_by_telegram_id(int(value))


UserDep = Annotated[User, Depends(get_current_user)]


async def get_admin_or_bot(
    session: SessionDep,
    authorization: Annotated[str | None, Header()] = None,
    x_bot_token: Annotated[str | None, Header()] = None,
) -> bool:
    """Read-only catalog endpoints are shared by the bot and the admin panel."""
    if x_bot_token and x_bot_token == settings.bot_api_token:
        return True
    if authorization and authorization.lower().startswith("bearer "):
        await AuthService(session).current_admin(authorization.split(" ", 1)[1].strip())
        return True
    raise UnauthorizedError("unauthorized")


ClientDep = Annotated[bool, Depends(get_admin_or_bot)]


class Pagination:
    def __init__(
        self,
        page: Annotated[int, Query(ge=1)] = 1,
        size: Annotated[int, Query(ge=1, le=100)] = 20,
        search: Annotated[str | None, Query()] = None,
    ) -> None:
        self.page = page
        self.size = size
        self.search = search


PageDep = Annotated[Pagination, Depends(Pagination)]
