from enum import Enum
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, Field


class PoliciesJoinOperation(str, Enum):
    OR = "OR"
    AND = "AND"


class SQLAuthorizerFlags(BaseModel):
    """Modification flags for the SQL Authorizer request."""

    model_config = {"validate_by_name": True, "validate_by_alias": True}

    empty_rls_treat_as_denied: Optional[bool] = Field(
        default=None, alias="emptyRLSTreatAsDenied"
    )
    empty_cls_treat_as_permitted: Optional[bool] = Field(
        default=None, alias="emptyCLSTreatAsPermitted"
    )
    ignore_runtime_cls_response: Optional[bool] = Field(
        default=None, alias="ignoreRuntimeCLSResponse"
    )
    expand_star_column: Optional[bool] = Field(
        default=None, alias="expandStarColumn"
    )
    opposite_column_filtering_behavior: Optional[bool] = Field(
        default=None, alias="oppositeColumnFilteringBehavior"
    )
    policies_join_operation: Optional[PoliciesJoinOperation] = Field(
        default=None, alias="policiesJoinOperation"
    )
    runtime_cls_as_masked: Optional[bool] = Field(
        default=None, alias="runtimeCLSAsMasked"
    )
    columns_resource_type: Optional[str] = Field(
        default=None, alias="columnsResourceType"
    )


class SQLAuthorizerRuntimeFineTune(BaseModel):
    """Optional PDP Policy Resolution parameters."""

    model_config = {"validate_by_name": True, "validate_by_alias": True}

    remote_ip: Optional[str] = Field(
        default=None, alias="remoteIp"
    )
    time_zone_offset: Optional[float] = Field(
        default=None, alias="timeZoneOffset"
    )
    asset_list: Optional[List[Dict[str, Any]]] = Field(
        default=None, alias="assetList"
    )
    resource_types: Optional[List[Dict[str, Any]]] = Field(
        default=None, alias="resourceTypes"
    )
    all_resource_types: Optional[Dict[str, Any]] = Field(
        default=None, alias="allResourceTypes"
    )
    include_context: bool = Field(
        default=False, alias="includeContext"
    )
    include_access_policy: bool = Field(
        default=False, alias="includeAccessPolicy"
    )
    include_access_policy_id: bool = Field(
        default=False, alias="includeAccessPolicyId"
    )
    include_identity: bool = Field(
        default=False, alias="includeIdentity"
    )
    access_token_format: Optional[str] = Field(
        default=None, alias="accessTokenFormat"
    )
    use_cache: bool = Field(
        default=True, alias="useCache"
    )
    combined_multi_value: bool = Field(
        default=False, alias="combinedMultiValue"
    )
    asset_context: Optional[List[Dict[str, Any]]] = Field(
        default=None, alias="assetContext"
    )
    use_optimized_asset_context_response: bool = Field(
        default=False, alias="useOptimizedAssetContextResponse"
    )
    operational_filters: Optional[List[Dict[str, Any]]] = Field(
        default=None, alias="operationalFilters"
    )
    skip_unneeded_or_unavailable_identity_sources: bool = Field(
        default=False, alias="skipUnneededOrUnavailableIdentitySources"
    )
    include_partial_identity_sources_indication: bool = Field(
        default=False, alias="includePartialIdentitySourcesIndication"
    )
    fail_on_calculated_attributes_errors: bool = Field(
        default=True, alias="failOnCalculatedAttributesErrors"
    )


class SQLAuthorizerRequest(BaseModel):
    """Request model for the SQL Authorizer /resql endpoint."""

    model_config = {"validate_by_name": True, "validate_by_alias": True}

    sql: str
    entity_id: Optional[str] = Field(default=None, alias="entityId")
    entity_type_id: Optional[str] = Field(default=None, alias="entityTypeId")
    user: Optional[str] = None
    flags: Optional[SQLAuthorizerFlags] = None
    entity_attributes: Optional[Dict[str, List[Dict[str, Any]]]] = Field(
        default=None, alias="entityAttributes"
    )
    context_data: Optional[Dict[str, List[Dict[str, Any]]]] = Field(
        default=None, alias="contextData"
    )
    environment: Optional[Dict[str, List[Dict[str, Any]]]] = None
    runtime_fine_tune: Optional[SQLAuthorizerRuntimeFineTune] = Field(
        default=None, alias="runtimeFineTune"
    )


class SQLAuthorizerResponse(BaseModel):
    """Response model from the SQL Authorizer /resql endpoint."""

    model_config = {"validate_by_name": True, "validate_by_alias": True}

    sql: str
    was_modified: bool = Field(alias="wasModified")
    error: Optional[str] = Field(default=None)
