# generated by datamodel-codegen:
#   filename:  VizQLDataServiceOpenAPISchema.json
#   timestamp: 2025-09-08T18:59:06+00:00

from __future__ import annotations

from datetime import date
from enum import Enum
from typing import Annotated, Any, Dict, List, Optional, Union

from .tableau_model import TableauModel
from pydantic import AwareDatetime, Field as PydanticField, RootModel


class TableauError(TableauModel):
    errorCode: Optional[str] = None
    message: Optional[str] = None
    messages: Optional[List] = None
    datetime: Optional[AwareDatetime] = None
    debug: Optional[Dict[str, Any]] = None
    tab_error_code: Annotated[Optional[str], PydanticField(alias='tab-error-code')] = None


class TableCalcType(Enum):
    CUSTOM = 'CUSTOM'
    NESTED = 'NESTED'
    DIFFERENCE_FROM = 'DIFFERENCE_FROM'
    PERCENT_DIFFERENCE_FROM = 'PERCENT_DIFFERENCE_FROM'
    PERCENT_FROM = 'PERCENT_FROM'
    PERCENT_OF_TOTAL = 'PERCENT_OF_TOTAL'
    RANK = 'RANK'
    PERCENTILE = 'PERCENTILE'
    RUNNING_TOTAL = 'RUNNING_TOTAL'
    MOVING_CALCULATION = 'MOVING_CALCULATION'


class RelativeTo(Enum):
    PREVIOUS = 'PREVIOUS'
    NEXT = 'NEXT'
    FIRST = 'FIRST'
    LAST = 'LAST'


class RankType(Enum):
    COMPETITION = 'COMPETITION'
    MODIFIED_COMPETITION = 'MODIFIED COMPETITION'
    DENSE = 'DENSE'
    UNIQUE = 'UNIQUE'


class TableCalcComputedAggregation(Enum):
    SUM = 'SUM'
    AVG = 'AVG'
    MIN = 'MIN'
    MAX = 'MAX'


class ColumnClass(Enum):
    COLUMN = 'COLUMN'
    BIN = 'BIN'
    GROUP = 'GROUP'
    CALCULATION = 'CALCULATION'
    TABLE_CALCULATION = 'TABLE_CALCULATION'


class DataType(Enum):
    INTEGER = 'INTEGER'
    REAL = 'REAL'
    STRING = 'STRING'
    DATETIME = 'DATETIME'
    BOOLEAN = 'BOOLEAN'
    DATE = 'DATE'
    SPATIAL = 'SPATIAL'
    UNKNOWN = 'UNKNOWN'


class Connection(TableauModel):
    connectionLuid: Optional[str] = None
    connectionUsername: str
    connectionPassword: str


class Datasource(TableauModel):
    datasourceLuid: Annotated[
        str, PydanticField(description='The LUID of the data source to be queried.')
    ]
    connections: Optional[List[Connection]] = None


class FilterType(Enum):
    QUANTITATIVE_DATE = 'QUANTITATIVE_DATE'
    QUANTITATIVE_NUMERICAL = 'QUANTITATIVE_NUMERICAL'
    SET = 'SET'
    MATCH = 'MATCH'
    DATE = 'DATE'
    TOP = 'TOP'


class DimensionFilterField(TableauModel):
    fieldCaption: Annotated[
        str, PydanticField(description='The caption of the field to filter on.')
    ]


class CalculatedFilterField(TableauModel):
    calculation: Annotated[
        str, PydanticField(description='A Tableau calculation that will be used to filter on.')
    ]


class Function(Enum):
    SUM = 'SUM'
    AVG = 'AVG'
    MEDIAN = 'MEDIAN'
    COUNT = 'COUNT'
    COUNTD = 'COUNTD'
    MIN = 'MIN'
    MAX = 'MAX'
    STDEV = 'STDEV'
    VAR = 'VAR'
    COLLECT = 'COLLECT'
    YEAR = 'YEAR'
    QUARTER = 'QUARTER'
    MONTH = 'MONTH'
    WEEK = 'WEEK'
    DAY = 'DAY'
    TRUNC_YEAR = 'TRUNC_YEAR'
    TRUNC_QUARTER = 'TRUNC_QUARTER'
    TRUNC_MONTH = 'TRUNC_MONTH'
    TRUNC_WEEK = 'TRUNC_WEEK'
    TRUNC_DAY = 'TRUNC_DAY'
    AGG = 'AGG'
    NONE = 'NONE'
    UNSPECIFIED = 'UNSPECIFIED'


