# app/modules/tenancy/schemas/team.py
"""
Pydantic schemas for store team management.

This module defines request/response schemas for:
- Team member listing
- Team member invitation
- Team member updates
- Role management
"""

from datetime import datetime

from pydantic import BaseModel, EmailStr, Field, field_validator

# ============================================================================
# Role Schemas
# ============================================================================


class RoleBase(BaseModel):
    """Base role schema."""

    name: str = Field(..., min_length=1, max_length=100, description="Role name")
    permissions: list[str] = Field(
        default_factory=list, description="List of permission strings"
    )


class RoleCreate(RoleBase):
    """Schema for creating a role."""


class RoleUpdate(BaseModel):
    """Schema for updating a role."""

    name: str | None = Field(None, min_length=1, max_length=100)
    permissions: list[str] | None = None


class RoleResponse(RoleBase):
    """Schema for role response."""

    id: int
    store_id: int
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True  # Pydantic v2 (use orm_mode = True for v1)


class RoleListResponse(BaseModel):
    """Schema for role list response."""

    roles: list[RoleResponse]
    total: int


# ============================================================================
# Team Member Schemas
# ============================================================================


class TeamMemberBase(BaseModel):
    """Base team member schema."""

    email: EmailStr = Field(..., description="Team member email address")
    first_name: str | None = Field(None, max_length=100)
    last_name: str | None = Field(None, max_length=100)


class TeamMemberInvite(TeamMemberBase):
    """Schema for inviting a team member."""

    role_id: int | None = Field(
        None, description="Role ID to assign (for preset roles)"
    )
    role_name: str | None = Field(
        None, description="Role name (manager, staff, support, etc.)"
    )
    custom_permissions: list[str] | None = Field(
        None, description="Custom permissions (overrides role preset)"
    )

    @field_validator("role_name")
    @classmethod
    def validate_role_name(cls, v):
        """Validate role name is in allowed presets."""
        if v is not None:
            allowed_roles = ["manager", "staff", "support", "viewer", "marketing"]
            if v.lower() not in allowed_roles:
                raise ValueError(
                    f"Role name must be one of: {', '.join(allowed_roles)}"
                )
        return v.lower() if v else v

    @field_validator("custom_permissions")
    @classmethod
    def validate_custom_permissions(cls, v):
        """Validate custom permissions list."""
        return v


class TeamMemberUpdate(BaseModel):
    """Schema for updating a team member."""

    role_id: int | None = Field(None, description="New role ID")
    is_active: bool | None = Field(None, description="Active status")


class TeamMemberResponse(BaseModel):
    """Schema for team member response."""

    id: int = Field(..., description="User ID")
    email: EmailStr
    username: str
    first_name: str | None
    last_name: str | None
    full_name: str
    role_name: str = Field(..., description="Role name")
    role_id: int | None
    permissions: list[str] = Field(
        default_factory=list, description="User's permissions"
    )
    is_active: bool
    is_owner: bool
    invitation_pending: bool = Field(
        default=False, description="True if invitation not yet accepted"
    )
    invited_at: datetime | None = Field(None, description="When invitation was sent")
    accepted_at: datetime | None = Field(
        None, description="When invitation was accepted"
    )
    joined_at: datetime = Field(..., description="When user joined store")

    class Config:
        from_attributes = True


class TeamMemberListResponse(BaseModel):
    """Schema for team member list response."""

    members: list[TeamMemberResponse]
    total: int
    active_count: int
    pending_invitations: int


# ============================================================================
# Invitation Schemas
# ============================================================================


class InvitationAccept(BaseModel):
    """Schema for accepting a team invitation."""

    invitation_token: str = Field(
        ..., min_length=32, description="Invitation token from email"
    )
    password: str = Field(
        ..., min_length=8, max_length=128, description="Password for new account"
    )
    first_name: str = Field(..., min_length=1, max_length=100)
    last_name: str = Field(..., min_length=1, max_length=100)

    @field_validator("password")
    @classmethod
    def validate_password_strength(cls, v):
        """Validate password meets minimum requirements."""
        if len(v) < 8:
            raise ValueError("Password must be at least 8 characters long")

        has_upper = any(c.isupper() for c in v)
        has_lower = any(c.islower() for c in v)
        has_digit = any(c.isdigit() for c in v)

        if not (has_upper and has_lower and has_digit):
            raise ValueError(
                "Password must contain at least one uppercase letter, "
                "one lowercase letter, and one digit"
            )

        return v


class InvitationResponse(BaseModel):
    """Schema for invitation response."""

    message: str
    email: EmailStr
    role: str
    invitation_token: str | None = Field(
        None, description="Token (only returned in dev/test environments)"
    )
    invitation_sent: bool = Field(default=True)


class InvitationAcceptResponse(BaseModel):
    """Schema for invitation acceptance response."""

    message: str
    store: dict = Field(..., description="Store information")
    user: dict = Field(..., description="User information")
    role: str


