"""
Pydantic v2 models for authentication flows.

CallerContext is the unified return type of gateway_auth — all three caller
types are represented as discriminated union variants keyed on caller_type.
This lets route handlers check `caller.caller_type` and get full type safety.
"""

from __future__ import annotations

from typing import Annotated, Literal

from pydantic import BaseModel, EmailStr, Field, field_validator


# ---------------------------------------------------------------------------
# Request models
# ---------------------------------------------------------------------------

class LoginRequest(BaseModel):
    email: EmailStr
    password: str = Field(..., min_length=1)

    @field_validator("email")
    @classmethod
    def normalise_email(cls, v: str) -> str:
        """Lowercase + strip whitespace before any comparison or storage."""
        return v.lower().strip()


# ---------------------------------------------------------------------------
# Response models
# ---------------------------------------------------------------------------

class TokenResponse(BaseModel):
    """Returned by POST /auth/login."""
    access_token: str
    token_type: Literal["bearer"] = "bearer"
    expires_in: int = Field(..., description="Seconds until access token expires")


class RefreshResponse(BaseModel):
    """Returned by POST /auth/refresh."""
    access_token: str
    token_type: Literal["bearer"] = "bearer"
    expires_in: int


class LogoutResponse(BaseModel):
    """Returned by POST /auth/logout."""
    message: str = "Logged out successfully"


# ---------------------------------------------------------------------------
# Caller context — unified identity objects returned by gateway_auth
#
# Discriminated union on `caller_type` field lets mypy + FastAPI know exactly
# which fields are available after an isinstance() or caller_type check.
# ---------------------------------------------------------------------------

class UserCallerContext(BaseModel):
    """Identity resolved from a valid JWT access token."""
    caller_type: Literal["user"] = "user"
    sub: str    # user UUID as string
    role: str   # viewer | analyst | admin


class ApiKeyCallerContext(BaseModel):
    """Identity resolved from HMAC-signed request headers."""
    caller_type: Literal["api_key"] = "api_key"
    key_id: str
    service_name: str
    scopes: list[str]
    rate_limit: int


class CronCallerContext(BaseModel):
    """Identity resolved from a static internal ApiKey header."""
    caller_type: Literal["cron"] = "cron"
    key_id: str
    service_name: str
    scopes: list[str]


# Annotated union with discriminator — Pydantic v2 / FastAPI can parse it
CallerContext = Annotated[
    UserCallerContext | ApiKeyCallerContext | CronCallerContext,
    Field(discriminator="caller_type"),
]
