"""Phase 14: API Key Pydantic schemas."""

from __future__ import annotations

from datetime import datetime
from typing import List, Optional
from uuid import UUID

from pydantic import BaseModel, Field, field_validator

from app.models.api_key import VALID_SCOPES


class ApiKeyCreate(BaseModel):
    name:        str             = Field(..., min_length=1, max_length=200)
    description: Optional[str]  = None
    scopes:      List[str]       = Field(default=["read"])
    expires_at:  Optional[datetime] = None

    @field_validator("scopes")
    @classmethod
    def validate_scopes(cls, v: list) -> list:
        invalid = set(v) - VALID_SCOPES
        if invalid:
            raise ValueError(f"Invalid scopes: {invalid}. Valid: {VALID_SCOPES}")
        if not v:
            raise ValueError("At least one scope is required")
        return v


class ApiKeyOut(BaseModel):
    """Safe representation — never exposes key_hash."""
    id:           UUID
    name:         str
    description:  Optional[str] = None
    key_prefix:   str
    user_id:      UUID
    scopes:       List[str]
    last_used_at: Optional[datetime] = None
    expires_at:   Optional[datetime] = None
    is_active:    bool
    created_at:   Optional[datetime] = None

    class Config:
        from_attributes = True


class ApiKeyCreated(ApiKeyOut):
    """Returned only once at creation — includes the raw key."""
    raw_key: str = Field(..., description="The full API key — shown only this once.")


class ApiKeyUpdate(BaseModel):
    name:        Optional[str]      = Field(None, min_length=1, max_length=200)
    description: Optional[str]      = None
    scopes:      Optional[List[str]] = None
    expires_at:  Optional[datetime]  = None
    is_active:   Optional[bool]      = None

    @field_validator("scopes")
    @classmethod
    def validate_scopes(cls, v: Optional[list]) -> Optional[list]:
        if v is None:
            return v
        invalid = set(v) - VALID_SCOPES
        if invalid:
            raise ValueError(f"Invalid scopes: {invalid}")
        return v