class QuantitativeFilterType(Enum):
    RANGE = 'RANGE'
    MIN = 'MIN'
    MAX = 'MAX'
    ONLY_NULL = 'ONLY_NULL'
    ONLY_NON_NULL = 'ONLY_NON_NULL'


class QueryOptions(TableauModel):
    debug: Optional[bool] = False
    bypassMetadataCache: Optional[bool] = False
    interpretFieldCaptionsAsFieldNames: Annotated[
        Optional[bool],
        PydanticField(
            description="When true, user will pass in the Field's fieldName instead of the Field's fieldCaption in every place that fieldCaption appears (in Fields, Filters, and Calculation formulas). See FieldMetadata of the read-metadata endpoint."
        ),
    ] = False


class QueryOutput(TableauModel):
    data: Optional[List] = None


class ReadMetadataRequest(TableauModel):
    datasource: Datasource
    options: Optional[QueryOptions] = None


class ReturnFormat(Enum):
    OBJECTS = 'OBJECTS'
    ARRAYS = 'ARRAYS'


class SortDirection(Enum):
    ASC = 'ASC'
    DESC = 'DESC'


class PeriodType(Enum):
    MINUTES = 'MINUTES'
    HOURS = 'HOURS'
    DAYS = 'DAYS'
    WEEKS = 'WEEKS'
    MONTHS = 'MONTHS'
    QUARTERS = 'QUARTERS'
    YEARS = 'YEARS'


class DateRangeType(Enum):
    CURRENT = 'CURRENT'
    LAST = 'LAST'
    LASTN = 'LASTN'
    NEXT = 'NEXT'
    NEXTN = 'NEXTN'
    TODATE = 'TODATE'


class Direction(Enum):
    TOP = 'TOP'
    BOTTOM = 'BOTTOM'


class Parameter(TableauModel):
    parameterCaption: Annotated[
        str, PydanticField(description='The caption of the parameter to set.')
    ]
    value: Annotated[
        Any,
        PydanticField(
            description='The value to set for the parameter. The type of the value must match the type of the parameter.'
        ),
    ]


class NullableAny(RootModel[Optional[Any]]):
    root: Optional[Any] = None


class ParameterType(Enum):
    ANY_VALUE = 'ANY_VALUE'
    LIST = 'LIST'
    QUANTITATIVE_RANGE = 'QUANTITATIVE_RANGE'
    QUANTITATIVE_DATE = 'QUANTITATIVE_DATE'


class ParameterRecordBase(TableauModel):
    parameterType: ParameterType
    parameterName: Annotated[
        Optional[str],
        PydanticField(
            description='The tableau internal name of the parameter to identify and reference the parameter.'
        ),
    ] = None
    parameterCaption: Annotated[
        str,
        PydanticField(
            description='The user defined name of the parameter to identify and reference the parameter.'
        ),
    ]
    dataType: DataType
    value: Annotated[
        Any,
        PydanticField(
            description='The value to set for the parameter. The type of the value must match the type of the parameter.'
        ),
    ]


class GetDatasourceModelRequest(TableauModel):
    datasource: Datasource
    options: Optional[QueryOptions] = None


class LogicalTable(TableauModel):
    logicalTableId: str
    caption: str


class LogicalTableRelationshipEndpoint(TableauModel):
    logicalTableId: str


class FieldBase(TableauModel):
    fieldCaption: Annotated[
        str,
        PydanticField(
            description='Either the name of a specific Field in the data source, or, in the case of a calculation, a user-supplied name for the calculation.'
        ),
    ]
    fieldAlias: Annotated[
        Optional[str],
        PydanticField(
            description='An alternative name to give the field. Will only be used in object format output.'
        ),
    ] = None
    maxDecimalPlaces: Annotated[
        Optional[int],
        PydanticField(
            description='The maximum number of decimal places. Any trailing 0s will be dropped. The maxDecimalPlaces value must be greater or equal to 0.'
        ),
    ] = None
    sortDirection: Optional[SortDirection] = None
    sortPriority: Annotated[
        Optional[int],
        PydanticField(
            description='To enable sorting on a specific Field, provide a sortPriority for that field, and that field will be sorted. The sortPriority provides a ranking of how to sort fields when multiple fields are being sorted. The highest priority (lowest number) field is sorted first. If only one field is being sorted, then any value may be used for sortPriority. SortPriority should be an integer greater than 0.'
        ),
    ] = None


