declare type AggregateFunction = 'COUNT' | 'SUM' | 'AVG' | 'MIN' | 'MAX' | 'MEDIAN' | 'DISTINCT';

/**
 * Formula metadata for calculated fields (UI-only metadata)
 * This is supplementary data to help the UI display and edit calculated fields.
 * The `expression` field remains the source of truth for the backend.
 *
 * IMPORTANT: This metadata is ALWAYS updated atomically with the expression field.
 * Both are generated together from the same dialog inputs, preventing drift.
 */
declare interface CalculatedFieldFormula {
    operation: CalculatedFieldOperation;
    /**
     * Array of full MetricField objects used as inputs to the calculated field.
     *
     * Storing complete Field objects eliminates the need for runtime lookups and ensures:
     * - Table alias resolution works with schema-qualified tables (Issue 1)
     * - All field metadata is available even if the input field isn't selected on the card (Issue 2)
     * - Aggregate functions, filters, and entity info are preserved
     *
     * Each input field contains complete metadata:
     * - name, entityId, entityName, qualifiedEntityName (for table qualification)
     * - aggregate (for proper post-aggregation: SUM(sales) / COUNT(orders))
     * - parameters.filters (for filtered metrics)
     * - dataType and other properties
     *
     * Example: [
     *   {name: 'sales', aggregate: 'SUM', entityName: 'sales_data', ...},
     *   {name: 'order_id', aggregate: 'COUNT', entityName: 'sales_data', ...}
     * ]
     */
    inputFields: Array<MetricField | GroupByField>;
    /**
     * Constant value used in scale operations (e.g., multiply by 0.15)
     * Only applicable for 'scale' operation type
     */
    constant?: number;
}

/**
 * Operations supported for calculated fields
 */
declare type CalculatedFieldOperation = 'sum' | 'difference' | 'product' | 'ratio' | 'change' | 'percentage' | 'scale' | 'custom';

declare interface CardConfig {
    groupByColumns?: GroupByField[];
    metricColumns?: MetricField[];
    pivotByColumns?: PivotByField[];
    sortByColumns?: SortByField[];
    detailColumns?: DetailField[];
    /**
     * Typed source that anchors the query before auto-join materializes an
     * executable joinPlan.baseEntity. This is distinct from
     * DataSource.selectedEntities, which lists available datasets but does not
     * define join-root semantics.
     */
    queryBaseSource?: SemaphorSourceRef;
    /** Preserves non-detail config when switching to detail tables. */
    detailTableBackup?: DetailTableBackupConfig;
    filters?: FilterGroup;
    joinPlan?: JoinPlan;
    rowLimit?: number;
    /**
     * One or more hierarchies that define drillable paths through dimensions.
     */
    drillHierarchies?: DrillHierarchy[];
    /**
     * Optional list of dimensions allowed for dynamic drill-down across this card.
     * Used only when drill steps contain `mode: 'dynamicDrill'` or `type: 'dynamic'`.
     */
    allowedDrillTargets?: Field[];
    /**
     * NOT UOptional preload settings for inline drill previews
     */
    inlineDrillPreview?: {
        enabled: boolean;
        limit: number;
        mode: 'lazy' | 'preloaded';
    };
    /**
     * Configuration for on-click dashboard filters triggered by this card.
     */
    clickFilterInteractions?: ClickFilterInteraction[];
    comparisonType?: 'none' | 'previous_period' | 'same_period_last_year' | 'target' | 'start_vs_end';
    targetValue?: number;
    showComparisonInLegend?: boolean;
    showTrendline?: boolean;
    trendlineWindow?: number;
    trendlineGranularity?: 'day' | 'week' | 'month';
    summary?: {
        enabled?: boolean;
        showOnCard?: boolean;
        includeInDashboardSummary?: boolean;
        breakdownDimensions?: GroupByField[];
    };
    rowAggregates?: Array<{
        label?: string;
        function: AggregateFunction;
        groupLevel: string | 'ALL';
    }>;
    columnAggregates?: Array<{
        label?: string;
        function: AggregateFunction;
        pivotLevel: string | 'ALL';
    }>;
}

