"""project_auth domain — Pydantic request/response schemas."""
from __future__ import annotations

from datetime import datetime
from typing import Annotated, List, Literal, Optional, Union
from uuid import UUID

from pydantic import BaseModel, Field

from src.domain.project_auth.models import AuthAssignmentTier, AuthKeyStatus, AuthRoleCreator


# ---------------------------------------------------------------------------
# Auth Config
# ---------------------------------------------------------------------------

AuthProvider = Literal["email", "magic_link", "google"]
AuthMethod = Literal["password", "passwordless", "oidc", "ldap"]
GoogleOAuthMode = Literal["platform", "custom"]


class UpsertAuthConfigRequest(BaseModel):
    """Create or update auth configuration for a project.

    Pass only fields you want to change when updating.
    To enable Google BYOC, set google_oauth_mode="custom" and supply credentials.
    """

    enabled: Optional[bool] = None
    providers: Optional[List[AuthProvider]] = None
    auth_methods: Optional[List[AuthMethod]] = None
    identity_channels: Optional[List[str]] = None
    auth_connections: Optional[List[dict]] = None
    audiences: Optional[List[str]] = None
    mfa_methods: Optional[List[str]] = None
    require_mfa: Optional[bool] = None
    allow_signup: Optional[bool] = None
    require_email_verify: Optional[bool] = None
    google_oauth_mode: Optional[GoogleOAuthMode] = None
    google_client_id: Optional[str] = Field(None, description="BYOC mode only — stored encrypted")
    google_client_secret: Optional[str] = Field(None, description="BYOC mode only — stored encrypted")
    access_token_ttl_seconds: Optional[int] = Field(None, ge=300, le=86400)
    refresh_token_ttl_days: Optional[int] = Field(None, ge=1, le=365)
    password_min_length: Optional[int] = Field(None, ge=6, le=128)


class AuthConfigResponse(BaseModel):
    project_id: UUID
    enabled: bool
    providers: List[str]
    auth_methods: List[str]
    identity_channels: List[str]
    auth_connections: List[dict]
    audiences: List[str]
    mfa_methods: List[str]
    require_mfa: bool
    allow_signup: bool
    require_email_verify: bool
    google_oauth_mode: Optional[str] = None
    google_client_id_set: bool = Field(
        False, description="True when BYOC client_id is configured"
    )
    access_token_ttl_seconds: int
    refresh_token_ttl_days: int
    password_min_length: int
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


# ---------------------------------------------------------------------------
# Auth Keys
# ---------------------------------------------------------------------------


class AuthKeyResponse(BaseModel):
    id: UUID
    project_id: UUID
    key_id: str
    status: AuthKeyStatus
    public_key_pem: str
    created_at: datetime
    rotated_at: Optional[datetime] = None

    model_config = {"from_attributes": True}


class RotateKeyResponse(BaseModel):
    """Returned after rotating — includes the new active key."""

    new_key: AuthKeyResponse
    previous_key_id: Optional[str] = Field(None, description="kid of the key just rotated out")


# ---------------------------------------------------------------------------
# Auth Roles
# ---------------------------------------------------------------------------


class CreateAuthRoleRequest(BaseModel):
    name: str = Field(..., min_length=1, max_length=64, pattern=r"^[a-z][a-z0-9_-]*$")
    description: Optional[str] = None
    is_default: bool = False
    permissions: List[str] = Field(default_factory=list)
    assignment_tier: AuthAssignmentTier


class UpdateAuthRoleRequest(BaseModel):
    description: Optional[str] = None
    is_default: Optional[bool] = None
    permissions: Optional[List[str]] = None
    assignment_tier: Optional[AuthAssignmentTier] = None


class AuthRoleResponse(BaseModel):
    id: UUID
    project_id: UUID
    name: str
    description: Optional[str] = None
    is_default: bool
    permissions: List[str]
    assignment_tier: Optional[AuthAssignmentTier] = None
    protected: bool = False
    created_by: AuthRoleCreator
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


# ---------------------------------------------------------------------------
# Revocation
# ---------------------------------------------------------------------------


class RevokeAppUserRequest(BaseModel):
    """Revoke an app user's access — pushes to Cloud KV and marks them in Cloud's audit log."""

    user_id: str = Field(..., description="Cloud app user ID (e.g. usr_abc123)")
    reason: str = Field("admin_revoke", max_length=64)
