"""
Pydantic schemas cho Memos-style backend.

Hiện tại chỉ là skeleton để API không bị lỗi import.
Sau này có thể map chi tiết 1-1 với proto/api/v1/*.proto của memos.
"""

from __future__ import annotations

from typing import Any, List, Optional

from pydantic import BaseModel, ConfigDict, EmailStr, Field
from pydantic.aliases import AliasChoices


class InstanceInfo(BaseModel):
    mode: Optional[str] = None
    version: Optional[str] = None


class InstanceUpdate(BaseModel):
    data_dir: Optional[str] = None


class InstanceSetting(BaseModel):
    # Stub fields for Connect compatibility
    allow_signup: bool = True
    disallow_login: bool = False
    additional_setting: dict | None = None


class AuthSignInRequest(BaseModel):
    """
    Accept both REST-style and Connect/proto-like payloads.

    REST (legacy stub):
      { "email": "...", "password": "..." }
    Connect/proto-like (from web SignInRequest):
      { "credentials": { "case": "passwordCredentials", "value": { "username": "...", "password": "..." } } }
    """

    # REST-style
    email: Optional[EmailStr] = None
    password: Optional[str] = None

    # Connect/proto-like
    credentials: Optional[dict[str, Any]] = None


class AuthSignInResponse(BaseModel):
    # Frontend expects SignInResponse.accessToken (proto field access_token = 2).
    # Accept both snake_case and camelCase on input; always serialize camelCase.
    accessToken: str = Field(validation_alias=AliasChoices("accessToken", "access_token"))
    tokenType: str = Field(default="bearer", validation_alias=AliasChoices("tokenType", "token_type"))

    model_config = ConfigDict(populate_by_name=True)


class AuthSignUpRequest(BaseModel):
    email: EmailStr
    password: str


class AuthSignUpResponse(BaseModel):
    user_id: int


class AuthMeResponse(BaseModel):
    id: int
    email: EmailStr


class UserBase(BaseModel):
    # Connect client có thể không gửi email khi hit stub; để optional để tránh 422.
    email: Optional[EmailStr] = None


class UserCreate(UserBase):
    # Connect/proto client có thể gửi payload khác format REST, nên để optional để tránh 422.
    password: str = ""


class UserUpdate(BaseModel):
    email: Optional[EmailStr] = None
    nickname: Optional[str] = None


class UserResponse(UserBase):
    id: int
    nickname: Optional[str] = None


class MemoBase(BaseModel):
    content: str
    visibility: Optional[str] = "PRIVATE"
    tags: List[str] = []


class MemoCreate(MemoBase):
    pass


class MemoUpdate(BaseModel):
    content: Optional[str] = None
    visibility: Optional[str] = None
    tags: Optional[List[str]] = None


class MemoResponse(MemoBase):
    id: int
    creator_id: str  # Clerk user ID (e.g., "user_2abc123..." or "anonymous")
    create_time: Optional[str] = None
    update_time: Optional[str] = None
    display_time: Optional[str] = None

    model_config = ConfigDict(populate_by_name=True)


class MemoEmbeddingCreate(BaseModel):
    memoId: int
    content: str
    tags: List[str] = []
    dateKey: Optional[str] = None
    embedding: List[float]
    model: Optional[str] = "stub-embedding"


class MemoEmbeddingResponse(BaseModel):
    id: int
    memoId: int
    content: str
    tags: List[str]
    dateKey: Optional[str] = None
    dim: int
    model: str
    score: Optional[float] = None


class AttachmentResponse(BaseModel):
    id: int
    filename: str
    url: str


class ShortcutCreate(BaseModel):
    name: str
    filter: str


class ShortcutUpdate(BaseModel):
    name: Optional[str] = None
    filter: Optional[str] = None


class ShortcutResponse(BaseModel):
    id: int
    name: str
    filter: str


class ListShortcutsResponse(BaseModel):
    shortcuts: List[ShortcutResponse] = []


class ActivityResponse(BaseModel):
    id: int
    type: str
    description: Optional[str] = None


class IdentityProviderCreate(BaseModel):
    name: str
    type: str


class IdentityProviderUpdate(BaseModel):
    name: Optional[str] = None
    config: Optional[dict] = None


class IdentityProviderResponse(BaseModel):
    id: int
    name: str
    type: str