declare interface ClickFilterInteraction {
    mode: 'clickFilter';
    /**
     * What element must be clicked to trigger this interaction.
     * Determines both the matching logic and the filtering behavior.
     *
     * @migration Optional during migration. Will be required in V2.
     * Old configs without trigger will apply to any click (legacy behavior).
     */
    trigger?: InteractionTrigger;
    /**
     * Fields from the chart element that should be used as filters.
     * e.g., [region, ship_mode] from a stacked bar chart
     */
    filterFields: Field[];
    /**
     * Should this card visually highlight when clicked?
     */
    highlightSelf?: boolean;
    /**
     * Cards this filter applies to (inclusive).
     * If omitted and `excludeCardIds` is also omitted → applies to all cards except self.
     */
    applyToCardIds?: string[];
    /**
     * Cards to explicitly exclude from receiving this filter.
     * Takes effect only if `applyToCardIds` is undefined (acts as override).
     */
    excludeCardIds?: string[];
    /**
     * Optional UI label or tooltip.
     */
    label?: string;
}

declare type ConnectionType = 'GoogleSheets' | 'FileUpload' | 'MySQL' | 'MSSQL' | 'PostgreSQL' | 'BigQuery' | 'Redshift' | 'Snowflake' | 'S3' | 'clickhouse' | 'S3Tables' | 'API' | 'none';

export declare const DASHBOARD_ASSISTANT_VISUAL_TOOL_PART_TYPES: readonly ["tool-runDashboardAnalysis", "tool-runAdvancedAnalysis", "tool-renderDynamicVisual"];

export declare type DashboardAssistantAddToDashboardPayload = {
    cardType: TChartType;
    cardTitle: string;
    data: Record<string, unknown>[];
    dataSource?: DataSource;
    cardConfig?: CardConfig;
    connectionId?: string;
    sql?: string;
    python?: string;
    customVisualPreferences?: {
        url: string;
        componentName: string;
        pluginChartType: string;
        settings?: Record<string, unknown>;
    };
    visualizationMode?: TVisualizationMode;
    dynamicCardPreferences?: TDynamicCardPreferences;
};

export declare type DashboardAssistantAnalysisRequest = {
    operation: DashboardAssistantOperationKind;
    analyticsIntent: SemaphorAnalyticsIntent;
    chartTitle?: string;
    chartType?: TChartType;
    responseMode?: 'standard' | 'data_only';
};

export declare type DashboardAssistantArtifact = {
    kind: 'analysis' | 'dynamic_visual' | 'clarification';
    status: 'ready' | 'partial' | 'failed';
    title?: string;
    question?: string;
    chartType?: TChartType;
    records?: Record<string, unknown>[];
    columns?: SemaphorResultColumn[];
    sql?: string;
    python?: string;
    cardConfig?: CardConfig;
    dataSource?: DataSource;
    suppressVisualRender?: boolean;
    executionResult?: SemaphorAnalyticsExecutionResult;
    dynamicVisual?: DashboardAssistantDynamicVisualArtifact;
    addToDashboard?: DashboardAssistantAddToDashboardPayload;
    warnings?: string[];
    diagnostics?: Record<string, unknown>;
    clarification?: {
        question: string;
        missingInputs: string[];
        candidateOptions?: Array<{
            label: string;
            value: unknown;
            description?: string;
        }>;
    };
};

export declare type DashboardAssistantDynamicVisualArtifact = {
    renderer: 'dynamic-visual';
    status: 'generated' | 'fallback' | 'failed';
    artifactId: string;
    parentArtifactId?: string;
    title: string;
    rendererCode?: string;
    question: string;
    provenance: 'query_spec' | 'sql' | 'sql+python';
    visualIntent?: TDynamicVisualIntent;
    assistantNote?: string;
    fallback: TDynamicVisualFallback;
    error?: {
        stage: string;
        message: string;
        details?: string[];
    };
};

export declare type DashboardAssistantInspectMode = 'dashboard_summary' | 'card_context' | 'artifact_context';

export declare type DashboardAssistantOperationKind = 'answer' | 'preview_visual' | 'explain_card' | 'add_visual';

export declare type DashboardAssistantToolOutput = {
    artifact: DashboardAssistantArtifact;
    executionResult?: SemaphorAnalyticsExecutionResult;
    message?: string;
    error?: string;
};

export declare type DashboardAssistantTurnContext = {
    selectedSheetId: string | null;
    visibleCards: Array<Record<string, unknown>>;
    activeFilters: unknown[];
    inlineFilters?: unknown[];
    interactionFilters?: unknown[];
    linkedInsightReplacements?: Record<string, unknown>;
    sourceRefs?: unknown[];
    fieldRefs?: unknown[];
};

export declare type DashboardAssistantVisualToolName = 'runDashboardAnalysis' | 'runAdvancedAnalysis' | 'renderDynamicVisual';

export declare type DashboardAssistantVisualToolPartType = (typeof DASHBOARD_ASSISTANT_VISUAL_TOOL_PART_TYPES)[number];

