"""Admin request/response schemas.""" from typing import Literal from pydantic import BaseModel, Field class UserManagement(BaseModel): """Schema for user access management.""" has_access: bool class PasswordReset(BaseModel): """Schema for resetting a user's password.""" new_password: str = Field(..., min_length=6) class CreateUserRequest(BaseModel): """Schema for admin-created user accounts.""" username: str = Field(..., min_length=1) password: str = Field(..., min_length=6) role: str = Field(default="user", pattern=r"^(user|admin)$") has_access: bool = False class RegistrationToggle(BaseModel): """Schema for toggling registration on/off.""" enabled: bool class SystemSettingUpdate(BaseModel): """Schema for updating a system setting.""" value: str = Field(..., min_length=1) class DataCleanupRequest(BaseModel): """Schema for data cleanup — delete records older than N days.""" older_than_days: int = Field(..., gt=0) class JobToggle(BaseModel): """Schema for enabling/disabling a scheduled job.""" enabled: bool class RecommendationConfigUpdate(BaseModel): high_confidence_threshold: float | None = Field(default=None, ge=0, le=100) moderate_confidence_threshold: float | None = Field(default=None, ge=0, le=100) confidence_diff_threshold: float | None = Field(default=None, ge=0, le=100) signal_alignment_weight: float | None = Field(default=None, ge=0, le=1) sr_strength_weight: float | None = Field(default=None, ge=0, le=1) momentum_technical_divergence_threshold: float | None = Field(default=None, ge=0, le=100) fundamental_technical_divergence_threshold: float | None = Field(default=None, ge=0, le=100) class TickerUniverseUpdate(BaseModel): universe: Literal["sp500", "nasdaq100", "nasdaq_all"] class ActivationConfigUpdate(BaseModel): """Activation gate: what counts as an actionable signal.""" min_momentum_percentile: float | None = Field(default=None, ge=0, le=100) min_rr: float | None = Field(default=None, ge=0) min_confidence: float | None = Field(default=None, ge=0, le=100) require_high_conviction: bool | None = None exclude_conflicts: bool | None = None exclude_neutral: bool | None = None class ScheduleConfigUpdate(BaseModel): """Cron schedule for the pipelines + fundamentals. Crons are 5-field (min hour dom month dow); timezone is an IANA name (e.g. Europe/Berlin).""" schedule_timezone: str | None = Field(default=None, max_length=64) schedule_daily_pipeline_cron: str | None = Field(default=None, max_length=120) schedule_intraday_pipeline_cron: str | None = Field(default=None, max_length=120) schedule_fundamentals_cron: str | None = Field(default=None, max_length=120) class SentimentConfigUpdate(BaseModel): """Runtime sentiment LLM config. api_key is write-only; omit/empty to keep the stored key.""" provider: Literal["openai", "gemini", "deepseek", "xai", "openai_compatible"] | None = None model: str | None = Field(default=None, max_length=100) api_key: str | None = Field(default=None, max_length=400) base_url: str | None = Field(default=None, max_length=300) class SentimentTestRequest(BaseModel): ticker: str = Field(default="AAPL", max_length=10) class AlertConfigUpdate(BaseModel): """Telegram alert config. bot_token is write-only; omit/empty to keep the stored token.""" enabled: bool | None = None bot_token: str | None = Field(default=None, max_length=200) telegram_chat_id: str | None = Field(default=None, max_length=64) qualified_enabled: bool | None = None sr_proximity_enabled: bool | None = None score_drop_enabled: bool | None = None digest_enabled: bool | None = None regime_quadrant_enabled: bool | None = None trade_closed_enabled: bool | None = None