from __future__ import annotations from datetime import date, datetime, time from typing import Literal from pydantic import BaseModel, Field from backend.features.accounts.service import PROFILE_PRIVACY_NOTICE class CredentialsInput(BaseModel): username: str password: str class PasswordChangeInput(BaseModel): current_password: str new_password: str confirmation: str class AccountIdentityResponse(BaseModel): id: int username: str is_admin: bool membership_status: str membership_active: bool smart_access: bool badges: list[str] class AuthResponse(BaseModel): account: AccountIdentityResponse csrf_token: str class MessageResponse(BaseModel): message: str class BirthProfileInput(BaseModel): birth_date: date birth_time: time gender: Literal["male", "female"] class BirthProfileResponse(BaseModel): configured: bool birth_date: date | None = None birth_time: time | None = None gender: str | None = None updated_at: datetime | None = None privacy_notice: str = PROFILE_PRIVACY_NOTICE class MembershipStatusResponse(BaseModel): status: str active: bool is_permanent: bool expires_at: datetime | None remaining_days: int | None daily_limit: int used_today: int remaining_today: int | None quota_exempt: bool smart_access: bool description: str = "开通会员后可使用智能选股、问师、问天、复盘助手等智能功能。" usage_package_available: bool = False class MembershipAdminResponse(BaseModel): user_id: int username: str is_admin: bool membership: MembershipStatusResponse class MembershipUpdateInput(BaseModel): action: Literal["activate", "disable", "set_limit"] duration: Literal["1_month", "3_months", "12_months", "3_years", "permanent"] | None = None daily_limit: int | None = Field(default=None, ge=1, le=1000) class CredentialStatusResponse(BaseModel): name: str configured: bool updated_at: datetime | None class CredentialInput(BaseModel): value: str = Field(min_length=1, max_length=4096) class ModelInput(BaseModel): display_name: str = Field(min_length=1, max_length=40) base_url: str = Field(min_length=1, max_length=2048) model_identifier: str = Field(min_length=1, max_length=128) api_key: str = Field(min_length=1, max_length=4096) class ModelUpdateInput(BaseModel): display_name: str = Field(min_length=1, max_length=40) base_url: str = Field(min_length=1, max_length=2048) model_identifier: str = Field(min_length=1, max_length=128) api_key: str | None = Field(default=None, min_length=1, max_length=4096) class ModelPoolItemResponse(BaseModel): id: int display_name: str base_url: str model_identifier: str has_api_key: bool is_primary: bool is_fallback: bool updated_at: datetime class ModelSelectionInput(BaseModel): primary_model_id: int = Field(ge=1) fallback_model_id: int | None = Field(default=None, ge=1) class ModelTestResponse(BaseModel): connected: bool message: str duration_ms: int = Field(ge=0) request_id: str