declare interface DatabaseEntityReference {
    connectionId: string;
    connectionType: ConnectionType;
    type: EntityType;
    dbObjectType?: string;
    dialect?: Dialect;
    database?: string;
    schema?: string;
    name: string;
}

declare type DatabaseEntityType = 'table' | 'view' | 'materialized view';

declare interface DataModelEntityReference extends DatabaseEntityReference {
    type: 'model';
    id: string;
    label: string;
    description: string;
}

declare interface DatasetEntityReference extends DatabaseEntityReference {
    type: 'dataset';
    datasetType: 'physical' | 'virtual';
    table?: string | null;
    datamodelId?: string | null;
    sql?: string | null;
    id: string;
    domainId: string;
    label: string;
    description?: string;
}

declare interface DataSource {
    connectionId: string;
    semanticDomainId?: string;
    connectionType: string;
    mode: 'database' | 'upload' | 'url' | 'semanticDomain';
    dbSelection?: {
        database: string;
        schema: string;
        entityType: DatabaseEntityType;
    };
    selectedEntities: SelectedEntities;
}

declare const DATE_FORMAT_VALUES: readonly ["MM-DD-YYYY", "YYYY-MM-DD", "MM/DD/YYYY", "DD/MM/YYYY", "MMMM DD, YYYY", "MMM DD, YYYY", "DD MMM YYYY", "YYYY-MM-DD HH:mm", "YYYY-MM-DD HH:mm:ss", "YYYY-MM-DD HH:mm Z", "YYYY-MM-DD HH:mm:ss Z", "Week of MMM DD, YYYY", "Week of MMMM DD, YYYY", "YYYY-WW", "MMM YYYY", "MMMM YYYY", "YYYY-MM", "MM/YYYY", "YYYY MMM", "Q1 YYYY", "YYYY Q1", "1st Quarter YYYY", "YYYY-Q1", "Quarter 1, YYYY", "YYYY", "YY", "custom"];

declare type DateFormatValue = (typeof DATE_FORMAT_VALUES)[number];

/**
 * Field configuration for detail table columns.
 * Unlike GroupByField, DetailField does not support aggregation or granularity.
 * Columns are selected and displayed as-is from the database.
 */
declare interface DetailField extends Omit<Field, 'role' | 'granularity'> {
    role: 'detail';
    dateFormat?: DateFormatValue;
    customFormat?: string;
    /**
     * Optional SQL expression for calculated detail fields.
     */
    expression?: string;
    /**
     * Formula metadata for calculated fields (used for token qualification).
     */
    calculatedFormula?: CalculatedFieldFormula;
}

declare interface DetailTableBackupConfig {
    groupByColumns?: GroupByField[];
    metricColumns?: MetricField[];
    pivotByColumns?: PivotByField[];
    sortByColumns?: SortByField[];
    rowAggregates?: Array<{
        label?: string;
        function: AggregateFunction;
        groupLevel: string | 'ALL';
    }>;
    columnAggregates?: Array<{
        label?: string;
        function: AggregateFunction;
        pivotLevel: string | 'ALL';
    }>;
    comparisonType?: 'none' | 'previous_period' | 'same_period_last_year' | 'target' | 'start_vs_end';
}

declare type Dialect = 'mysql' | 'postgres' | 'bigquery' | 'redshift' | 'snowflake' | 'clickhouse' | 'duckdb' | 'mssql';

declare interface DrillHierarchy {
    id: string;
    label?: string;
    type: 'static' | 'date';
    steps: DrillHierarchyStep[];
    default?: boolean;
    baseField?: Field;
}

declare interface DrillHierarchyStep {
    field: Field;
    mode: 'drillDown';
    preferredChartType?: TChartType;
    breadcrumbLabelTemplate?: string;
    retainFilters?: boolean;
    label?: string;
    linkedInsightId?: string;
}

declare type EntityType = 'table' | 'view' | 'materialized view' | 'model' | 'file' | 'dataset' | 'url' | 'upload';