# ============================================================================
# Team Statistics Schema
# ============================================================================


class TeamStatistics(BaseModel):
    """Schema for team statistics."""

    total_members: int
    active_members: int
    inactive_members: int
    pending_invitations: int
    owners: int
    team_members: int
    roles_breakdown: dict = Field(
        default_factory=dict, description="Count of members per role"
    )


# ============================================================================
# Bulk Operations Schemas
# ============================================================================


class BulkRemoveRequest(BaseModel):
    """Schema for bulk removing team members."""

    user_ids: list[int] = Field(
        ..., min_items=1, description="List of user IDs to remove"
    )


class BulkRemoveResponse(BaseModel):
    """Schema for bulk remove response."""

    success_count: int
    failed_count: int
    errors: list[dict] = Field(default_factory=list)


# ============================================================================
# Permission Check Schemas
# ============================================================================


class PermissionCheckRequest(BaseModel):
    """Schema for checking permissions."""

    permissions: list[str] = Field(..., min_items=1, description="Permissions to check")


class PermissionCheckResponse(BaseModel):
    """Schema for permission check response."""

    has_all: bool = Field(..., description="True if user has all permissions")
    has_any: bool = Field(..., description="True if user has any permission")
    granted: list[str] = Field(default_factory=list, description="Permissions user has")
    denied: list[str] = Field(
        default_factory=list, description="Permissions user lacks"
    )


class UserPermissionsResponse(BaseModel):
    """Schema for user's permissions response."""

    permissions: list[str] = Field(default_factory=list)
    permission_count: int
    is_owner: bool
    role_name: str | None = None


# ============================================================================
# Permission Catalog Schemas
# ============================================================================


class PermissionCatalogItem(BaseModel):
    """A single permission with its metadata for UI display."""

    id: str
    label: str
    description: str
    is_owner_only: bool = False


class PermissionCategoryResponse(BaseModel):
    """A category of related permissions."""

    id: str
    label: str
    permissions: list[PermissionCatalogItem]


class PermissionCatalogResponse(BaseModel):
    """Complete permission catalog grouped by category."""

    categories: list[PermissionCategoryResponse]


# ============================================================================
# Error Response Schema
# ============================================================================


class TeamErrorResponse(BaseModel):
    """Schema for team operation errors."""

    error_code: str
    message: str
    details: dict | None = None


# ============================================================================
# Merchant Team Schemas (Hub View)
# ============================================================================


class MerchantTeamMemberStoreInfo(BaseModel):
    """A member's role/status in one specific store."""

    store_id: int
    store_name: str
    store_code: str
    role_name: str | None = None
    role_id: int | None = None
    is_active: bool = True
    is_pending: bool = False


class MerchantTeamMemberResponse(BaseModel):
    """A team member aggregated across all merchant stores."""

    user_id: int
    email: EmailStr
    first_name: str | None = None
    last_name: str | None = None
    full_name: str
    stores: list[MerchantTeamMemberStoreInfo] = Field(default_factory=list)
    is_owner: bool = False


class MerchantTeamStoreInfo(BaseModel):
    """Compact store info for the merchant team overview."""

    id: int
    name: str
    code: str


class MerchantTeamOverviewResponse(BaseModel):
    """Merchant team overview with member-centric view."""

    merchant_name: str
    stores: list[MerchantTeamStoreInfo]
    members: list[MerchantTeamMemberResponse]
    total_members: int
    total_active: int
    total_pending: int


class MerchantTeamInvite(BaseModel):
    """Schema for inviting a member to merchant stores."""

    email: EmailStr
    first_name: str | None = Field(None, max_length=100)
    last_name: str | None = Field(None, max_length=100)
    store_ids: list[int] = Field(..., min_length=1, description="Store IDs to invite to")
    role_name: str = Field("staff", description="Role name for all selected stores")

    @field_validator("role_name")
    @classmethod
    def validate_role_name(cls, v):
        """Validate role name is in allowed presets."""
        allowed_roles = ["manager", "staff", "support", "viewer", "marketing"]
        if v.lower() not in allowed_roles:
            raise ValueError(
                f"Role name must be one of: {', '.join(allowed_roles)}"
            )
        return v.lower()


class MerchantTeamInviteResult(BaseModel):
    """Per-store invite result."""

    store_id: int
    store_name: str
    success: bool
    error: str | None = None


class MerchantTeamInviteResponse(BaseModel):
    """Response for merchant team invite (multi-store)."""

    message: str
    email: EmailStr
    results: list[MerchantTeamInviteResult]


class MerchantTeamProfileUpdate(BaseModel):
    """Schema for updating a team member's profile."""

    first_name: str | None = Field(None, max_length=100)
    last_name: str | None = Field(None, max_length=100)
    email: EmailStr | None = None