class DimensionField(FieldBase):
    fieldCaption: Optional[Any] = None
    fieldAlias: Optional[Any] = None
    maxDecimalPlaces: Optional[Any] = None
    sortDirection: Optional[Any] = None
    sortPriority: Optional[Any] = None


class MeasureField(FieldBase):
    function: Function
    fieldCaption: Optional[Any] = None
    fieldAlias: Optional[Any] = None
    maxDecimalPlaces: Optional[Any] = None
    sortDirection: Optional[Any] = None
    sortPriority: Optional[Any] = None


class CalculatedField(FieldBase):
    calculation: Annotated[
        str,
        PydanticField(
            description='A Tableau calculation that will be returned as a Field in the query.'
        ),
    ]
    fieldCaption: Optional[Any] = None
    fieldAlias: Optional[Any] = None
    maxDecimalPlaces: Optional[Any] = None
    sortDirection: Optional[Any] = None
    sortPriority: Optional[Any] = None


class BinField(FieldBase):
    binSize: Annotated[float, PydanticField(description='The size of the bin to be applied.')]
    fieldCaption: Optional[Any] = None
    fieldAlias: Optional[Any] = None
    maxDecimalPlaces: Optional[Any] = None
    sortDirection: Optional[Any] = None
    sortPriority: Optional[Any] = None


class TableCalcFieldReference(TableauModel):
    fieldCaption: str
    function: Optional[Function] = None


class TableCalcCustomSort(TableauModel):
    fieldCaption: str
    function: Function
    direction: SortDirection


class FieldMetadata(TableauModel):
    fieldName: Annotated[
        Optional[str],
        PydanticField(description='The underlying database column name for the field.'),
    ] = None
    fieldCaption: Annotated[
        Optional[str], PydanticField(description='The caption of the field saved in the PDS.')
    ] = None
    dataType: Annotated[
        Optional[DataType],
        PydanticField(description='Data type of the column, i.e., "STRING", "BOOLEAN", etc.'),
    ] = None
    defaultAggregation: Annotated[
        Optional[Function],
        PydanticField(description='The default aggregation applied to the field.'),
    ] = None
    columnClass: Annotated[
        Optional[ColumnClass],
        PydanticField(description='The type of field, i.e., "COLUMN", "GROUP", BIN" etc.'),
    ] = None
    formula: Annotated[
        Optional[str],
        PydanticField(description='The formula for this field if it is a calculation.'),
    ] = None
    logicalTableId: Annotated[
        Optional[str],
        PydanticField(
            description='An internal unique identifier for the logical table that this field originates from.'
        ),
    ] = None


class MeasureFilterField(TableauModel):
    fieldCaption: Annotated[
        str, PydanticField(description='The caption of the field to filter on.')
    ]
    function: Function


class ExtraData(TableauModel):
    parameters: Optional[List[ParameterRecord]] = None


class MetadataOutput(TableauModel):
    data: Optional[List[FieldMetadata]] = None
    extraData: Optional[ExtraData] = None


class QueryDatasourceOptions(QueryOptions):
    disaggregate: Optional[bool] = False
    returnFormat: Optional[ReturnFormat] = None


class AnyValueParameter(ParameterRecordBase):
    pass


class ListParameter(ParameterRecordBase):
    members: Optional[List[NullableAny]] = None


class QuantitativeRangeParameter(ParameterRecordBase):
    min: Annotated[
        Optional[float],
        PydanticField(
            description='The minimum allowable value for this range parameter. Parameter values must be greater than or equal to this value.'
        ),
    ] = None
    max: Annotated[
        Optional[float],
        PydanticField(
            description='The maximum allowable value for this range parameter. Parameter values must be less than or equal to this value.'
        ),
    ] = None
    step: Annotated[
        Optional[float],
        PydanticField(
            description='The increment step size for values within the numeric range. Defines the granularity of allowed values between min and max.'
        ),
    ] = None