declare interface Field {
    /**
     * Unique identifier for this field instance (for joins, UI state, etc.).
     * Should be unique within the context of the query or data model.
     * Example: 'orders.customer_id', 'expr_12345', etc.
     */
    id: string;
    /**
     * The physical/source column name in the database or data source.
     * Used for mapping to the underlying data model and SQL generation (unless overridden by expression).
     */
    name: string;
    /**
     * Human-friendly, localizable display name for the UI (table headers, chart axes, etc.).
     */
    label: string;
    /**
     * Unique, stable, machine-friendly reference name for SQL (AS alias), exports, and scripting.
     * If not provided, should be auto-generated from label or name.
     */
    alias?: string;
    sourceField?: string;
    qualifiedFieldName: string;
    dataType: string;
    description?: string;
    qualifiedEntityName?: string;
    dateFormat?: DateFormatValue;
    customFormat?: string;
    granularity?: TimeGranularity;
    entityId: string;
    entityName: string;
    entityType: EntityType;
    role?: 'groupby' | 'metric' | 'sortby' | 'pivotby' | 'detail';
    expression?: string;
    calculatedFormula?: CalculatedFieldFormula;
    format?: FormatSpec;
    aggregate?: AggregateFunction;
    fieldScope?: FieldScope;
}

declare type FieldScope = 'card' | 'sheet' | 'dashboard' | 'domain';

declare interface FileEntityReference extends DatabaseEntityReference {
    id: string;
    type: 'file' | 'url' | 'upload';
    label: string;
    description: string;
    originalName: string;
    file?: File;
    url?: string;
}

declare interface FilterCondition {
    id: string;
    field: Field;
    operator: Operator;
    value: FilterValue;
}

declare interface FilterGroup {
    id: string;
    logicalOperator: LogicalOperator;
    negate: boolean;
    conditions: FilterCondition[];
    groups: FilterGroup[];
}

declare type FilterValue = string | number | boolean | Date | null | [number, number] | [string, string] | string[] | number[];

declare type FormatSpec = {
    type: 'number' | 'currency' | 'percent' | 'percentage' | 'scientific';
    locale?: string;
    minimumFractionDigits?: number;
    maximumFractionDigits?: number;
    useGrouping?: boolean;
    prefix?: string;
    suffix?: string;
    negativeStyle?: 'minus' | 'parentheses';
    compact?: boolean;
    scale?: number;
    currency?: string;
    percentValueMode?: 'fraction' | 'whole';
} | {
    type: 'date';
    locale?: string;
    pattern?: string;
    relative?: boolean;
    timezone?: string;
    sourceTimezone?: string;
    prefix?: string;
    suffix?: string;
} | {
    type: 'duration';
    inputUnit?: 'millisecond' | 'second' | 'minute' | 'hour' | 'day';
    outputStyle?: 'compact' | 'digital' | 'long';
    largestUnit?: 'millisecond' | 'second' | 'minute' | 'hour' | 'day';
    smallestUnit?: 'millisecond' | 'second' | 'minute' | 'hour' | 'day';
    maxUnits?: number;
    prefix?: string;
    suffix?: string;
    negativeStyle?: 'minus' | 'parentheses';
} | {
    type: 'string';
    prefix?: string;
    suffix?: string;
};

declare interface GroupByField extends Field {
    role: 'groupby';
    granularity?: TimeGranularity;
    /**
     * Optional SQL expression for grouping (e.g., DATE_TRUNC('month', order_date)).
     * If present, used in SELECT and GROUP BY instead of just the column name.
     */
    expression?: string;
    timeDrillPath?: TimeDrillStep[];
    calculatedFormula?: CalculatedFieldFormula;
}

/**
 * Defines what element must be clicked to trigger an interaction.
 *
 * The `type` determines filtering behavior:
 * - 'metric': Captures intersection of ALL dimensions (e.g., country='USA' AND state='CA')
 * - 'attribute': Captures ONLY the clicked dimension (e.g., country='USA')
 *
 * Note: `trigger.type` is different from `field.type`:
 * - trigger.type = filtering behavior ('metric' | 'attribute')
 * - field.type = data type ('dimension' | 'metric' | 'measure')
 */
declare interface InteractionTrigger {
    /**
     * Determines filtering behavior when this trigger fires:
     * - 'metric': Capture intersection of all dimensions
     * - 'attribute': Capture only this specific dimension
     */
    type: 'metric' | 'attribute';
    /**
     * The field (metric or attribute) that must be clicked.
     * For multi-series charts: Use the specific metric Field with unique ID
     * (e.g., Field with id='count_of_orders')
     */
    field: Field;
}

export declare function isDashboardAssistantVisualToolPartType(value: string): value is DashboardAssistantVisualToolPartType;

declare interface Join {
    id: string;
    source: DatabaseEntityReference;
    target: DatabaseEntityReference;
    joinType: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
    joinKeyGroups: JoinKeyGroup[];
    sequence: number;
    relationshipId?: string;
    relationshipName?: string;
    relationshipCardinality?: 'one_to_one' | 'one_to_many' | 'many_to_one' | 'many_to_many';
    relationshipTraversalDirection?: 'forward' | 'reverse';
}

