# models/schema/team.py
"""
Pydantic schemas for vendor 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
    vendor_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")
    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")
    def validate_custom_permissions(cls, v, values):
        """Ensure either role_id/role_name OR custom_permissions is provided."""
        if v is not None and len(v) > 0:
            # If custom permissions provided, role_name should be provided too
            if "role_name" not in values or not values["role_name"]:
                raise ValueError(
                    "role_name is required when providing custom_permissions"
                )
        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
    user_type: str = Field(..., description="'owner' or 'member'")
    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 vendor")

    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")
    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
    vendor: dict = Field(..., description="Vendor 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


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


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

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