"""Dependencyهای مشترک API."""
from __future__ import annotations

from dataclasses import dataclass
from uuid import UUID

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

from app.core.database import get_db
from app.core.security import get_current_user, get_optional_user
from app.models.user import User
from app.services.user_service import UserService
from shared.exceptions import TenantNotResolvedError
from shared.pagination import PaginationParams
from shared.security import CurrentUser

__all__ = [
    "get_db",
    "get_pagination",
    "require_tenant",
    "get_current_core_user",
    "get_optional_core_user",
    "TenantResolution",
    "get_tenant_resolution",
    "AsyncSession",
]


def get_pagination(
    page: int = Query(default=1, ge=1),
    page_size: int = Query(default=20, ge=1, le=100),
) -> PaginationParams:
    return PaginationParams(page=page, page_size=page_size)


def require_tenant(request: Request) -> UUID:
    """اطمینان از resolve شدن tenant برای endpointهای tenant-aware.

    این dependency مقدار tenant_id را از request.state (که middleware پر
    کرده) می‌خواند و در نبود آن خطای مناسب برمی‌گرداند.
    """
    tenant_id = getattr(request.state, "tenant_id", None)
    if tenant_id is None:
        raise TenantNotResolvedError(
            "tenant قابل تشخیص نبود. یکی از هدرهای X-Tenant-ID یا "
            "X-Tenant-Slug را ارسال کنید یا از دامنه معتبر استفاده نمایید."
        )
    return tenant_id


async def get_current_core_user(
    db: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(get_current_user),
) -> User:
    """کاربر Core متناظر با هویت جاری (JWT محلی یا Keycloak SSO).

    برای endpointهای onboarding/tenant-context استفاده می‌شود که نیاز به
    رکورد واقعی users دارند (نه فقط claims توکن).
    """
    return await UserService(db).resolve_current(user)


async def get_optional_core_user(
    db: AsyncSession = Depends(get_db),
    user: CurrentUser | None = Depends(get_optional_user),
) -> User | None:
    if user is None:
        return None
    try:
        return await UserService(db).resolve_current(user)
    except Exception:  # noqa: BLE001 - عدم لینک بودن یعنی کاربر Core ندارد
        return None


@dataclass(frozen=True)
class TenantResolution:
    """نتیجه تشخیص tenant جاری request (هدر/دامنه/tenant انتخابی کاربر)."""

    tenant_id: UUID | None
    tenant_slug: str | None
    source: str  # "header" | "domain" | "user_default" | "none"


async def get_tenant_resolution(
    request: Request,
    core_user: User | None = Depends(get_optional_core_user),
) -> TenantResolution:
    """تشخیص tenant جاری: اول هدر/دامنه (middleware)، سپس tenant انتخابی کاربر.

    این dependency جایگزین middleware نمی‌شود و endpointهای platform-admin
    فعلی را تحت تأثیر قرار نمی‌دهد (صرفاً یک ابزار کمکی جدید است).
    """
    tenant_id = getattr(request.state, "tenant_id", None)
    tenant_slug = getattr(request.state, "tenant_slug", None)
    if tenant_id is not None:
        return TenantResolution(tenant_id=tenant_id, tenant_slug=tenant_slug, source="header")

    if core_user is not None and core_user.current_tenant_id is not None:
        return TenantResolution(
            tenant_id=core_user.current_tenant_id,
            tenant_slug=None,
            source="user_default",
        )

    return TenantResolution(tenant_id=None, tenant_slug=None, source="none")