declare interface JoinKey {
    id?: string;
    source: Field;
    target: Field;
    operator: string;
}

declare interface JoinKeyGroup {
    id: string;
    operator: string;
    keys: JoinKey[];
}

declare interface JoinPlan {
    baseEntity: DatabaseEntityReference;
    joins: Join[];
}

declare type LogicalOperator = 'AND' | 'OR';

declare interface MetricField extends Field {
    role: 'metric';
    aggregate?: AggregateFunction;
    /**
     * Optional SQL expression for the metric (e.g., ship_date - order_date).
     * If present, used as aggregate(expression) instead of aggregate(name).
     */
    expression?: string;
    /**
     * Optional parameters for future extensibility (e.g., window functions).
     * * Example:
     * {
     aggregate: "SUM",
     name: "sales",
     parameters: {
     window: "PARTITION BY region ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW"
     }
     }

     {
     aggregate: "COUNT",
     name: "order_id",
     parameters: {
     filter: "status = 'Active'"
     }
     }
     */
    parameters?: {
        filters?: FilterGroup;
        windowTransform?: WindowTransform;
    };
    aliasTemplate?: string;
    valueAliases?: Record<string, string>;
    /**
     * Formula metadata for calculated fields (UI-only metadata)
     * This is supplementary data to help the UI display and edit calculated fields.
     * The `expression` field remains the source of truth for the backend.
     *
     * IMPORTANT: This metadata is ALWAYS updated atomically with the expression field.
     * Both are generated together from the same dialog inputs, preventing drift.
     */
    calculatedFormula?: CalculatedFieldFormula;
    /**
     * Indicates the metric expression must be evaluated after row-level filtering,
     * either because it contains an aggregate function directly or depends on a
     * pre-aggregated metric input.
     */
    isPreAggregated?: boolean;
    comparisonType?: 'none' | 'previous_period' | 'same_period_last_year' | 'start_vs_end' | 'target';
    comparisonDisplay?: 'column' | 'inline' | 'hover';
    targetValue?: number;
}

declare type Operator = '=' | '!=' | '>' | '>=' | '<' | '<=' | 'contains' | 'startsWith' | 'endsWith' | 'like' | 'not like' | 'in' | 'not in' | 'between' | 'not between' | 'isNull' | 'isNotNull';

declare interface PivotByField extends Field {
    role: 'pivotby';
}

declare type SelectedEntities = SelectedEntity[];

declare type SelectedEntity = DatabaseEntityReference | DataModelEntityReference | DatasetEntityReference | FileEntityReference;

declare type SemaphorAbsoluteTimeWindow = {
    kind: 'absolute';
    start: string;
    end: string;
};

declare type SemaphorAggregateFunction = 'SUM' | 'COUNT' | 'AVG' | 'MIN' | 'MAX' | 'MEDIAN' | 'DISTINCT';

declare type SemaphorAnalyticsExecutionResult = {
    intentId?: string;
    queryId?: string;
    status: SemaphorAnalyticsExecutionStatus;
    resultShape?: SemaphorAnalyticsResult['kind'] | 'period_change';
    intent?: SemaphorAnalyticsIntent;
    compiledQuery?: SemaphorCompiledQuery;
    fieldsUsed?: SemaphorExecutionFieldRef[];
    result?: SemaphorAnalyticsResult;
    validation: SemaphorAnalyticsValidationResult;
    coverage?: {
        answeredObligations: string[];
        missingObligations: string[];
        warnings?: SemaphorAnalyticsValidationIssue[];
    };
    missingFields?: string[];
    warnings?: string[];
    relationshipDiagnostics?: SemaphorRelationshipDiagnostics;
    population?: SemaphorAnalyticsPopulation;
    metadata?: Record<string, unknown>;
};

declare type SemaphorAnalyticsExecutionStatus = 'answered' | 'partial' | 'failed';

declare type SemaphorAnalyticsFieldRole = 'metric' | 'dateField' | 'dimension' | 'input' | 'source' | 'sql';

declare type SemaphorAnalyticsFilter = SemaphorAnalyticsValueFilter | SemaphorAnalyticsNullFilter;

declare type SemaphorAnalyticsFilterBase = {
    id?: string;
    field: SemaphorFieldRef;
    /**
     * Controls where the filter is applied in an aggregate query.
     *
     * `row` means pre-aggregation filtering (`WHERE`).
     * `aggregate` means post-aggregation filtering (`HAVING`) and is valid only
     * for measure fields the execution engine can aggregate safely.
     */
    scope?: 'row' | 'aggregate';
};

