# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from typing import Dict, List, Union, Optional
from datetime import datetime
from typing_extensions import Literal, TypeAlias

from pydantic import Field as FieldInfo

from ..._models import BaseModel

__all__ = [
    "EvaluationDashboardWidgetWithResult",
    "Query",
    "QuerySeriesQuery",
    "QuerySeriesQuerySelect",
    "QuerySeriesQuerySelectExpression",
    "QuerySeriesQuerySelectExpressionColumn",
    "QuerySeriesQuerySelectExpressionAggregation",
    "QuerySeriesQueryFilter",
    "QuerySeriesQueryFilterCondition",
    "QuerySeriesQueryOrderBy",
    "QueryMetricQuery",
    "QueryMetricQuerySelect",
    "QueryMetricQuerySelectExpression",
    "QueryMetricQuerySelectExpressionColumn",
    "QueryMetricQuerySelectExpressionAggregation",
    "QueryMetricQueryFilter",
    "QueryMetricQueryFilterCondition",
    "Result",
]


class QuerySeriesQuerySelectExpressionColumn(BaseModel):
    """Reference to a column from evaluation_items.data

    Example:
        {"type": "COLUMN", "column": "category"}
    """

    column: str
    """Column name from evaluation_items.data"""

    source: Optional[str] = None
    """Column source: 'data' or 'task_result_cache'"""

    type: Optional[Literal["COLUMN"]] = None


class QuerySeriesQuerySelectExpressionAggregation(BaseModel):
    """Aggregation function to apply

    Examples:
        {"type": "AGGREGATION", "function": "AVG", "column": "score"}
        {"type": "AGGREGATION", "function": "COUNT", "column": "*"}
        {"type": "AGGREGATION", "function": "PERCENTILE", "column": "score", "params": {"percentile": 95}}
    """

    column: str
    """Column to aggregate, or '_' for COUNT(_)"""

    function: Literal[
        "COUNT", "SUM", "AVG", "MIN", "MAX", "STDDEV", "VARIANCE", "PERCENTILE", "COUNT_DISTINCT", "PERCENTAGE"
    ]
    """Supported aggregation functions"""

    params: Optional[Dict[str, object]] = None
    """
    Function parameters (e.g., {'percentile': 95} for PERCENTILE,
    {'percentage_filters': Filter} for PERCENTAGE)
    """

    source: Optional[str] = None
    """Column source: 'data' or 'task_result_cache'"""

    type: Optional[Literal["AGGREGATION"]] = None


QuerySeriesQuerySelectExpression: TypeAlias = Union[
    QuerySeriesQuerySelectExpressionColumn, QuerySeriesQuerySelectExpressionAggregation
]


class QuerySeriesQuerySelect(BaseModel):
    """Column in SELECT clause"""

    expression: QuerySeriesQuerySelectExpression
    """Reference to a column from evaluation_items.data

    Example: {"type": "COLUMN", "column": "category"}
    """

    alias: Optional[str] = None
    """Optional alias for the selected item"""


class QuerySeriesQueryFilterCondition(BaseModel):
    """Single filter condition comparing a column to a value.

    Example:
        {"column": "score", "operator": ">", "value": 0.5}
        {"column": "category", "operator": "=", "value": "test"}
    """

    column: str
    """Column name to filter on"""

    operator: Literal["=", "!=", ">", "<", ">=", "<=", "IN", "NOT IN", "LIKE", "NOT LIKE"]
    """Comparison operator"""

    value: object
    """Value to compare against"""

    source: Optional[str] = None
    """Column source: 'data' or 'task_result_cache'"""


class QuerySeriesQueryFilter(BaseModel):
    """Filter conditions (WHERE clause)"""

    conditions: List[QuerySeriesQueryFilterCondition]

    logical_operators: Optional[List[Literal["AND", "OR"]]] = FieldInfo(alias="logicalOperators", default=None)
    """Logical operators connecting conditions. Length must be len(conditions) - 1"""


class QuerySeriesQueryOrderBy(BaseModel):
    """Column in ORDER BY clause"""

    column: str
    """Column name to sort by"""

    direction: Optional[Literal["ASC", "DESC"]] = None
    """Sort direction"""

    source: Optional[str] = None
    """Column source: 'data' or 'task_result_cache'"""


class QuerySeriesQuery(BaseModel):
    """Query that returns a series of records (used for table/bar/histogram widgets).

    Used for widget types: table, bar, histogram.
    Returns: {"type": "series", "data": [...]}

    Example SQL equivalent:
        SELECT category, AVG(score) as avg_score, COUNT(*) as count
        FROM evaluation_items
        WHERE score > 0.5 AND category = 'test'
        GROUP BY category
        ORDER BY avg_score DESC
        LIMIT 100
    """

    select: List[QuerySeriesQuerySelect]

    filter: Optional[QuerySeriesQueryFilter] = None
    """Filter conditions (WHERE clause)"""

    group_by: Optional[List[str]] = FieldInfo(alias="groupBy", default=None)
    """Columns to group by"""

    limit: Optional[int] = None
    """Max rows to return"""

    order_by: Optional[List[QuerySeriesQueryOrderBy]] = FieldInfo(alias="orderBy", default=None)
    """Sort order"""


