# [DEF:backend.src.schemas.profile:Module]
#
# @TIER:      STANDARD
# @SEMANTICS: profile, schemas, pydantic, preferences, superset, lookup, security, git, ux
# @PURPOSE:   Defines API schemas for profile preference persistence, security read-only snapshot, and Superset account lookup.
# @LAYER:     API
# @RELATION:  DEPENDS_ON -> pydantic
#
# @INVARIANT: Schema shapes stay stable for profile UI states and backend preference contracts.

# [SECTION: IMPORTS]
from datetime import datetime
from typing import List, Literal, Optional
from pydantic import BaseModel, Field
# [/SECTION]


# [DEF:ProfilePermissionState:Class]
# @TIER: STANDARD
# @PURPOSE: Represents one permission badge state for profile read-only security view.
class ProfilePermissionState(BaseModel):
    key: str
    allowed: bool
# [/DEF:ProfilePermissionState:Class]


# [DEF:ProfileSecuritySummary:Class]
# @TIER: STANDARD
# @PURPOSE: Read-only security and access snapshot for current user.
class ProfileSecuritySummary(BaseModel):
    read_only: bool = True
    auth_source: Optional[str] = None
    current_role: Optional[str] = None
    role_source: Optional[str] = None
    roles: List[str] = Field(default_factory=list)
    permissions: List[ProfilePermissionState] = Field(default_factory=list)
# [/DEF:ProfileSecuritySummary:Class]


# [DEF:ProfilePreference:Class]
# @TIER: STANDARD
# @PURPOSE: Represents persisted profile preference for a single authenticated user.
class ProfilePreference(BaseModel):
    user_id: str
    superset_username: Optional[str] = None
    superset_username_normalized: Optional[str] = None
    show_only_my_dashboards: bool = False
    show_only_slug_dashboards: bool = True

    git_username: Optional[str] = None
    git_email: Optional[str] = None
    has_git_personal_access_token: bool = False
    git_personal_access_token_masked: Optional[str] = None

    start_page: Literal["dashboards", "datasets", "reports"] = "dashboards"
    auto_open_task_drawer: bool = True
    dashboards_table_density: Literal["compact", "comfortable"] = "comfortable"

    telegram_id: Optional[str] = None
    email_address: Optional[str] = None
    notify_on_fail: bool = True

    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True
# [/DEF:ProfilePreference:Class]


# [DEF:ProfilePreferenceUpdateRequest:Class]
# @TIER: STANDARD
# @PURPOSE: Request payload for updating current user's profile settings.
class ProfilePreferenceUpdateRequest(BaseModel):
    superset_username: Optional[str] = Field(
        default=None,
        description="Apache Superset username bound to current user profile.",
    )
    show_only_my_dashboards: Optional[bool] = Field(
        default=None,
        description='When true, "/dashboards" can auto-apply profile filter in main context.',
    )
    show_only_slug_dashboards: Optional[bool] = Field(
        default=None,
        description='When true, "/dashboards" hides dashboards without slug by default.',
    )
    git_username: Optional[str] = Field(
        default=None,
        description="Git author username used for commit signature.",
    )
    git_email: Optional[str] = Field(
        default=None,
        description="Git author email used for commit signature.",
    )
    git_personal_access_token: Optional[str] = Field(
        default=None,
        description="Personal Access Token value. Empty string clears existing token.",
    )
    start_page: Optional[
        Literal["dashboards", "datasets", "reports", "reports-logs"]
    ] = Field(
        default=None,
        description="Preferred start page after login.",
    )
    auto_open_task_drawer: Optional[bool] = Field(
        default=None,
        description="Auto-open task drawer when long-running tasks start.",
    )
    dashboards_table_density: Optional[
        Literal["compact", "comfortable", "free"]
    ] = Field(
        default=None,
        description="Preferred table density for dashboard listings.",
    )
    telegram_id: Optional[str] = Field(
        default=None,
        description="Telegram ID for notifications.",
    )
    email_address: Optional[str] = Field(
        default=None,
        description="Email address for notifications (overrides system email).",
    )
    notify_on_fail: Optional[bool] = Field(
        default=None,
        description="Whether to send notifications on validation failure.",
    )
# [/DEF:ProfilePreferenceUpdateRequest:Class]


# [DEF:ProfilePreferenceResponse:Class]
# @TIER: STANDARD
# @PURPOSE: Response envelope for profile preference read/update endpoints.
class ProfilePreferenceResponse(BaseModel):
    status: Literal["success", "error"] = "success"
    message: Optional[str] = None
    validation_errors: List[str] = Field(default_factory=list)
    preference: ProfilePreference
    security: ProfileSecuritySummary = Field(default_factory=ProfileSecuritySummary)
# [/DEF:ProfilePreferenceResponse:Class]


# [DEF:SupersetAccountLookupRequest:Class]
# @TIER: STANDARD
# @PURPOSE: Query contract for Superset account lookup by selected environment.
class SupersetAccountLookupRequest(BaseModel):
    environment_id: str
    search: Optional[str] = None
    page_index: int = Field(default=0, ge=0)
    page_size: int = Field(default=20, ge=1, le=100)
    sort_column: str = Field(default="username")
    sort_order: str = Field(default="desc")
# [/DEF:SupersetAccountLookupRequest:Class]


# [DEF:SupersetAccountCandidate:Class]
# @TIER: STANDARD
# @PURPOSE: Canonical account candidate projected from Superset users payload.
class SupersetAccountCandidate(BaseModel):
    environment_id: str
    username: str
    display_name: Optional[str] = None
    email: Optional[str] = None
    is_active: Optional[bool] = None
# [/DEF:SupersetAccountCandidate:Class]


# [DEF:SupersetAccountLookupResponse:Class]
# @TIER: STANDARD
# @PURPOSE: Response envelope for Superset account lookup (success or degraded mode).
class SupersetAccountLookupResponse(BaseModel):
    status: Literal["success", "degraded"]
    environment_id: str
    page_index: int = Field(ge=0)
    page_size: int = Field(ge=1, le=100)
    total: int = Field(ge=0)
    warning: Optional[str] = None
    items: List[SupersetAccountCandidate] = Field(default_factory=list)
# [/DEF:SupersetAccountLookupResponse:Class]

# [/DEF:backend.src.schemas.profile:Module]