declare type SemaphorAnalyticsFilterOperator = SemaphorInputOperator | 'not_contains' | 'is_null' | 'is_not_null';

declare type SemaphorAnalyticsIntent = SemaphorMetricIntent | SemaphorRecordsIntent | SemaphorInputOptionsIntent | SemaphorSqlIntent;

declare type SemaphorAnalyticsNullFilter = SemaphorAnalyticsFilterBase & {
    operator: SemaphorAnalyticsNullFilterOperator;
    values?: never;
};

declare type SemaphorAnalyticsNullFilterOperator = 'is_null' | 'is_not_null';

declare type SemaphorAnalyticsPopulation = {
    scope: 'filtered_query';
    metrics: Record<string, number | string | null>;
};

declare type SemaphorAnalyticsRepairHint = {
    code: SemaphorAnalyticsValidationCode | string;
    message?: string;
    invalidField?: string;
    fieldRole?: SemaphorAnalyticsFieldRole;
    validMetricCandidates?: string[];
    validDateCandidates?: string[];
    validDimensionCandidates?: string[];
    recommendedNextStep: string;
};

declare type SemaphorAnalyticsResult = SemaphorMetricResult | SemaphorRecordsResult | SemaphorInputOptionsResult | SemaphorSqlResult;

declare type SemaphorAnalyticsResultBase = {
    intentId?: string;
    queryPath: SemaphorQueryPath;
    warnings?: string[];
    rowCount?: number;
    rowLimitExceeded?: boolean;
    limit?: number;
};

declare type SemaphorAnalyticsValidationCode = 'missing_source' | 'invalid_source_kind' | 'missing_semantic_domain' | 'missing_dataset_name' | 'missing_connection_id' | 'missing_table_name' | 'missing_sql' | 'missing_metric' | 'missing_record_fields' | 'missing_input_options_field' | 'invalid_metric' | 'invalid_metric_list' | 'invalid_date_field' | 'invalid_dimension' | 'invalid_metric_dimensions' | 'conflicting_sql' | 'sql_policy_violation' | 'unsupported_intent_for_adapter' | 'invalid_analytics_kind' | 'invalid_analytics_intent';

declare type SemaphorAnalyticsValidationIssue = SemaphorProtocolIssue & {
    code: SemaphorAnalyticsValidationCode | string;
    fieldRole?: SemaphorAnalyticsFieldRole;
    repairHint?: SemaphorAnalyticsRepairHint;
};

declare type SemaphorAnalyticsValidationResult = {
    ok: boolean;
    errors: SemaphorAnalyticsValidationIssue[];
    warnings: SemaphorAnalyticsValidationIssue[];
    repairHints: SemaphorAnalyticsRepairHint[];
};

declare type SemaphorAnalyticsValueFilter = SemaphorAnalyticsFilterBase & {
    operator?: SemaphorAnalyticsValueFilterOperator;
    values: unknown[];
};

declare type SemaphorAnalyticsValueFilterOperator = Exclude<SemaphorAnalyticsFilterOperator, 'is_null' | 'is_not_null'>;

declare type SemaphorCompiledQuery = {
    kind: 'config';
    queryId: string;
    source: SemaphorSourceRef;
    cardType: string;
    connectionId: string;
    cardConfig: unknown;
    cardDataSource: unknown;
    activeFilters?: SemaphorAnalyticsFilter[];
    rowLimit: number;
    analyticsIntent?: SemaphorAnalyticsIntent;
} | {
    kind: 'sql';
    queryId: string;
    source: Extract<SemaphorSourceRef, {
        kind: 'sql';
    }>;
    connectionId: string;
    dialect: SemaphorDialect;
    sql: string;
    parameters?: Record<string, unknown>;
    pythonCode?: string;
    activeFilters?: SemaphorAnalyticsFilter[];
    rowLimit: number;
    analyticsIntent?: SemaphorAnalyticsIntent;
};

declare type SemaphorDialect = 'postgres' | 'mysql' | 'mssql' | 'snowflake' | 'clickhouse' | 'bigquery' | 'redshift' | 'duckdb' | 'sqlite' | 'unknown';

declare type SemaphorExecutionFieldRef = SemaphorFieldRef & {
    semanticAggregate?: SemaphorAggregateFunction;
    effectiveAggregate?: SemaphorAggregateFunction;
    aggregateSource?: SemaphorMetricAggregateSource;
};

declare type SemaphorFieldRef = {
    name: string;
    label?: string;
    role?: 'dimension' | 'measure' | 'date' | 'id' | 'unknown';
    dataType?: 'string' | 'number' | 'boolean' | 'date' | 'datetime' | 'unknown';
    source?: SemaphorSourceRef;
    aggregate?: SemaphorAggregateFunction;
};