class QuantitativeDateParameter(ParameterRecordBase):
    minDate: Annotated[
        Optional[str],
        PydanticField(
            description='An RFC 3339 date indicating the earliest allowable date for this parameter.'
        ),
    ] = None
    maxDate: Annotated[
        Optional[str],
        PydanticField(
            description='An RFC 3339 date indicating the latest allowable date for this parameter.'
        ),
    ] = None
    periodType: Optional[PeriodType] = None
    periodValue: Annotated[
        Optional[float],
        PydanticField(
            description='The numeric value associated with the period type for date granularity.'
        ),
    ] = None


class LogicalTableRelationship(TableauModel):
    fromLogicalTable: LogicalTableRelationshipEndpoint
    toLogicalTable: LogicalTableRelationshipEndpoint


class TableCalcSpecification(TableauModel):
    tableCalcType: TableCalcType
    dimensions: List[TableCalcFieldReference]


class CustomTableCalcSpecification(TableCalcSpecification):
    levelAddress: Optional[TableCalcFieldReference] = None
    restartEvery: Optional[TableCalcFieldReference] = None
    customSort: Optional[TableCalcCustomSort] = None


class NestedTableCalcSpecification(TableCalcSpecification):
    fieldCaption: str
    levelAddress: Optional[TableCalcFieldReference] = None
    restartEvery: Optional[TableCalcFieldReference] = None
    customSort: Optional[TableCalcCustomSort] = None


class DifferenceTableCalcSpecification(TableCalcSpecification):
    levelAddress: Optional[TableCalcFieldReference] = None
    relativeTo: Optional[RelativeTo] = 'PREVIOUS'
    customSort: Optional[TableCalcCustomSort] = None


class PercentOfTotalTableCalcSpecification(TableCalcSpecification):
    levelAddress: Optional[TableCalcFieldReference] = None
    customSort: Optional[TableCalcCustomSort] = None


class RankTableCalcSpecification(TableCalcSpecification):
    rankType: Optional[RankType] = 'COMPETITION'
    direction: Optional[SortDirection] = None


class PercentileTableCalcSpecification(TableCalcSpecification):
    direction: Optional[SortDirection] = None


class RunningTotalTableCalcSpecification(TableCalcSpecification):
    aggregation: Optional[TableCalcComputedAggregation] = 'SUM'
    restartEvery: Optional[TableCalcFieldReference] = None
    customSort: Optional[TableCalcCustomSort] = None
    secondaryTableCalculation: Optional[TableCalcSpecification] = None


class MovingTableCalcSpecification(TableCalcSpecification):
    aggregation: Optional[TableCalcComputedAggregation] = 'SUM'
    previous: Optional[int] = -2
    next: Optional[int] = 0
    includeCurrent: Optional[bool] = True
    fillInNull: Optional[bool] = False
    customSort: Optional[TableCalcCustomSort] = None
    secondaryTableCalculation: Optional[TableCalcSpecification] = None


class FilterField(
    RootModel[Union[DimensionFilterField, MeasureFilterField, CalculatedFilterField]]
):
    root: Union[DimensionFilterField, MeasureFilterField, CalculatedFilterField]


class DatasourceModelOutput(TableauModel):
    logicalTables: Optional[List[LogicalTable]] = None
    logicalTableRelationships: Optional[List[LogicalTableRelationship]] = None


class TableCalcField(FieldBase):
    function: Optional[Function] = None
    calculation: Optional[str] = None
    tableCalculation: TableCalcSpecification
    nestedTableCalculations: Optional[List[TableCalcSpecification]] = None
    fieldCaption: Optional[Any] = None
    fieldAlias: Optional[Any] = None
    maxDecimalPlaces: Optional[Any] = None
    sortDirection: Optional[Any] = None
    sortPriority: Optional[Any] = None


class Filter(TableauModel):
    field: FilterField
    filterType: FilterType
    context: Annotated[
        Optional[bool],
        PydanticField(
            description="Make the given filter a context filter, meaning that it's an independent filter. Any other filters that you set are defined as dependent filters because they process only the data that passes through the context filter."
        ),
    ] = False


class MatchFilter(Filter):
    contains: Annotated[
        Optional[str], PydanticField(description='Matches when a field contains this value.')
    ] = None
    startsWith: Annotated[
        Optional[str], PydanticField(description='Matches when a field starts with this value.')
    ] = None
    endsWith: Annotated[
        Optional[str], PydanticField(description='Matches when a field ends with this value.')
    ] = None
    exclude: Annotated[
        Optional[bool],
        PydanticField(description='When true, the inverse of the matching logic will be used.'),
    ] = False