class QueryMetricQuerySelectExpressionColumn(BaseModel):
    """Reference to a column from evaluation_items.data

    Example:
        {"type": "COLUMN", "column": "category"}
    """

    column: str
    """Column name from evaluation_items.data"""

    source: Optional[str] = None
    """Column source: 'data' or 'task_result_cache'"""

    type: Optional[Literal["COLUMN"]] = None


class QueryMetricQuerySelectExpressionAggregation(BaseModel):
    """Aggregation function to apply

    Examples:
        {"type": "AGGREGATION", "function": "AVG", "column": "score"}
        {"type": "AGGREGATION", "function": "COUNT", "column": "*"}
        {"type": "AGGREGATION", "function": "PERCENTILE", "column": "score", "params": {"percentile": 95}}
    """

    column: str
    """Column to aggregate, or '_' for COUNT(_)"""

    function: Literal[
        "COUNT", "SUM", "AVG", "MIN", "MAX", "STDDEV", "VARIANCE", "PERCENTILE", "COUNT_DISTINCT", "PERCENTAGE"
    ]
    """Supported aggregation functions"""

    params: Optional[Dict[str, object]] = None
    """
    Function parameters (e.g., {'percentile': 95} for PERCENTILE,
    {'percentage_filters': Filter} for PERCENTAGE)
    """

    source: Optional[str] = None
    """Column source: 'data' or 'task_result_cache'"""

    type: Optional[Literal["AGGREGATION"]] = None


QueryMetricQuerySelectExpression: TypeAlias = Union[
    QueryMetricQuerySelectExpressionColumn, QueryMetricQuerySelectExpressionAggregation
]


class QueryMetricQuerySelect(BaseModel):
    """Column in SELECT clause"""

    expression: QueryMetricQuerySelectExpression
    """Reference to a column from evaluation_items.data

    Example: {"type": "COLUMN", "column": "category"}
    """

    alias: Optional[str] = None
    """Optional alias for the selected item"""


class QueryMetricQueryFilterCondition(BaseModel):
    """Single filter condition comparing a column to a value.

    Example:
        {"column": "score", "operator": ">", "value": 0.5}
        {"column": "category", "operator": "=", "value": "test"}
    """

    column: str
    """Column name to filter on"""

    operator: Literal["=", "!=", ">", "<", ">=", "<=", "IN", "NOT IN", "LIKE", "NOT LIKE"]
    """Comparison operator"""

    value: object
    """Value to compare against"""

    source: Optional[str] = None
    """Column source: 'data' or 'task_result_cache'"""


class QueryMetricQueryFilter(BaseModel):
    """Filter conditions (WHERE clause)"""

    conditions: List[QueryMetricQueryFilterCondition]

    logical_operators: Optional[List[Literal["AND", "OR"]]] = FieldInfo(alias="logicalOperators", default=None)
    """Logical operators connecting conditions. Length must be len(conditions) - 1"""


class QueryMetricQuery(BaseModel):
    """Query that returns a single metric value (used for metric widgets).

    Used for widget type: metric.
    Enforces exactly 1 aggregation in select.
    Returns: {"type": "metric", "data": ...}

    Example SQL equivalent:
        SELECT AVG(score) as average_score
        FROM evaluation_items
    """

    select: List[QueryMetricQuerySelect]

    filter: Optional[QueryMetricQueryFilter] = None
    """Filter conditions (WHERE clause)"""


Query: TypeAlias = Union[QuerySeriesQuery, QueryMetricQuery]


class Result(BaseModel):
    """Computed result for this widget"""

    id: str
    """Unique identifier of the widget result"""

    computation_status: str
    """Status: pending, completed, or failed"""

    widget_id: str
    """Widget ID this result belongs to"""

    computed_at: Optional[datetime] = None
    """When computation completed"""

    computed_result: Optional[Dict[str, object]] = None
    """Computed result data.

    Metric: {type: 'metric', data: 42}, Series: {type: 'series', data: [{x: 'A', y:
    10}, ...]}
    """

    error_message: Optional[str] = None
    """Error message if computation failed"""


class EvaluationDashboardWidgetWithResult(BaseModel):
    """Response model for widget creation - includes widget and computed result"""

    id: str
    """Unique identifier of the widget"""

    account_id: str
    """Account that owns this widget"""

    created_at: datetime
    """When the widget was created"""

    title: str
    """Widget title"""

    type: Literal["bar", "histogram", "metric", "table", "markdown", "heading"]
    """Widget type"""

    config: Optional[Dict[str, object]] = None
    """Display configuration"""

    object: Optional[Literal["evaluation_widget"]] = None

    query: Optional[Query] = None
    """Structured query AST for computation (SeriesQuery or MetricQuery)"""

    result: Optional[Result] = None
    """Computed result for this widget"""