declare type SemaphorInputBinding = {
    inputId: string;
    field?: SemaphorFieldRef;
};

declare type SemaphorInputOperator = '=' | '!=' | 'in' | 'not_in' | 'contains' | 'between' | 'not_between' | '>' | '>=' | '<' | '<=';

declare type SemaphorInputOptionsIntent = {
    kind: 'inputOptions';
    version?: SemaphorProtocolVersion;
    id?: string;
    label?: string;
    source: SemaphorSourceRef;
    field: SemaphorFieldRef;
    search?: string;
    limit?: number;
};

declare type SemaphorInputOptionsResult = SemaphorAnalyticsResultBase & {
    kind: 'inputOptions';
    options: Array<{
        label: string;
        value: unknown;
        count?: number;
    }>;
};

declare type SemaphorMetricAggregateSource = 'semantic_model' | 'caller_override' | 'default_sum';

declare type SemaphorMetricAnalysis = {
    kind: 'period_change';
    orderBy?: 'absolute_change' | 'positive_change' | 'negative_change' | 'period';
    direction?: 'increase' | 'decrease' | 'both';
    timeWindow?: SemaphorTimeWindow;
};

declare type SemaphorMetricIntent = {
    kind: 'metric';
    version?: SemaphorProtocolVersion;
    id?: string;
    source: SemaphorSourceRef;
    metrics: SemaphorFieldRef[];
    primaryMetric?: SemaphorFieldRef;
    label?: string;
    dateField?: SemaphorFieldRef;
    timeGrain?: SemaphorTimeGrain;
    timeWindow?: SemaphorTimeWindow;
    dimensions?: SemaphorFieldRef[];
    filters?: SemaphorAnalyticsFilter[];
    comparison?: {
        kind: 'previous_period' | 'previous_year' | 'target';
        targetValue?: number;
    };
    analysis?: SemaphorMetricAnalysis;
    orderBy?: {
        field: SemaphorFieldRef;
        direction: 'asc' | 'desc';
    };
    inputs?: SemaphorInputBinding[];
    limit?: number;
};

declare type SemaphorMetricResult = SemaphorAnalyticsResultBase & {
    kind: 'metric';
    value: number | string | null;
    comparison?: {
        kind: NonNullable<SemaphorMetricIntent['comparison']>['kind'];
        value?: number | string | null;
        delta?: number | null;
        deltaPercent?: number | null;
    };
};

declare type SemaphorProtocolIssue = {
    code: string;
    message: string;
    path?: string;
};

declare type SemaphorProtocolVersion = 1;

declare type SemaphorQueryPath = 'query_spec' | 'sql' | 'sql_python';

declare type SemaphorRecordsIntent = {
    kind: 'records';
    version?: SemaphorProtocolVersion;
    source: SemaphorSourceRef;
    id?: string;
    label?: string;
    fields: SemaphorFieldRef[];
    dateField?: SemaphorFieldRef;
    timeGrain?: SemaphorTimeGrain;
    limit?: number;
    orderBy?: {
        field: SemaphorFieldRef;
        direction: 'asc' | 'desc';
    };
    inputs?: SemaphorInputBinding[];
};

declare type SemaphorRecordsResult = SemaphorAnalyticsResultBase & {
    kind: 'records';
    columns: SemaphorResultColumn[];
    records: Array<Record<string, unknown>>;
};

declare type SemaphorRelationshipDiagnostics = {
    status: SemaphorRelationshipDiagnosticStatus;
    requiredSources?: SemaphorSourceRef[];
    relationshipsUsed?: string[];
    missingSources?: string[];
    warnings?: string[];
    message?: string;
    recommendedNextStep?: string;
    joinPlanSummary?: {
        baseSource?: SemaphorSourceRef;
        joinedSources?: SemaphorSourceRef[];
        joinCount?: number;
    };
    fanoutRisk?: {
        status: 'none' | 'warning' | 'error' | 'unknown';
        message?: string;
    };
};

declare type SemaphorRelationshipDiagnosticStatus = 'not_required' | 'resolved' | 'missing' | 'ambiguous' | 'fanout_risk' | 'unknown';

declare type SemaphorRelativeTimeWindow = {
    kind?: 'relative';
    unit: 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
    value: number;
    anchor?: 'now' | 'latest_available';
    completeness?: 'include_partial' | 'complete_periods';
};

