from __future__ import annotations from datetime import datetime from typing import Any, Literal from pydantic import BaseModel, ConfigDict, Field from govoplan_core.api.v1.schemas import DeltaDeletedItem, NavigationPreferencesPayload from govoplan_core.i18n import REFERENCE_LANGUAGE_CODE class TenantAdminItem(BaseModel): id: str slug: str = Field(min_length=1, max_length=100) name: str = Field(min_length=1, max_length=255) description: str | None = None default_locale: str = Field( default=REFERENCE_LANGUAGE_CODE, min_length=1, max_length=20, ) settings: dict[str, Any] = Field(default_factory=dict) allow_custom_groups: bool | None = None allow_custom_roles: bool | None = None allow_api_keys: bool | None = None effective_governance: dict[str, bool] = Field(default_factory=dict) is_active: bool counts: dict[str, int] = Field(default_factory=dict) created_at: datetime updated_at: datetime class TenantListResponse(BaseModel): tenants: list[TenantAdminItem] total: int = 0 page: int = 1 page_size: int = 100 pages: int = 1 class TenantListDeltaResponse(TenantListResponse): tenants: list[TenantAdminItem] = Field(default_factory=list) deleted: list[DeltaDeletedItem] = Field(default_factory=list) watermark: str | None = None has_more: bool = False full: bool = False class TenantOwnerCandidate(BaseModel): account_id: str email: str display_name: str | None = None class TenantOwnerCandidateListResponse(BaseModel): accounts: list[TenantOwnerCandidate] class TenantCreateRequest(BaseModel): model_config = ConfigDict(extra="forbid") slug: str name: str owner_account_id: str | None = None description: str | None = None default_locale: str = REFERENCE_LANGUAGE_CODE settings: dict[str, Any] = Field(default_factory=dict) allow_custom_groups: bool | None = None allow_custom_roles: bool | None = None allow_api_keys: bool | None = None class TenantUpdateRequest(BaseModel): model_config = ConfigDict(extra="forbid") name: str | None = Field(default=None, min_length=1, max_length=255) description: str | None = None default_locale: str | None = Field(default=None, min_length=1, max_length=20) settings: dict[str, Any] | None = None allow_custom_groups: bool | None = None allow_custom_roles: bool | None = None allow_api_keys: bool | None = None is_active: bool | None = None class TenantLifecycleIssue(BaseModel): severity: Literal["blocker", "warning", "info"] code: str message: str module_id: str | None = None details: dict[str, Any] = Field(default_factory=dict) class TenantDeletionPlanResponse(BaseModel): tenant_id: str action: Literal["retire", "destroy"] = "retire" allowed: bool destructive_supported: bool = False issues: list[TenantLifecycleIssue] = Field(default_factory=list) counts: dict[str, int] = Field(default_factory=dict) class TenantDeleteRequest(BaseModel): model_config = ConfigDict(extra="forbid") mode: Literal["retire", "destroy"] = "retire" reason: str | None = None class TenantLifecycleResponse(BaseModel): item: TenantAdminItem plan: TenantDeletionPlanResponse class TenantContextSwitchRequest(BaseModel): model_config = ConfigDict(extra="forbid") tenant_id: str class TenantContextSwitchResponse(BaseModel): account_id: str membership_id: str tenant_id: str session_id: str | None = None class TenantSettingsItem(BaseModel): id: str slug: str name: str default_locale: str = Field( default=REFERENCE_LANGUAGE_CODE, min_length=1, max_length=20, ) available_languages: list[dict[str, Any]] = Field(default_factory=list) system_enabled_language_codes: list[str] = Field(default_factory=list) enabled_language_codes: list[str] = Field(default_factory=list) navigation: NavigationPreferencesPayload | None = None appearance_palette: Literal["default", "civic_blue", "forest", "plum"] | None = None appearance_palette_locked: bool = False system_appearance_palette: Literal["default", "civic_blue", "forest", "plum"] = "default" system_appearance_palette_locked: bool = False effective_appearance_palette: Literal["default", "civic_blue", "forest", "plum"] = "default" effective_appearance_source: Literal["tenant", "system", "tenant_lock", "system_lock"] = "system" appearance_custom_overrides_allowed: bool | None = None system_appearance_custom_overrides_allowed: bool = False effective_appearance_custom_overrides_allowed: bool = False settings: dict[str, Any] = Field(default_factory=dict) class TenantSettingsDeltaResponse(BaseModel): item: TenantSettingsItem | None = None sections: dict[str, Any] = Field(default_factory=dict) changed_sections: list[str] = Field(default_factory=list) deleted: list[DeltaDeletedItem] = Field(default_factory=list) watermark: str | None = None has_more: bool = False full: bool = False class TenantSettingsUpdateRequest(BaseModel): model_config = ConfigDict(extra="forbid") default_locale: str = Field(min_length=1, max_length=20) enabled_language_codes: list[str] | None = None navigation: NavigationPreferencesPayload | None = None appearance_palette: Literal["default", "civic_blue", "forest", "plum"] | None = None appearance_palette_locked: bool | None = None appearance_custom_overrides_allowed: bool | None = None