# #region ProfileSchemas [C:5] [TYPE Module] [SEMANTICS pydantic, profile, schema, superset, profile-permission-state]
#
# @BRIEF Defines API schemas for profile preference persistence, security read-only snapshot, and Superset account lookup.
# @LAYER API
# @RELATION DEPENDS_ON -> [EXT:Library:pydantic]
#
# @INVARIANT  Schema shapes stay stable for profile UI states and backend preference contracts.
# @DATA_CONTRACT  ProfilePayload -> ProfileSchema

from datetime import datetime
from typing import Literal

from pydantic import BaseModel, ConfigDict, Field


# #region ProfilePermissionState [C:3] [TYPE Class]
# @BRIEF Represents one permission badge state for profile read-only security view.
# @RELATION DEPENDS_ON -> ProfileSchemas
class ProfilePermissionState(BaseModel):
    key: str
    allowed: bool


# #endregion ProfilePermissionState


# #region ProfileSecuritySummary [C:3] [TYPE Class]
# @BRIEF Read-only security and access snapshot for current user.
# @RELATION DEPENDS_ON -> ProfileSchemas
class ProfileSecuritySummary(BaseModel):
    read_only: bool = True
    auth_source: str | None = None
    current_role: str | None = None
    role_source: str | None = None
    roles: list[str] = Field(default_factory=list)
    permissions: list[ProfilePermissionState] = Field(default_factory=list)


# #endregion ProfileSecuritySummary


# #region ProfilePreference [C:3] [TYPE Class]
# @BRIEF Represents persisted profile preference for a single authenticated user.
# @RELATION DEPENDS_ON -> ProfileSchemas
class ProfilePreference(BaseModel):
    user_id: str
    superset_username: str | None = None
    superset_username_normalized: str | None = None
    show_only_my_dashboards: bool = False
    show_only_slug_dashboards: bool = True

    git_username: str | None = None
    git_email: str | None = None
    has_git_personal_access_token: bool = False
    git_personal_access_token_masked: str | None = None

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

    telegram_id: str | None = None
    email_address: str | None = None
    notify_on_fail: bool = True

    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


# #endregion ProfilePreference


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


# #endregion ProfilePreferenceUpdateRequest


# #region ProfilePreferenceResponse [C:3] [TYPE Class]
# @BRIEF Response envelope for profile preference read/update endpoints.
# @RELATION DEPENDS_ON -> ProfileSchemas
class ProfilePreferenceResponse(BaseModel):
    status: Literal["success", "error"] = "success"
    message: str | None = None
    validation_errors: list[str] = Field(default_factory=list)
    preference: ProfilePreference
    security: ProfileSecuritySummary = Field(default_factory=ProfileSecuritySummary)


# #endregion ProfilePreferenceResponse


# #region SupersetAccountLookupRequest [C:3] [TYPE Class]
# @BRIEF Query contract for Superset account lookup by selected environment.
# @RELATION DEPENDS_ON -> ProfileSchemas
class SupersetAccountLookupRequest(BaseModel):
    environment_id: str
    search: str | None = 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")


# #endregion SupersetAccountLookupRequest


# #region SupersetAccountCandidate [C:3] [TYPE Class]
# @BRIEF Canonical account candidate projected from Superset users payload.
# @RELATION DEPENDS_ON -> ProfileSchemas
class SupersetAccountCandidate(BaseModel):
    environment_id: str
    username: str
    display_name: str | None = None
    email: str | None = None
    is_active: bool | None = None


# #endregion SupersetAccountCandidate


# #region SupersetAccountLookupResponse [C:3] [TYPE Class]
# @BRIEF Response envelope for Superset account lookup (success or degraded mode).
# @RELATION DEPENDS_ON -> ProfileSchemas
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: str | None = None
    items: list[SupersetAccountCandidate] = Field(default_factory=list)


# #endregion SupersetAccountLookupResponse

# #endregion ProfileSchemas