class QuantitativeFilterBase(Filter):
    quantitativeFilterType: QuantitativeFilterType
    includeNulls: Annotated[
        Optional[bool],
        PydanticField(
            description='Should nulls be returned or not. Only applies to RANGE, MIN, and MAX filters. If not provided, the default is to not include null values.'
        ),
    ] = None


class QuantitativeNumericalFilter(QuantitativeFilterBase):
    min: Annotated[
        Optional[float],
        PydanticField(
            description='A numerical value, either integer or floating point, indicating the minimum value to filter upon. Required if using quantitativeFilterType RANGE or if using quantitativeFilterType MIN.'
        ),
    ] = None
    max: Annotated[
        Optional[float],
        PydanticField(
            description='A numerical value, either integer or floating point, indicating the maximum value to filter upon. Required if using quantitativeFilterType RANGE or if using quantitativeFilterType MIN.'
        ),
    ] = None


class QuantitativeDateFilter(QuantitativeFilterBase):
    minDate: Annotated[
        Optional[date],
        PydanticField(
            description='An RFC 3339 date indicating the earliest date to filter upon. Required if using quantitativeFilterType RANGE or if using quantitativeFilterType MIN.'
        ),
    ] = None
    maxDate: Annotated[
        Optional[date],
        PydanticField(
            description='An RFC 3339 date indicating the latest date to filter on. Required if using quantitativeFilterType RANGE or if using quantitativeFilterType MIN.'
        ),
    ] = None


class SetFilter(Filter):
    values: Annotated[
        List[NullableAny], PydanticField(description='An array of values to filter on.')
    ]
    exclude: Optional[bool] = False


class RelativeDateFilter(Filter):
    periodType: PeriodType
    dateRangeType: Annotated[
        DateRangeType, PydanticField(description='The direction in the relative date range.')
    ]
    rangeN: Annotated[
        Optional[int],
        PydanticField(
            description='When dateRangeType is LASTN or NEXTN, this is the N value (how many years, months, etc.).'
        ),
    ] = None
    anchorDate: Annotated[
        Optional[date],
        PydanticField(
            description="If a value for this field isn't provided, the value defaults to today."
        ),
    ] = None
    includeNulls: Annotated[
        Optional[bool],
        PydanticField(
            description="Should nulls be returned or not. If a value isn't provided, the default is to not include null values."
        ),
    ] = None


class TopNFilter(Filter):
    direction: Annotated[
        Optional[Direction],
        PydanticField(description='Top (ascending) or Bottom (descending) N.'),
    ] = 'TOP'
    howMany: Annotated[
        int,
        PydanticField(
            description='The number of values from the top or the bottom of the given fieldToMeasure.'
        ),
    ]
    fieldToMeasure: FilterField


class Field(
    RootModel[
        Union[DimensionField, MeasureField, CalculatedField, BinField, TableCalcField]
    ]
):
    root: Union[DimensionField, MeasureField, CalculatedField, BinField, TableCalcField]


class Query(TableauModel):
    fields: Annotated[
        List[Field], PydanticField(description='An array of fields that define the query.')
    ]
    filters: Annotated[
        Optional[List[TabFilter]],
        PydanticField(description='An optional array of filters to apply to the query.'),
    ] = None
    parameters: Annotated[
        Optional[List[Parameter]],
        PydanticField(description='An optional array of parameters to apply to the query.'),
    ] = None


class QueryRequest(TableauModel):
    datasource: Datasource
    query: Query
    options: Optional[QueryDatasourceOptions] = None

class TabFilter(RootModel[Union[
    MatchFilter, QuantitativeNumericalFilter, QuantitativeDateFilter, SetFilter, RelativeDateFilter, TopNFilter]]):
    root: Union[
        MatchFilter, QuantitativeNumericalFilter, QuantitativeDateFilter, SetFilter, RelativeDateFilter, TopNFilter]

class ParameterRecord(RootModel[Union[
    AnyValueParameter, ListParameter, QuantitativeRangeParameter, QuantitativeDateParameter]]):
    root: Union[
        AnyValueParameter, ListParameter, QuantitativeRangeParameter, QuantitativeDateParameter]