declare type SemaphorResultColumn = {
    /**
     * Stable row accessor for this result. Consumers should read values with
     * `row[column.key]`; labels are display-only and may change.
     */
    key: string;
    /**
     * Semantic/source field name before result-key disambiguation.
     */
    name: string;
    /**
     * Human-facing display label.
     */
    label: string;
    role?: SemaphorFieldRef['role'];
    dataType?: SemaphorFieldRef['dataType'];
    aggregate?: SemaphorFieldRef['aggregate'];
    source?: SemaphorFieldRef['source'];
};

declare type SemaphorSourceRef = {
    kind: 'semantic';
    domainId: string;
    datasetName: string;
    datasetId?: string;
    label?: string;
    connectionId?: string;
} | {
    kind: 'physical';
    connectionId: string;
    connectionType?: string;
    tableName: string;
    databaseName?: string;
    schemaName?: string;
    label?: string;
    dialect?: SemaphorDialect;
} | {
    kind: 'sql';
    connectionId: string;
    dialect?: SemaphorDialect;
    label?: string;
};

declare type SemaphorSqlIntent = {
    kind: 'sql';
    version?: SemaphorProtocolVersion;
    id?: string;
    label?: string;
    source: Extract<SemaphorSourceRef, {
        kind: 'sql';
    }>;
    sql: string;
    parameters?: Record<string, unknown>;
    pythonCode?: string;
    limit?: number;
    rationale?: string;
    fields?: SemaphorFieldRef[];
    inputs?: SemaphorInputBinding[];
};

declare type SemaphorSqlResult = SemaphorAnalyticsResultBase & {
    kind: 'sql';
    columns: SemaphorRecordsResult['columns'];
    records: SemaphorRecordsResult['records'];
    sqlShape?: {
        statementType?: string;
        explicitLimit?: number;
        hasPythonCode?: boolean;
    };
};

declare type SemaphorTimeGrain = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';

declare type SemaphorTimeWindow = SemaphorRelativeTimeWindow | SemaphorAbsoluteTimeWindow;

declare interface SortByField extends Field {
    role: 'sortby';
    direction: 'asc' | 'desc';
}

declare type TChartType = 'bar' | 'horizontalBar' | 'line' | 'area' | 'stackedArea' | 'combo' | 'pie' | 'doughnut' | 'radar' | 'polarArea' | 'bubble' | 'scatter' | 'stackedBar' | 'stackedLine' | 'table' | 'pivotTable' | 'aggregateTable' | 'detailTable' | 'tableBuilder' | 'kpi' | 'pyramid' | 'tornado' | 'range' | 'text' | 'map' | 'funnel' | 'bullet' | 'heatmap' | 'treemap' | 'custom';

declare type TDynamicCardPreferences = {
    renderer: 'dynamic-visual';
    artifactId?: string;
    parentArtifactId?: string;
    title?: string;
    rendererCode?: string;
    question?: string;
    provenance?: 'card-config' | 'query_spec' | 'sql' | 'sql+python';
    visualIntent?: TDynamicVisualIntent;
    assistantNote?: string;
    builtinDisplayOptions?: {
        showChrome?: boolean;
        allowScroll?: boolean;
    };
    fallback: TDynamicVisualFallback;
    error?: {
        stage: string;
        message: string;
        details?: string[];
    };
};

declare type TDynamicVisualFallback = {
    mode: 'chart' | 'table';
    chartType?: TChartType;
    reason: string;
};

declare type TDynamicVisualIntent = {
    primaryChartType?: TChartType | 'custom';
    layout: 'chart-only' | 'composite';
    includesKpis: boolean;
};

declare interface TimeDrillStep {
    granularity: TimeGranularity;
    next?: TimeGranularity;
    comparison?: 'previous_year' | 'previous_period';
    rollingWindow?: number;
}

declare type TimeGranularity = 'day' | 'week' | 'month' | 'quarter' | 'year' | 'hour' | 'minute' | 'second';

declare type TVisualizationMode = 'builtin' | 'dynamic';

declare type WindowFunction = 'running_total' | 'moving_average' | 'previous_period_delta' | 'percent_of_total';

declare interface WindowTransform {
    function: WindowFunction;
    orderBy?: {
        fieldId: string;
        direction?: 'asc' | 'desc';
    };
    partitionByFieldIds?: string[];
    frame?: 'unbounded_preceding';
    movingAverage?: {
        windowSize?: number;
        minPeriods?: number;
    };
    previousPeriodDelta?: {
        mode?: 'absolute' | 'percent';
    };
    percentOfTotal?: {
        scope?: 'grand_total' | 'partition_total';
        output?: 'fraction' | 'percent';
    };
}

export { }
