import { ColumnSizingState } from '@tanstack/react-table';
import { FontSpec } from 'chart.js';

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

declare type AIContext = {
    selectedEntities: SelectedEntities;
    fileAttachments?: FileAttachment[];
};

declare type AIScopeTable = {
    connectionId: string;
    connectionType: string;
    databaseName: string;
    schemaName: string;
    tableName: string;
    datamodelId: string;
    datamodelName: string;
};

export declare function applyDashboardChangePlan(input: {
    dashboard: TDashboard;
    changePlan: DashboardChangePlan;
    cardArtifacts: GeneratedDashboardCardArtifact[];
}): DashboardChangeCompileResult;

declare type AxisConfig = {
    enabled?: boolean;
    name?: {
        enabled: boolean;
        text?: string;
        /** Font size for the axis title */
        fontSize?: number;
        /** Font weight for the axis title */
        fontWeight?: 'normal' | 'bold';
    };
    position?: 'auto' | 'top' | 'bottom' | 'left' | 'right';
    labels?: {
        enabled: boolean;
        rotation?: 'auto' | 0 | 45 | 90 | -45 | -90;
    };
    formatMode?: 'inherit' | 'override';
    formatOptions?: TFormatOptions;
    scale?: {
        min?: number | 'auto';
        max?: number | 'auto';
        stepSize?: number | 'auto';
    };
};

declare interface BaseColumn {
    id: string;
    name: string;
    label?: string;
    type: ColumnType;
    table?: string;
}

declare type BaseCustomCard = {
    cardId: string;
    replaceDefault?: boolean;
};

declare type BaseFilter = {
    filterId: TFilter['id'];
    expression?: string;
    name: string;
    valueType: 'string' | 'number' | 'date' | 'boolean';
    connectionType?: 'database' | 'api';
    dataType?: string;
    fieldMeta?: FilterFieldMeta;
    semanticContext?: FilterSemanticContext;
};

declare type Breakpoint = 'lg' | 'md' | 'sm' | 'xs' | 'xxs';

declare type CacheConfig = {
    ttl: string;
    status: 'on' | 'on-refresh' | 'off';
};

/**
 * 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 CardInteractionConfig {
    /**
     * V2: Unified interactions array.
     * Each interaction includes a trigger that specifies what element must be clicked.
     */
    interactions?: PersistedInteraction[];
    allowedDrillTargets?: Field[];
    drillHierarchies?: DrillHierarchy[];
}

declare type CardWithContent = BaseCustomCard & {
    content: React.FC<{
        card: TCard;
    }>;
    footer?: React.FC<{
        card: TCard;
    }>;
};

declare type CardWithFooter = BaseCustomCard & {
    content?: React.FC<{
        card: TCard;
    }>;
    footer: React.FC<{
        card: TCard;
    }>;
};

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 ColorConfig = {
    segments: Record<string, string>;
};

declare type ColorRange = {
    start: number;
    end: number;
    color: string;
};

declare interface ColorRange_2 {
    min: number;
    max: number;
    color: string;
    applyTo: 'cell' | 'row';
}

declare interface ColumnSettings {
    type: 'none' | 'text' | 'number' | 'date' | 'badge' | 'link' | 'progress';
    inheritMetricFormat?: boolean;
    textAlign: 'left' | 'center' | 'right';
    width: number;
    minWidth?: number;
    maxWidth?: number;
    textOverflow?: 'ellipsis' | 'wrap' | 'clip';
    textWrap: ColumnTextWrap;
    /** Deprecated/inert. Totals are controlled by tablePrefs.tableStyle.totals. */
    totalsBehavior?: TotalsBehavior;
    totalsLabel?: string;
    numberFormat: {
        style: 'decimal' | 'currency' | 'percent' | 'scientific';
        currency: string;
        locale: string;
        minimumFractionDigits: number;
        maximumFractionDigits: number;
        useGrouping?: boolean;
        percentValueMode?: 'fraction' | 'whole';
        showDataBar: boolean;
        dataBarColor: string;
        dataBarMinValue?: number;
        dataBarMaxValue?: number;
        /**
         * When true, render the cell bg with a heatmap intensity tint scaled
         * across the column's value range. Composes with the existing text
         * color/color-range logic (tint is bg only). `showDataBar` takes
         * precedence when both are set — per the canonical design, a cell is
         * either a data-bar or a heatmap, never both.
         */
        showHeatmap?: boolean;
    };
    dateFormat: {
        format: string;
        useCustomFormat: boolean;
        customFormat: string;
        useRelativeTime: boolean;
        timezone?: string;
        sourceTimezone?: string;
    };
    linkFormat: LinkFormat;
    colorRanges: ColorRange_2[];
}

declare type ColumnSettingsMap = Record<string, ColumnSettings>;

declare type ColumnTextWrap = 'default' | 'truncate' | 'wrap' | 'nowrap' | 'preserve';

declare type ColumnType = 'string' | 'number' | 'date';

declare type ComparisonOperator = 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte';

export declare function compileDashboardFromPlan(input: {
    dashboardId: string;
    plan: DashboardPlan;
    cardArtifacts: GeneratedDashboardCardArtifact[];
}): DashboardCompileResult;

export declare type CompiledDashboardInputDefaults = {
    inputs: DashboardInput[];
    defaultInputValues?: DashboardInputValues;
};

export declare function compileResponsiveDashboardLayouts(inputs: DashboardLayoutCompileInput[]): DashboardLayoutCompileResult;

declare type ConditionalFormatCondition = {
    kind: 'comparison';
    columnId: string;
    operator: ComparisonOperator;
    value: unknown;
} | {
    kind: 'between';
    columnId: string;
    min: unknown;
    max: unknown;
    inclusive?: boolean;
} | {
    kind: 'blank';
    columnId: string;
    isBlank: boolean;
} | {
    kind: 'contains';
    columnId: string;
    value: string;
    caseSensitive?: boolean;
    exact?: boolean;
} | {
    kind: 'topBottom';
    columnId: string;
    direction: 'top' | 'bottom';
    count: number;
} | {
    kind: 'colorScale';
    columnId: string;
    range: 'auto' | 'manual';
    min?: number;
    mid?: number;
    max?: number;
    colors: {
        min: string;
        mid?: string;
        max: string;
    };
} | {
    kind: 'dataBar';
    columnId: string;
    range: 'auto' | 'manual';
    min?: number;
    max?: number;
    color: string;
    showValue?: boolean;
};

declare type ConditionalFormatRule = {
    id: string;
    name?: string;
    enabled?: boolean;
    target: ConditionalFormatTarget;
    condition: ConditionalFormatCondition;
    style?: ConditionalFormatStyle;
};

declare type ConditionalFormatStyle = {
    backgroundColor?: string;
    textColor?: string;
    fontWeight?: 'normal' | 'medium' | 'semibold' | 'bold';
    italic?: boolean;
    textDecoration?: 'none' | 'underline' | 'line-through';
    icon?: 'arrowUp' | 'arrowDown' | 'warning' | 'check' | 'x';
    dataBar?: {
        color: string;
        showValue: boolean;
    };
};

declare type ConditionalFormatTarget = {
    level: 'cell' | 'row';
    columnIds?: string[];
    conditionColumnId?: string;
    applyToColumnIds?: string[];
    tableParts?: TablePart[];
    rowRoles?: string[];
    depth?: number;
    includeTotals?: boolean;
    includeSubtotals?: boolean;
};

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

declare type ControlBinding = {
    controlId: string;
    target: 'sql_param';
    paramId: string;
} | {
    controlId: string;
    target: 'config_metric_selector';
    mapping: Record<string, StructuralMetricSelectorTarget>;
} | {
    controlId: string;
    target: 'config_field_selector';
    mapping: Record<string, StructuralFieldSelectorTarget>;
} | {
    controlId: string;
    target: 'config_aggregation';
    mapping: Record<string, string>;
} | {
    controlId: string;
    target: 'config_grain';
    mapping: Record<string, string>;
};

declare type ControlDashboardInput = DashboardInputBase & {
    kind: 'control';
    control: ControlDefinition;
};

declare type ControlDefinition = {
    id: string;
    label: string;
    scope: ControlScope;
    type: ControlType;
    source: ControlSource;
    initialValueStrategy: ControlInitialValueStrategy;
    defaultValue?: unknown;
    requiredAtExecution: boolean;
    hidden?: boolean;
    locked?: boolean;
    helpText?: string;
    placement?: 'toolbar' | 'card_header' | 'advanced';
    showLabel?: boolean;
    toolbarWidth?: number;
};

declare type ControlInitialValueStrategy = 'saved_default' | 'builtin' | 'embed_required' | 'schedule_snapshot';

declare type ControlOption = {
    value: string;
    label: string;
    presentation?: {
        granularity?: TimeGranularity;
        dateFormat?: DateFormatValue;
        customFormat?: string;
    };
};

declare type ControlScope = 'dashboard' | 'card';

declare type ControlSource = {
    kind: 'manual';
    options: ControlOption[];
} | {
    kind: 'dataset_values';
    fieldId: string;
    connectionId?: string;
} | {
    kind: 'field_allowlist';
    fieldIds: string[];
} | {
    kind: 'metric_allowlist';
    metricIds: string[];
} | SqlQueryControlSource;

declare type ControlType = 'enum' | 'multi_enum' | 'text' | 'number' | 'boolean' | 'date' | 'field_selector' | 'metric_selector' | 'aggregation_selector' | 'grain_selector';

declare type CustomCard = CardWithContent | CardWithFooter;

export declare const DASHBOARD_AUTHORING_BREAKPOINTS: readonly ["lg", "md", "sm", "xs", "xxs"];

export declare const DASHBOARD_AUTHORING_MAX_GENERATED_CARDS = 15;

declare type DashboardAIContext = AIContext & {
    mode?: DashboardAIContextMode;
};

declare type DashboardAIContextMode = 'auto' | 'fixed';

export declare type DashboardAuthoringBreakpoint = (typeof DASHBOARD_AUTHORING_BREAKPOINTS)[number];

export declare function dashboardAuthoringDatasetMatchesSource(dataset: unknown, source: SemaphorSourceRef | undefined): boolean;

export declare type DashboardAuthoringDatasetScopeIssue = 'invalid_dataset_count' | 'invalid_multi_dataset_scope';

export declare type DashboardAuthoringDatasetScopeResult = {
    ok: true;
} | {
    ok: false;
    issue: DashboardAuthoringDatasetScopeIssue;
};

export declare function dashboardAuthoringFieldsReferToSameTarget(left: SemaphorFieldRef | undefined, right: SemaphorFieldRef | undefined): boolean;

export declare type DashboardAuthoringIdFactory = {
    dashboardId?: () => string;
    sheetId?: () => string;
    frameId: (seed?: string) => string;
    cardId: (seed?: string) => string;
};

export declare function dashboardAuthoringSourceFromField(field: SemaphorFieldRef | undefined, fallback?: SemaphorSourceRef): MaterializableDashboardAuthoringSource | undefined;

export declare function dashboardAuthoringSourceKey(source: SemaphorSourceRef): string;

export declare function dashboardAuthoringSourcesReferToSameDataset(left: SemaphorSourceRef, right: SemaphorSourceRef): boolean;

export declare type DashboardAuthoringValidationResult = {
    ok: boolean;
    errors: DashboardPlanWarning[];
    warnings: DashboardPlanWarning[];
};

export declare type DashboardCardSizeIntent = 'kpi' | 'chart' | 'table' | 'text';

export declare type DashboardChangeCompileResult = {
    dashboard: TDashboard;
    warnings: DashboardPlanWarning[];
    skippedOperations: DashboardPlanWarning[];
};

export declare type DashboardChangeOperation = {
    kind: 'addCard';
    card: DashboardPlanCard;
} | {
    kind: 'addFilterInput';
    input: DashboardPlanFilterInput;
} | {
    kind: 'addCalculatedField';
    field: DashboardPlanCalculatedField;
} | {
    kind: 'reuseCalculatedField';
    fieldId: string;
    scope: 'sheet' | 'dashboard' | 'domain';
} | {
    kind: 'renameCard';
    cardId: string;
    title: string;
    description?: string;
} | {
    kind: 'reorderCards';
    cardIds: string[];
} | {
    kind: 'unsupported';
    requestedAction: string;
    reason: string;
};

export declare type DashboardChangePlan = {
    version: 1;
    id: string;
    dashboardId: string;
    title?: string;
    description?: string;
    datasets: SemaphorSourceRef[];
    operations: DashboardChangeOperation[];
    warnings?: DashboardPlanWarning[];
    unresolvedRequests?: string[];
};

export declare type DashboardCompileResult = {
    dashboard: TDashboard;
    warnings: DashboardPlanWarning[];
    skippedOperations: DashboardPlanWarning[];
};

declare type DashboardInput = FilterDashboardInput | ControlDashboardInput;

declare type DashboardInputBase = {
    id: string;
    label: string;
    variableName: string;
    description?: string;
    requiredAtExecution?: boolean;
    scope: DashboardInputScope;
    runtimeScope: DashboardInputRuntimeScope;
    presentation?: DashboardInputPresentation;
    exports?: DashboardInputExportKey[];
    compatibility?: DashboardInputCompatibilityMetadata;
};

declare type DashboardInputCompatibilityMetadata = {
    source: 'dashboardFilter';
    filterId: string;
} | {
    source: 'dashboardControl';
    controlId: string;
} | {
    source: 'cardInlineFilter';
    cardId: string;
    filterId: string;
} | {
    source: 'cardControl';
    cardId: string;
    controlId: string;
} | {
    source: 'documentInput';
    sheetId: string;
    inputId: string;
};

declare type DashboardInputExportKey = 'label' | 'value' | 'start' | 'end' | 'range';

declare type DashboardInputPresentation = {
    placement?: 'toolbar' | 'card_header' | 'advanced' | 'hidden';
    widthPx?: number;
    order?: number;
};

declare type DashboardInputRuntimeScope = 'shared' | 'perSheet' | 'perCard' | 'perDocumentSection';

declare type DashboardInputScope = {
    kind: 'allSheets';
    sheetKinds?: Array<'dashboard' | 'document'>;
} | {
    kind: 'sheets';
    sheetIds: string[];
} | {
    kind: 'cards';
    cardIds: string[];
} | {
    kind: 'documentSections';
    sheetId: string;
    sectionIds: string[];
};

declare type DashboardInputSlot = {
    status: 'set';
    value: DashboardInputValue;
} | {
    status: 'cleared';
};

declare type DashboardInputTextContent = Array<{
    type: 'text';
    value: string;
} | {
    type: 'variable';
    ref: DashboardInputVariableRef;
}>;

declare type DashboardInputValue = {
    kind: 'filter';
    filterValue: TFilterValue;
} | {
    kind: 'control';
    value: unknown;
};

declare type DashboardInputValues = {
    shared?: Record<string, DashboardInputSlot>;
    bySheetId?: Record<string, Record<string, DashboardInputSlot>>;
    byCardId?: Record<string, Record<string, DashboardInputSlot>>;
    byDocumentSectionId?: Record<string, Record<string, DashboardInputSlot>>;
};

declare type DashboardInputVariableRef = {
    source: 'dashboardInput';
    inputId: string;
    export: DashboardInputExportKey;
} | {
    source: 'dashboardInputAlias';
    variableName: string;
    export?: DashboardInputExportKey;
} | {
    source: 'documentMeta';
    key: 'generatedAt' | 'pageNumber' | 'pageCount';
};

export declare type DashboardLayoutCompileInput = {
    frameId: string;
    role: DashboardCardSizeIntent;
    priority: number;
};

export declare type DashboardLayoutCompileResult = PersistedFrameLayouts;

export declare type DashboardPlan = {
    version: 1;
    id: string;
    title: string;
    description?: string;
    datasets: SemaphorSourceRef[];
    sheets: DashboardPlanSheet[];
    filterInputs?: DashboardPlanFilterInput[];
    calculatedFields?: DashboardPlanCalculatedField[];
    warnings?: DashboardPlanWarning[];
    unresolvedRequests?: string[];
    deferredSuggestions?: string[];
};

export declare type DashboardPlanCalculatedField = {
    id: string;
    name: string;
    scope: 'card' | 'sheet' | 'dashboard' | 'domain';
    expression?: string;
    field?: Field;
    targetCardId?: string;
    reuseOnly?: boolean;
};

export declare type DashboardPlanCard = {
    id: string;
    frameId: string;
    title: string;
    description?: string;
    type: Exclude<TChartType, 'custom'>;
    role: DashboardCardSizeIntent;
    priority: number;
    section?: string;
    analyticsIntent?: SemaphorAnalyticsIntent;
    text?: string;
};

export declare type DashboardPlanFilterInput = {
    id: string;
    label: string;
    variableName: string;
    scope?: DashboardInputScope;
    filter: TFilter;
    defaultValue?: unknown;
};

export declare type DashboardPlanFromProtocolResult = {
    plan: DashboardPlan;
    warnings: DashboardPlanWarning[];
};

export declare function dashboardPlanFromSemaphorDashboardIntent(intent: SemaphorDashboardIntent): DashboardPlanFromProtocolResult;

export declare type DashboardPlanSheet = {
    id: string;
    title: string;
    description?: string;
    kind: 'dashboard';
    cards: DashboardPlanCard[];
};

export declare type DashboardPlanWarning = {
    code: string;
    message: string;
    cardId?: string;
};

export declare type DashboardSuggestion = {
    id: string;
    title: string;
    description: string;
    preview: DashboardSuggestionPreviewKind[];
    cardCount: number;
    filterCount: number;
    prompt: string;
    datasets?: Array<{
        name: string;
        label?: string;
    }>;
    relationshipHints?: string[];
};

export declare type DashboardSuggestionPreviewKind = 'kpi' | 'line' | 'bar' | 'donut' | 'table';

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];

declare type DateOptions = {
    locale: string;
    format: string;
    options: Intl.DateTimeFormatOptions;
};

declare type DateSelectionMode = 'range' | 'months';

declare type DateUnit = 'day' | 'week' | 'month' | 'quarter' | 'year';

declare type DefaultDateFilter = RelativeDateFilter | FixedMonthDefaultDateFilter;

/**
 * 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 type DisplayDataType = 'string' | 'date' | 'number' | 'html' | 'none';

declare type DocumentChartSection = {
    id: string;
    type: 'chart';
    title?: string;
    card: TCard;
    heightPx: number;
};

declare type DocumentControlInputDefinition = DocumentInputBase & {
    kind: 'control';
    control: ControlDefinition;
    exports?: DocumentInputExportKey[];
};

declare type DocumentDefinition = {
    version: 1;
    page: DocumentPageSetup;
    runtime?: DocumentRuntimeSettings;
    inputs?: DocumentInputDefinition[];
    defaultInputValues?: Record<string, unknown>;
    header?: DocumentHeaderRegion;
    footer?: DocumentFooterRegion;
    sections: DocumentSection[];
    theme?: DocumentTheme;
};

declare type DocumentFilterInputDefinition = DocumentInputBase & {
    kind: 'filter';
    filter: TFilter;
    exports?: DocumentInputExportKey[];
};

declare type DocumentFooterRegion = DocumentRegionBase & {
    region: 'footer';
    layout: {
        type: 'preset';
        preset: 'mvp_footer';
    };
};

declare type DocumentHeaderRegion = DocumentRegionBase & {
    region: 'header';
    layout: {
        type: 'preset';
        preset: 'mvp_header';
    };
};

declare type DocumentImageRegionBlock = DocumentRegionBlockBase & {
    type: 'image';
    role?: 'logo';
    src: string;
    alt?: string;
    widthPx?: number;
};

declare type DocumentInputBase = {
    id: string;
    label: string;
    variableName: string;
    requiredAtExecution: boolean;
    documentPlacement?: 'input_bar';
    description?: string;
};

declare type DocumentInputDefinition = DocumentFilterInputDefinition | DocumentControlInputDefinition;

declare type DocumentInputExportKey = 'label' | 'value' | 'start' | 'end' | 'range';

declare type DocumentPageBreakSection = {
    id: string;
    type: 'page_break';
};

declare type DocumentPageSetup = {
    size: 'letter' | 'a4';
    orientation: 'portrait' | 'landscape';
    margins: {
        top: number;
        right: number;
        bottom: number;
        left: number;
        unit: 'in' | 'mm';
    };
};

declare type DocumentRegionBase = {
    enabled: boolean;
    heightPx?: number;
    layout: DocumentRegionLayout;
    blocks: DocumentRegionBlock[];
};

declare type DocumentRegionBlock = DocumentTextRegionBlock | DocumentImageRegionBlock;

declare type DocumentRegionBlockBase = {
    id: string;
    area?: 'left' | 'center' | 'right' | 'title' | 'metadata' | 'note' | 'pageInfo';
};

declare type DocumentRegionLayout = {
    type: 'preset';
    preset: 'mvp_header' | 'mvp_footer';
};

declare type DocumentRuntimeSettings = {
    generatedAtFormat?: string;
};

declare type DocumentSection = DocumentTextSection | DocumentTableSection | DocumentChartSection | DocumentSpacerSection | DocumentPageBreakSection;

declare type DocumentSpacerSection = {
    id: string;
    type: 'spacer';
    heightPx: number;
};

declare type DocumentTableSection = {
    id: string;
    type: 'table';
    title?: string;
    card: TCard;
    table: {
        totalsRow?: boolean;
        columnFormatting?: Record<string, unknown>;
        repeatHeaderOnPageBreak?: boolean;
        rowHeightPx?: number;
    };
};

declare type DocumentTextContent = DocumentTextNode[];

declare type DocumentTextInlineFormat = {
    bold?: boolean;
    italic?: boolean;
    underline?: boolean;
};

declare type DocumentTextNode = {
    type: 'text';
    value: string;
    format?: DocumentTextInlineFormat;
} | {
    type: 'variable';
    ref: DocumentVariableRef;
    format?: DocumentTextInlineFormat;
};

declare type DocumentTextRegionBlock = DocumentRegionBlockBase & {
    type: 'text';
    role?: 'title' | 'metadata' | 'note' | 'pageInfo';
    content: DocumentTextContent;
    style?: DocumentTextStyle;
};

declare type DocumentTextSection = {
    id: string;
    type: 'text';
    content: DocumentTextContent;
    style?: DocumentTextStyle;
};

declare type DocumentTextStyle = {
    fontSize?: number;
    fontWeight?: 'normal' | 'medium' | 'semibold' | 'bold';
    color?: string;
    align?: 'left' | 'center' | 'right';
};

declare type DocumentTheme = {
    fontFamily?: string;
    primaryColor?: string;
};

declare type DocumentVariableRef = {
    source: 'input';
    inputId: string;
    export: DocumentInputExportKey;
} | {
    source: 'documentMeta';
    key: 'generatedAt' | 'pageNumber' | 'pageCount';
};

declare interface DrillDownInteraction {
    mode: 'drillDown';
    /**
     * What element must be clicked to trigger this drill-down.
     * Optional during configuration, but must be defined before execution.
     */
    trigger?: InteractionTrigger;
    filterFields: Field[];
    hierarchyId?: string;
    label?: string;
}

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 interface DrillThroughInteraction {
    mode: 'drillThrough';
    /**
     * What element must be clicked to trigger this drill-through.
     * @migration Optional during migration. Will be required in V2.
     */
    trigger?: InteractionTrigger;
    filterFields: Field[];
    targetDashboardId: string;
    /**
     * How to pass context to the target dashboard
     * @default 'interactionFilters'
     */
    contextMode?: 'interactionFilters' | 'full' | 'none';
    label?: string;
}

declare interface DrillToDetailInteraction {
    mode: 'drillToDetail';
    /**
     * What element must be clicked to trigger this drill to detail.
     * @migration Optional during migration. Will be required in V2.
     */
    trigger?: InteractionTrigger;
    filterFields: Field[];
    detailFields?: Field[];
    sortBy?: SortByField[];
    limit?: number;
    detailTitle?: string;
    /**
     * Target insight ID to navigate to
     */
    targetInsightId?: string;
    /**
     * How to pass context to the target insight
     * @default 'interactionFilters'
     */
    contextMode?: 'interactionFilters' | 'full' | 'none';
    /**
     * How to display the insight
     * @default 'modal'
     */
    displayMode?: 'modal' | 'replace-card';
    label?: string;
}

declare interface DrillToURLInteraction {
    mode: 'drillToURL';
    /**
     * What element must be clicked to trigger this URL drill.
     */
    trigger?: InteractionTrigger;
    filterFields: Field[];
    /**
     * URL template with placeholders (e.g., 'https://example.com/product/{{product_id}}')
     */
    urlTemplate: string;
    /**
     * List of parameters used in the URL template
     */
    parameters: URLParameter[];
    /**
     * Whether to URL-encode parameter values
     * @default true
     */
    encodeParameters?: boolean;
    /**
     * Custom label for this interaction in the menu
     */
    label?: string;
}

declare interface DrillUpInteraction {
    mode: 'drillUp';
    /**
     * What element must be clicked to trigger this drill-up.
     * For synthetic drill-up interactions, this is inherited from the original drill-down.
     */
    trigger?: InteractionTrigger;
    /**
     * The hierarchy ID to reference for display purposes.
     * Used to show the parent level name in the interaction menu.
     */
    hierarchyId?: string;
    label?: string;
}

declare interface DynamicDrillInteraction {
    mode: 'dynamicDrill';
    /**
     * What element must be clicked to trigger this dynamic drill menu.
     * When this trigger fires, user sees a menu of available fields to explore.
     */
    trigger?: InteractionTrigger;
    /**
     * List of fields available for dynamic exploration.
     * User can choose which field to drill into at runtime.
     * Only drillable fields (string, boolean types) should be included.
     */
    availableFields: Field[];
    /**
     * Optional label for the menu item.
     * Defaults to "Explore Fields" if not specified.
     */
    label?: string;
    /* Excluded from this release type: drillField */
}

declare type EmailSettings = {
    companyName: string;
    dashboardUrl: string;
    supportEmail: string;
    senderTitle: 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 type FileAttachment = {
    id: string;
    name: string;
    size: number;
    type: string;
    data?: string;
    url?: string;
    preview?: string;
    uploadProgress?: number;
};

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

declare interface FilterByColumn extends BaseColumn {
    role: 'filter';
    operators?: string[];
    mode?: 'include' | 'exclude';
    sql?: string;
    fetchValues?: boolean;
    fetchLimit?: number;
    valueSource?: 'distinct' | 'static' | 'range';
    staticValues?: string[];
}

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

declare type FilterDashboardInput = DashboardInputBase & {
    kind: 'filter';
    filter: TFilter;
};

/**
 * Display mode for individual filters
 * - 'canvas': Filter displayed as a draggable card on the dashboard canvas
 * - 'toolbar': Filter displayed in the compact toolbar
 * - 'inherit': Use the dashboard's filterLayout.displayMode setting (default)
 */
declare type FilterDisplayMode = 'canvas' | 'toolbar' | 'inherit';

declare type FilterFieldMeta = Pick<Field, 'name' | 'qualifiedFieldName'> & Partial<Pick<Field, 'id' | 'qualifiedEntityName' | 'entityId' | 'dataType' | 'role' | 'fieldScope'>> & {
    entityName?: Field['entityName'];
    entityType?: string;
    expression?: string;
    calculatedFormula?: CalculatedFieldFormula;
};

declare type FilterForBetween = BaseFilter & {
    operation: 'between' | 'not between';
    values: [number, number];
};

declare type FilterForCompare = BaseFilter & {
    operation: '>' | '<' | '>=' | '<=';
    values: [number];
};

declare type FilterForDate = BaseFilter & {
    operation: 'between' | 'not between' | '=' | '!=' | '>' | '<' | '>=' | '<=';
    values: [Date | string, Date | string] | [Date | string];
    relativeMeta?: RelativeDateFilter;
};

declare type FilterForEqual = BaseFilter & {
    operation: '=' | '!=';
    values: [string | number];
};

declare type FilterForIn = BaseFilter & {
    operation: 'in' | 'not in';
    values: (string | number)[];
};

declare type FilterForNull = BaseFilter & {
    operation: 'is null' | 'is not null';
    values: [];
};

declare type FilterForString = BaseFilter & {
    operation: 'like' | 'not like';
    values: [string];
};

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

declare type FilterKind = 'field' | 'global-date';

/**
 * Filter layout settings for controlling how dashboard filters are displayed
 */
declare type FilterLayoutSettings = {
    /**
     * Display mode for filters
     * - 'canvas': Filters displayed as draggable/resizable cards on the dashboard canvas (default)
     * - 'toolbar': Filters displayed in a compact horizontal toolbar below dashboard controls
     */
    displayMode?: 'canvas' | 'toolbar';
    /**
     * Whether the toolbar should wrap filters to multiple lines
     * - false: Horizontal scroll when filters overflow (default)
     * - true: Wrap to multiple lines
     */
    toolbarWrap?: boolean;
    /**
     * Whether to show a download button in the filter toolbar
     * Useful when embedding Dashboard component without Surfboard's controls
     */
    showDownloadButton?: boolean;
    /**
     * Mixed toolbar item order for dashboard-level filter and control chips.
     * Values use prefixed ids like `filter:<id>` and `control:<id>`.
     */
    toolbarItemOrder?: string[];
};

declare type FilterLocation = 'dashboard' | 'frame' | 'sheet' | undefined;

declare type FilterOnClick = {
    expression?: string;
    columnIndex: number;
};

declare type FilterSemanticContext = {
    semanticDomainId?: string;
    selectedEntities?: unknown[];
    connectionId?: string;
    connectionType?: string;
};

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

export declare function findDashboardAuthoringDatasetForSource(datasets: readonly SemaphorSourceRef[], source: SemaphorSourceRef | undefined): SemaphorSourceRef | undefined;

/**
 * Absolute fixed month/year default used by Month Picker defaults.
 * - `month` is 0-indexed (0=January, 11=December) to align with MonthPicker.
 */
declare type FixedMonthDefaultDateFilter = {
    mode: 'fixed';
    unit: 'month';
    year: number;
    month: 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;
};

export declare type GeneratedDashboardCardArtifact = {
    planCardId: string;
    frameId: string;
    card: TCard;
    queryValidated?: boolean;
    warnings?: DashboardPlanWarning[];
};

export declare function getDashboardAuthoringCardSource(card: Pick<DashboardPlanCard, 'analyticsIntent'>): SemaphorSourceRef | undefined;

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

declare interface GroupByColumn extends BaseColumn {
    role: 'groupby';
    granularity?: Granularity;
    format?: 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;
}

declare type HtmlOptions = {
    html: string;
};

declare interface InlineDrillInteraction {
    mode: 'inlineDrill';
    /**
     * What element must be clicked to trigger this inline drill.
     * @migration Optional during migration. Will be required in V2.
     */
    trigger?: InteractionTrigger;
    filterFields: Field[];
    /**
     * When to fetch the detailed data
     * @default 'lazy'
     */
    fetchMode?: 'lazy' | 'preloaded';
    /**
     * Maximum number of records to show (0 for unlimited)
     * @default 100
     */
    inlineLimit?: number;
    /**
     * How to display the detailed records
     * @default 'table'
     */
    displayMode?: 'table' | 'list' | 'cards';
    /**
     * Whether to show records in a modal overlay
     * @default false
     */
    showInModal?: boolean;
    /**
     * Whether to allow exporting the detailed records
     * @default true
     */
    allowExport?: boolean;
    label?: string;
}

/**
 * Unified Interaction type (V2)
 * Combines all interaction types into a single union for the new interactions array.
 */
declare type Interaction = ClickFilterInteraction | DrillDownInteraction | DrillThroughInteraction | DrillToDetailInteraction | DrillToURLInteraction | InlineDrillInteraction | DrillUpInteraction | DynamicDrillInteraction;

declare interface InteractionTargetOverride {
    applyToCardIds?: string[] | null;
    excludeCardIds?: string[] | null;
}

/**
 * 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 isMaterializableDashboardAuthoringSource(value: unknown): value is MaterializableDashboardAuthoringSource;

export declare function isSemaphorSourceRef(value: unknown): value is SemaphorSourceRef;

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 interface LinkFormat {
    urlTemplate: string;
    labelType: 'value' | 'static' | 'column';
    staticLabel?: string;
    labelColumn?: string;
    openInNewTab: boolean;
}

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

export declare type MaterializableDashboardAuthoringSource = Extract<SemaphorSourceRef, {
    kind: 'semantic' | 'physical';
}>;

export declare function mergeDashboardAuthoringSources(sources: readonly SemaphorSourceRef[]): SemaphorSourceRef[];

declare interface MetricColumn extends BaseColumn {
    role: 'metric';
    aggregate: AggregateFunction;
    aliasTemplate?: string;
}

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 NoneOptions = {};

declare type NumberAxisFormat = {
    decimalPlaces?: number;
    minimumFractionDigits?: number;
    maximumFractionDigits?: number;
    suffix?: string;
    currency?: string;
    locale?: string;
    useGrouping?: boolean;
    percentValueMode?: 'fraction' | 'whole';
};

declare type NumberOptions = {
    locale: string;
    currency?: string;
    options: Intl.NumberFormatOptions;
    colorRanges?: ColorRange[];
};

declare type OldFilterValue = string | number | null | (string | number)[] | RangeValue;

declare type Operation = '=' | '>' | '<' | '>=' | '<=' | '!=' | 'in' | 'not in' | 'like' | 'not like' | 'between' | 'not between' | 'is null' | 'is not null';

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

declare type OptionsMap = {
    number: NumberOptions;
    string: StringOptions;
    date: DateOptions;
    html: HtmlOptions;
    none: NoneOptions;
};

declare interface OrderBy {
    columnId: string;
    direction: 'asc' | 'desc';
}

/**
 * Pagination configuration for table queries
 */
declare interface PaginationConfig {
    page: number;
    pageSize: number;
}

declare type PersistedFrameLayoutItem = {
    i: string;
    x: number;
    y: number;
    w: number;
    h: number;
    minW?: number;
    minH?: number;
    maxW?: number;
    maxH?: number;
    static?: boolean;
    isResizable?: boolean;
    isDraggable?: boolean;
};

declare type PersistedFrameLayouts = Partial<Record<Breakpoint, PersistedFrameLayoutItem[]>>;

declare type PersistedInteraction = Interaction & {
    id?: string;
};

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

export declare function preferDashboardAuthoringSourceMetadata(current: SemaphorSourceRef, next: SemaphorSourceRef): SemaphorSourceRef;

export declare function preferredDashboardAuthoringSource(sources: readonly SemaphorSourceRef[]): SemaphorSourceRef | undefined;

declare interface QueryConfig {
    groupByColumns?: GroupByColumn[];
    pivotColumns?: GroupByColumn[];
    metricColumns?: MetricColumn[];
    filterColumns?: FilterByColumn[];
    filters?: QueryFilter[];
    limit?: number;
    orderBy?: OrderBy[];
}

declare type QueryFilter = {
    filterColumnName: string;
    filterValue: OldFilterValue;
};

declare type RangeValue = {
    gte?: string | number;
    lte?: string | number;
    lt?: string | number;
    gt?: string | number;
};

declare type RelativeDateFilter = {
    mode: 'last';
    n: number;
    unit: DateUnit;
    complete?: boolean;
} | {
    mode: 'this';
    unit: DateUnit;
    toDate?: boolean;
} | {
    mode: 'previous';
    unit: DateUnit;
} | {
    mode: 'between';
    unit: DateUnit;
    from: number;
    to: number;
};

export declare function resolveDashboardAuthoringSource({ explicitSource, field, defaultSource, fallbackSources, }: {
    explicitSource?: unknown;
    field?: SemaphorFieldRef;
    defaultSource?: SemaphorSourceRef;
    fallbackSources?: readonly SemaphorSourceRef[];
}): MaterializableDashboardAuthoringSource | undefined;

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 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 SemaphorAnalyticsValueFilter = SemaphorAnalyticsFilterBase & {
    operator?: SemaphorAnalyticsValueFilterOperator;
    values: unknown[];
};

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

declare type SemaphorDashboardIntent = {
    version: SemaphorProtocolVersion;
    kind: 'dashboard';
    title: string;
    description?: string;
    inputs?: SemaphorInputSpec[];
    sections: SemaphorDashboardSectionIntent[];
};

declare type SemaphorDashboardSectionIntent = {
    id?: string;
    title: string;
    description?: string;
    views: SemaphorDashboardViewIntent[];
};

declare type SemaphorDashboardViewIntent = {
    id?: string;
    title: string;
    description?: string;
    presentation: SemaphorViewPresentation;
    analytics?: SemaphorAnalyticsIntent;
    text?: string;
};

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

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 SemaphorInputScope = {
    level: 'dashboard';
    excludeViewIds?: string[];
} | {
    level: 'section';
    sectionId: string;
    excludeViewIds?: string[];
} | {
    level: 'view';
    viewIds: string[];
};

declare type SemaphorInputSpec = {
    id: string;
    kind: 'filter' | 'control';
    label: string;
    field: SemaphorFieldRef;
    operator?: SemaphorInputOperator;
    multi?: boolean;
    defaultValue?: unknown;
    scope?: SemaphorInputScope;
};

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 SemaphorProtocolVersion = 1;

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 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 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 SemaphorTimeGrain = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';

declare type SemaphorTimeWindow = SemaphorRelativeTimeWindow | SemaphorAbsoluteTimeWindow;

declare type SemaphorViewPresentation = {
    kind: 'kpi';
    format?: 'number' | 'currency' | 'percent' | 'duration';
} | {
    kind: 'lineChart' | 'barChart' | 'areaChart';
    x?: string;
    y?: string[];
} | {
    kind: 'table';
    columns?: string[];
} | {
    kind: 'text';
};

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

declare type SqlQueryControlSource = {
    kind: 'sql_query';
    connectionId: string;
    sql: string;
    valueColumn: string;
    labelColumn?: string;
};

declare type StringOptions = {
    maxLength?: number;
};

declare type StructuralFieldSelectorTarget = GroupByField;

declare type StructuralMetricSelectorTarget = MetricField;

/**
 * Style propeerites for the dashboard
 */
declare type StyleProps = {
    /** Theme for dashboard background */
    canvasTheme?: 'clear' | 'muted' | string;
    /** css class for `dashboard-panel` */
    dashboardPanel?: string;
    /** css class for `dashboard-tabs-container` */
    dashboardTabsContainer?: string;
    /** css class for `dashboard-card` */
    /** css class for `dashboard-card-container` */
    dashboardCardContainer?: string;
    dashboardCard?: string;
    /** grid-layout config */
    /**
     * Border radius for the control inputs such as filter input, tabs, date picker, etc.
     */
    controlInputRadius?: number;
    /**
     * Border radius for the cards
     */
    cardBorderRadius?: number;
    gridLayout?: {
        /** css class for `react-grid-layout` */
        className?: string;
        margin?: [number, number];
    };
    /** chart config */
    chart?: {
        /** chart font config */
        font?: Partial<FontSpec>;
        dataset?: any;
        /** chart options */
        options?: any;
    };
    table?: {
        tableHeaderColor?: string;
    };
};

declare type TableBaseFormatting = {
    version: TableFormattingVersion;
    tableParts?: Partial<Record<TablePart, TableBaseStyle>>;
    columns?: Record<string, {
        body?: TableBaseStyle;
        header?: TableBaseStyle;
        footer?: TableBaseStyle;
    }>;
};

declare type TableBaseStyle = {
    fontWeight?: 'normal' | 'medium' | 'semibold' | 'bold';
    italic?: boolean;
    textColor?: string;
    backgroundColor?: string;
    textDecoration?: 'none' | 'underline' | 'line-through';
};

declare type TableConditionalFormatting = {
    version: TableFormattingVersion;
    rules: ConditionalFormatRule[];
};

/**
 * Row rhythm for the whole table. Authors pick one per card; undefined
 * falls back to 'compact' (the canonical default — dense scanning, matches
 * the Linear-style spec). Drives row padding, cell font size, and header
 * font size via a shared density spec in DataTable.
 */
declare type TableDensity = 'dense' | 'compact' | 'standard' | 'comfortable' | 'spacious';

declare type TableFormattingVersion = 1;

declare type TableGridLines = 'none' | 'outer' | 'inner' | 'horizontal' | 'vertical' | 'top' | 'right' | 'bottom' | 'left' | 'full';

declare type TableHeaderStyle = 'plain' | 'filled' | 'accent';

declare type TablePart = 'body' | 'header' | 'footer' | 'subtotal' | 'grandTotal';

declare type TablePreferences = {
    columnSettingsMap?: ColumnSettingsMap;
    baseFormatting?: TableBaseFormatting;
    conditionalFormatting?: TableConditionalFormatting;
    selectColumnVisible?: boolean;
    columnVisibility?: Record<string, boolean>;
    columnSizing?: ColumnSizingState;
    pageSize?: number;
    enableDevModePagination?: boolean;
    forceClientPagination?: boolean;
    density?: TableDensity;
    tableStyle?: TableStylePreferences;
};

declare type TableStylePreferences = {
    headerStyle?: TableHeaderStyle;
    headerBackgroundColor?: string;
    headerTextColor?: string;
    headerWrapText?: boolean;
    stripedRows?: boolean;
    gridLines?: TableGridLines;
    wrapText?: boolean;
    totals?: TableTotalsStylePreferences;
};

declare type TableTotalsFontWeight = 'normal' | 'medium' | 'semibold' | 'bold';

declare type TableTotalsStylePreferences = {
    enabled?: boolean;
    backgroundColor?: string;
    textColor?: string;
    fontWeight?: TableTotalsFontWeight;
    borderTop?: boolean;
    borderTopStyle?: 'solid' | 'dashed' | 'dotted' | 'double';
    borderTopColor?: string;
};

/**
 * Target column configuration for multi-field filters.
 * Allows a single filter to target multiple columns from the SAME table,
 * with users selecting which column to filter at runtime.
 *
 * Note: Cross-table filtering is not supported. All target columns must
 * be from the same table as the filter's primary table. For cross-table
 * date filtering, create separate filters or use a shared date dimension.
 */
declare type TargetColumn = {
    /** Column name (e.g., "shipping_date") - must be from the filter's table */
    column: string;
    /** Display label shown in the dropdown (e.g., "Shipping Date") */
    label: string;
};

/** Global bar style configuration */
declare type TBarStyleConfig = {
    /** Default border radius for all bars - 0-20 pixels */
    borderRadius?: number;
    /** Default border width for all bars - 0-5 pixels */
    borderWidth?: number;
    /** Default bar width as percentage of category width (0.1-1.0) */
    barPercentage?: number;
    /** Default category width as percentage of available space (0.1-1.0) */
    categoryPercentage?: number;
};

declare type TBaseQuery = {
    id: string;
    name: string;
    connectionId: string;
    sql: string;
    context?: string;
    description?: string;
};

declare type TBubbleScatterConfig = {
    /**
     * Explicit key for X-axis metric. Falls back to auto-detection.
     */
    xMetricKey?: string;
    /**
     * Explicit key for Y-axis metric. Falls back to auto-detection.
     */
    yMetricKey?: string;
    /**
     * Explicit key for radius metric (bubble only). Falls back to auto-detection.
     */
    radiusMetricKey?: string;
    /**
     * Key for point labels (first dimension).
     */
    labelKey?: string;
    /**
     * Whether to group points into series. Defaults to auto-detect in card config mode.
     */
    enableGrouping?: boolean;
    /**
     * Key for series grouping. Can be any data type (string, number, date).
     */
    groupKey?: string;
    /**
     * Scaling mode for bubble radius.
     */
    radiusScale?: 'linear' | 'sqrt' | 'fixed';
    /**
     * Fixed radius value when radiusScale is 'fixed' or for scatter charts.
     */
    fixedRadius?: number;
    /**
     * Minimum radius for bubble scaling.
     */
    minRadius?: number;
    /**
     * Maximum radius for bubble scaling.
     */
    maxRadius?: number;
};

declare type TBulletConfig = {
    /**
     * Orientation of the bullet chart. Defaults to horizontal.
     */
    orientation?: 'horizontal' | 'vertical';
    /**
     * Explicit metric key to use for target markers. Falls back to the next metric column.
     */
    targetMetricKey?: string;
    /**
     * Optional comparative metric (e.g., previous period).
     */
    comparativeMetricKey?: string;
    /**
     * When true, disables automatic comparative assignment even if a metric exists.
     */
    disableAutoComparative?: boolean;
    /**
     * Mapping of qualitative range names to column keys.
     */
    rangeKeys?: TBulletRangeKeys;
    /**
     * Static range values if columns are not provided.
     */
    ranges?: TBulletRangeValues;
    /**
     * Global target value if a column is not provided.
     */
    targetValue?: number;
    /**
     * Show numeric labels on the actual bar. Default true.
     */
    showValueLabels?: boolean;
    /**
     * Treat provided range values as percentages (0-1) when true.
     */
    rangesArePercentages?: boolean;
    /**
     * Whether qualitative ranges should be rendered.
     */
    showRanges?: boolean;
    /**
     * Display labels for qualitative ranges.
     */
    rangeLabels?: TBulletRangeLabelOverrides;
};

declare type TBulletRangeKeys = Partial<Record<TBulletRangeLabels, string>>;

declare type TBulletRangeLabelOverrides = Partial<Record<TBulletRangeLabels, string>>;

declare type TBulletRangeLabels = 'poor' | 'satisfactory' | 'good';

declare type TBulletRangeValues = Partial<Record<TBulletRangeLabels, number>>;

declare type TCard = {
    id: string;
    title: string;
    tabTitle?: string;
    displayTab?: boolean;
    description?: string;
    info?: string;
    connectionId?: string;
    datamodelId?: string;
    type: TChartType;
    sql?: string;
    python?: string;
    dataSource?: DataSource;
    config?: CardConfig;
    interactionConfig?: CardInteractionConfig;
    linkedSourceCardId?: string;
    linkedInteractionTargetOverrides?: Record<string, InteractionTargetOverride>;
    paginationConfig?: PaginationConfig;
    queryConfig?: QueryConfig;
    customCfg?: any;
    preferences?: TCardPreferences;
    customCardPreferences?: TCustomCardPreferences;
    visualizationMode?: TVisualizationMode;
    dynamicCardPreferences?: TDynamicCardPreferences;
    lastSelectedDatabase?: string;
    lastSelectedDatamodelId?: string;
    lastSelectedSchema?: string;
    lastSelectedTable?: string;
    refreshInterval?: string;
    /**
     * Card-specific display preferences that override dashboard-level preferences.
     * If not specified, the card will use the dashboard's display preferences.
     */
    displayPreferences?: VisualDisplayPreferences;
    /**
     * Inline filter definitions for this card.
     * Configured by editors via the visual editor settings.
     */
    inlineFilters?: TInlineFilter[];
    /**
     * Card-scoped calculated fields that should remain available even when they
     * are not actively selected in the chart configuration.
     */
    calculatedFields?: Field[];
    /**
     * Card-scoped control definitions for this card.
     */
    controls?: ControlDefinition[];
    /**
     * Per-card bindings that connect dashboard or card controls to this card's runtime targets.
     */
    controlBindings?: ControlBinding[];
};

declare type TCardPreferences = {
    onClickFilter?: FilterOnClick[];
    filterOnClick?: boolean;
    filterOnClickField?: string;
    filterOnClickColumnIndex?: number;
    sortChart?: 'asc' | 'desc' | 'none';
    formatNumber?: {
        decimalPlaces?: number;
        minimumFractionDigits?: number;
        maximumFractionDigits?: number;
        currency?: string;
        locale?: string;
        suffix?: string;
        prefix?: string;
        useGrouping?: boolean;
        percentValueMode?: 'fraction' | 'whole';
        enabled?: boolean | string;
        colorRanges?: ColorRange[];
    };
    numberAxisFormat?: NumberAxisFormat;
    datasetOptions?: TDatasetOptions[];
    chartOptions?: TChartOptions;
    columnSettings?: TColumnSetting<DisplayDataType>[];
    colorConfig?: ColorConfig;
    xAxisConfig?: AxisConfig;
    yAxisConfig?: AxisConfig;
    secondaryYAxisConfig?: AxisConfig;
    tooltipConfig?: TTooltipFormatConfig;
    dataLabelsConfig?: TDataLabelsConfig;
    bulletConfig?: TBulletConfig;
    heatmapConfig?: THeatmapConfig;
    bubbleScatterConfig?: TBubbleScatterConfig;
    funnelConfig?: TFunnelConfig;
    /** Global line/point style defaults for line and area charts */
    lineStyleConfig?: {
        lineStyle?: TLineStyle;
        pointRadius?: number;
        pointStyle?: TPointStyle;
    };
    /** Global bar style defaults for bar charts */
    barStyleConfig?: TBarStyleConfig;
    tablePrefs?: TablePreferences;
    allowDownload?: boolean;
    customVisualCode?: string;
    textVisualOptions?: {
        isDynamicText?: boolean;
        /**
         * Legacy structured content with dashboard-input variable refs.
         * Authored via the plain-text ContentEditableText editor. New cards
         * use `richContent` instead; this stays for backward compatibility
         * and is never set on a card that has `richContent`.
         */
        content?: DashboardInputTextContent;
        /**
         * Editor-agnostic rich content authored via the Lexical-based
         * editor. When this is present, the card renders via the rich-
         * content path on both the dashboard surface and inside the visual
         * editor. When absent (and `description` is set), the card falls
         * back to the legacy HTML-string render path.
         */
        richContent?: TextCardRichContent;
    };
    mapVisualOptions?: {
        topoJsonUrl?: string;
        objectKey?: string;
        outlineKey?: string;
        customTopoJsonUrl?: string;
        projection?: string;
        projectionScale?: number;
        projectionOffset?: [number, number];
        colorScale?: string;
    };
    kpiVisualOptions?: {
        lowerIsBetter?: boolean;
        countryLogoId?: string;
        valueAlignment?: 'left' | 'center';
        formatOptions?: TFormatOptions;
        metricComparison?: {
            enabled?: boolean;
            calculationType?: 'difference' | 'change' | 'change_difference' | 'ratio';
            formatOptions?: TFormatOptions;
            showArrow?: boolean;
            showColor?: boolean;
            conditionalLabel?: boolean;
            labelName?: string;
            position?: 'left' | 'right' | 'top';
            conditionalLabels?: {
                increase?: string;
                decrease?: string;
                noChange?: string;
            };
            colorConfig?: {
                increase?: 'green' | 'red' | 'neutral' | string;
                decrease?: 'green' | 'red' | 'neutral' | string;
                noChange?: 'green' | 'red' | 'neutral' | string;
            };
        };
    };
    tableVisualOptions?: {
        metricComparison?: {
            calculatedAs?: 'difference' | 'change' | 'change_difference' | 'ratio';
            indicatorStyle?: 'arrow_badge' | 'arrow' | 'badge' | 'none';
            formatOptions?: TFormatOptions;
            colors?: {
                increase?: 'green' | 'red' | 'neutral' | string;
                decrease?: 'green' | 'red' | 'neutral' | string;
                neutral?: 'green' | 'red' | 'neutral' | string;
            };
            lowerIsBetter?: boolean;
        };
    };
    pivotTableOptions?: {
        showRowTotals?: boolean;
        showColumnTotals?: boolean;
        showGrandTotal?: boolean;
        sortRowsBy?: 'label' | 'total' | 'metric';
        sortColumnsBy?: 'label' | 'total' | 'metric';
    };
    displayOptions?: {
        showFilterInfo?: boolean;
        showCardToolbar?: boolean;
        showChrome?: boolean;
        allowScroll?: boolean;
        showInlineFilterBar?: boolean;
    };
};

declare type TChartOptions = {
    type?: TChartType;
    scales?: {
        y?: {
            type?: 'linear' | 'logarithmic';
            min?: number;
            max?: number;
            ticks?: {
                stepSize?: number;
            };
            grid?: {
                display?: boolean;
            };
        };
        x?: {
            type?: 'linear' | 'logarithmic';
            min?: number;
            max?: number;
            ticks?: {
                stepSize?: number;
            };
            grid?: {
                display?: boolean;
            };
        };
    };
    indexAxis?: 'x' | 'y' | undefined;
    plugins?: {
        legend?: TLegendOptions;
        datalabels?: {
            anchor?: string;
        };
    };
    treemapColorMode?: 'branch' | 'category';
};

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 TColumnSetting<T extends DisplayDataType> = {
    columnIdx: number;
    textAlign?: 'left' | 'center' | 'right';
    width?: number;
    type: T;
    options: OptionsMap[T];
};

declare type TCustomCardPreferences = {
    showCardHeader?: boolean;
    url?: string;
    componentName?: string;
    icon?: string;
    pluginChartType?: string;
    type?: 'iframe' | 'component';
    visualType?: 'single' | 'multiple';
    minInputs?: number;
    maxInputs?: number;
    slotIndex?: number;
    settings?: any;
    slotSettings?: any;
    /** @deprecated Use position-based data collection. Kept for legacy dashboard support. */
    dataInputCardIds?: {
        [key: number]: {
            cardId: string;
        };
    };
};

declare type TCustomFilterPreferences = {
    url: string;
    componentName: string;
    pluginFilterType?: string;
    icon?: string;
    settings?: Record<string, string | number | boolean>;
};

declare type TDashboard = {
    id: string;
    title?: string;
    aiContext?: DashboardAIContext;
    summary?: {
        enabled?: boolean;
        position?: 'top' | 'bottom';
        maxItems?: number;
    };
    description?: string;
    sheets?: TSheet[];
    calculatedFields?: Field[];
    style?: TStyle;
    filters?: TFilter[];
    customCards?: CustomCard[];
    baseQueries?: TBaseQuery[];
    aiScopeTables?: AIScopeTable[];
    globalStyle?: TStyle;
    globalCacheConfig?: CacheConfig;
    emailSettings?: EmailSettings;
    defaultFilterValues?: TFilterValue[];
    controls?: ControlDefinition[];
    defaultControlValues?: Record<string, unknown>;
    inputs?: DashboardInput[];
    defaultInputValues?: DashboardInputValues;
    filterLayout?: FilterLayoutSettings;
};

declare type TDataLabelsConfig = {
    enabled?: boolean;
    position?: 'center' | 'top' | 'bottom' | 'left' | 'right' | 'auto' | 'custom';
    anchor?: 'center' | 'start' | 'end';
    align?: 'center' | 'start' | 'end' | 'top' | 'bottom' | number;
    display?: 'auto' | boolean;
    formatMode?: 'inherit' | 'override';
    /** @deprecated Use formatMode + formatOptions.type */
    format?: 'auto' | 'number' | 'currency' | 'percent' | 'date' | 'scientific' | 'duration' | 'none';
    formatOptions?: TFormatOptions;
    font?: {
        size?: number;
        weight?: 'normal' | 'bold';
    };
    color?: 'auto' | string;
    clamp?: boolean;
    clip?: boolean;
    rotation?: number;
    showTotal?: boolean;
    offset?: number;
};

declare type TDatasetOptions = {
    idx: number;
    type?: 'bar' | 'line';
    fill?: string | number;
    /** Y-axis assignment for combo charts: 'y' (primary/left) or 'y2' (secondary/right) */
    yAxisId?: 'y' | 'y2';
    /** Per-series data labels configuration - uses full TDataLabelsConfig for feature parity */
    dataLabels?: TDataLabelsConfig;
    /** Point radius (size) for line/area charts - 0 hides points */
    pointRadius?: number;
    /** Point shape style for line/area charts */
    pointStyle?: TPointStyle;
    /** Point radius on hover - defaults to pointRadius + 2 */
    pointHoverRadius?: number;
    /** Line dash style for line/area charts */
    lineStyle?: TLineStyle;
    /** Border radius (rounded corners) for bar charts - 0-20 pixels */
    borderRadius?: number;
    /** Border width for bar charts - 0-5 pixels */
    barBorderWidth?: number;
    /** Bar width as percentage of category width (0.1-1.0) */
    barPercentage?: number;
    /** Category width as percentage of available space (0.1-1.0) */
    categoryPercentage?: number;
    /** @deprecated Use dataLabels instead */
    datalabels?: {
        display?: boolean;
        align?: string;
        anchor?: string;
        clamp?: boolean;
        color?: string;
    };
};

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 type TextCardInlineFormat = {
    bold?: boolean;
    italic?: boolean;
};

declare type TextCardRichBlock = {
    type: 'paragraph';
    children: TextCardRichInline[];
} | {
    type: 'heading';
    level: 1 | 2;
    children: TextCardRichInline[];
} | {
    type: 'list';
    style: 'bulleted' | 'numbered';
    items: TextCardRichInline[][];
};

declare type TextCardRichContent = {
    version: 1;
    blocks: TextCardRichBlock[];
};

declare type TextCardRichInline = {
    type: 'text';
    value: string;
    format?: TextCardInlineFormat;
} | {
    type: 'variable';
    ref: DashboardInputVariableRef;
    format?: TextCardInlineFormat;
} | {
    type: 'link';
    url: string;
    children: Array<{
        type: 'text';
        value: string;
        format?: TextCardInlineFormat;
    } | {
        type: 'variable';
        ref: DashboardInputVariableRef;
        format?: TextCardInlineFormat;
    }>;
};

declare type TFilter = {
    kind?: FilterKind;
    type?: 'single' | 'multiple';
    uiType?: 'radio' | 'dropdown' | 'tabs';
    dateSelectionMode?: DateSelectionMode;
    defaultValues?: (string | number)[];
    defaultDateFilter?: DefaultDateFilter;
    sheetId?: string;
    location?: FilterLocation;
    hide?: boolean;
    id: string;
    /** Alias exposed to document/text variables, for example {{region}}. */
    variableName?: string;
    connectionId: string;
    title: string;
    column: string;
    dataType: string;
    table?: string;
    database?: string;
    qualifiedTableName?: string;
    sql: string;
    operation: Operation;
    fieldMeta?: FilterFieldMeta;
    semanticContext?: FilterSemanticContext;
    /**
     * Multi-field filter support: When set, provides multiple column options.
     * The first column becomes the default. Users can select which column
     * to filter at runtime via a dropdown in the date picker.
     * If not set, the single `column` field is used (backward compatible).
     */
    targetColumns?: TargetColumn[];
    searchMode?: 'text' | 'numeric' | 'auto';
    applyToSheetIds?: string[];
    excludeSheetIds?: string[];
    applyToCardIds?: string[];
    excludeCardIds?: string[];
    customFilterPreferences?: TCustomFilterPreferences;
    /** Whether to show the label above the filter (default: true) */
    showLabel?: boolean;
    /**
     * Width in pixels when displayed in toolbar mode.
     * Defaults vary by filter type (160px for dropdowns, 220px for date ranges, etc.)
     */
    toolbarWidth?: number;
    /**
     * Display mode for this filter
     * - 'canvas': Always show as draggable card on canvas
     * - 'toolbar': Always show in toolbar
     * - 'inherit': Use dashboard's filterLayout.displayMode setting (default)
     */
    displayMode?: FilterDisplayMode;
};

declare type TFilterValue = FilterForString | FilterForEqual | FilterForCompare | FilterForBetween | FilterForIn | FilterForNull | FilterForDate;

declare type TFormatOptions = {
    type?: 'auto' | 'number' | 'currency' | 'percent' | 'scientific' | 'date' | 'duration';
    decimalPlaces?: number;
    minimumFractionDigits?: number;
    maximumFractionDigits?: number;
    currency?: string;
    locale?: string;
    prefix?: string;
    suffix?: string;
    useSuffix?: boolean;
    useGrouping?: boolean;
    negativeInParentheses?: boolean;
    multiplyBy?: number;
    percentValueMode?: 'fraction' | 'whole';
    dateFormat?: string;
    timezone?: string;
    sourceTimezone?: string;
    relative?: boolean;
    durationInputUnit?: 'millisecond' | 'second' | 'minute' | 'hour' | 'day';
    durationDisplayStyle?: 'compact' | 'digital' | 'long';
    durationLargestUnit?: 'millisecond' | 'second' | 'minute' | 'hour' | 'day';
    durationSmallestUnit?: 'millisecond' | 'second' | 'minute' | 'hour' | 'day';
    durationMaxUnits?: number;
};

declare type TFrame = {
    id: string;
    visualId?: string;
    filterId?: string;
    cards: TCard[];
    activeCardId: string;
    calculatedFields?: Field[];
};

declare type TFunnelConfig = {
    /**
     * How to calculate percentage in tooltips and data labels.
     * - 'percentOfTotal': Each stage shows % of total sum (default/current behavior)
     * - 'percentOfFirst': First stage = 100%, others relative to first
     */
    percentMode?: TFunnelPercentMode;
    /**
     * Controls how much funnel segments narrow based on their values.
     * - 0: No shrink (all segments same width)
     * - 1: Full shrink (segments narrow proportionally to values, default)
     * Lower values prevent segments from becoming too narrow for labels.
     */
    shrinkFraction?: number;
    /**
     * Hide labels for segments smaller than this percentage of total.
     * - 0: Show all labels (default)
     * - 10: Hide labels for segments < 10% of total
     * Range: 0-25
     */
    labelThreshold?: number;
};

/**
 * Tooltip/data label percentage calculation mode for funnel charts.
 * - 'percentOfTotal': Percentage relative to sum of all values (default)
 * - 'percentOfFirst': Percentage relative to the first stage value (first stage = 100%)
 */
declare type TFunnelPercentMode = 'percentOfTotal' | 'percentOfFirst';

declare type THeatmapConfig = {
    colorMode?: 'continuous' | 'stepped';
    steps?: number;
    colorRange?: [string, string];
    colorPalette?: 'blue' | 'green' | 'purple' | 'orange' | 'custom';
    showLegend?: boolean;
    legendPosition?: 'top' | 'bottom' | 'left' | 'right';
    showDataLabels?: boolean;
    nullFillColor?: string;
    fillMissingCells?: boolean;
    xAxisBuckets?: string[];
    yAxisBuckets?: string[];
};

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';

/**
 * Inline filter definition stored on a card.
 * Inline filters appear on the right-hand side of the card header,
 * allowing ad-hoc data exploration without affecting other cards.
 */
declare type TInlineFilter = {
    id: string;
    /** Alias exposed to document/text variables, for example {{region}}. */
    variableName?: string;
    column: string;
    title: string;
    dataType: string;
    table: string;
    database: string;
    qualifiedTableName?: string;
    connectionId: string;
    operation: Operation;
    sql: string;
    fieldMeta?: FilterFieldMeta;
    semanticContext?: FilterSemanticContext;
    /** Selection type: 'single' allows one value, 'multiple' allows many */
    type?: 'single' | 'multiple';
    /** UI component for single-select filters */
    uiType?: 'radio' | 'dropdown' | 'tabs';
    /** Date picker type: 'range' for full calendar, 'months' for month picker */
    dateSelectionMode?: DateSelectionMode;
    /** Default values applied when the dashboard first loads */
    defaultValues?: (string | number)[];
    /** Default date filter applied on dashboard load (relative or fixed month/year) */
    defaultDateFilter?: DefaultDateFilter;
    /** Search mode for numeric filters: 'text' treats as text, 'numeric' enables operators (>, <, =) */
    searchMode?: 'text' | 'numeric' | 'auto';
    /** Custom filter UI from a plugin */
    customFilterPreferences?: TCustomFilterPreferences;
    /** Width of the inline filter in pixels (default: 250) */
    width?: number;
    /** Whether to show the label above the filter (default: true) */
    showLabel?: boolean;
};

declare type TLegendOptions = {
    display?: boolean;
    position?: 'top' | 'left' | 'bottom' | 'right';
    align?: 'start' | 'center' | 'end';
    labels?: {
        generateLabels?: (chart: any) => any[];
        [key: string]: any;
    };
};

/** Line dash style options */
declare type TLineStyle = 'solid' | 'dashed' | 'dotted' | 'dash-dot';

/** Historical per-column totals shape. Runtime totals are table-level now. */
declare type TotalsBehavior = 'sum' | 'avg' | 'count' | 'label' | 'none';

/** Point style options supported by Chart.js */
declare type TPointStyle = 'circle' | 'cross' | 'crossRot' | 'dash' | 'line' | 'rect' | 'rectRounded' | 'rectRot' | 'star' | 'triangle';

declare type TSheet = {
    id: string;
    kind?: 'dashboard' | 'document';
    title?: string;
    description?: string;
    layout?: ReactGridLayout.Layout[];
    layouts?: ReactGridLayout.Layouts;
    cards?: TCard[];
    frames?: TFrame[];
    calculatedFields?: Field[];
    document?: DocumentDefinition;
};

/**
 * Style for the dashboard
 */
declare type TStyle = {
    default: StyleProps;
    dark?: StyleProps;
};

declare type TTooltipFormatConfig = {
    formatMode?: 'inherit' | 'override';
    /** @deprecated Use formatMode */
    mode?: 'inherit' | 'override';
    formatOptions?: TFormatOptions;
};

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

/**
 * URL Parameter for drill-to-URL interpolation
 * Represents a placeholder in the URL template (e.g., {{product_id}})
 */
declare interface URLParameter {
    /**
     * Unique identifier for the parameter (e.g., 'product_id', 'card_id')
     * Used in template as {{id}}
     */
    id: string;
    /**
     * Display label for the parameter
     */
    label: string;
    /**
     * Category of the parameter
     * - attribute: From card dimensions/attributes (e.g., product name, region)
     * - identifier: System values (card_id, frame_id, sheet_id)
     */
    category: 'attribute' | 'identifier';
    /**
     * For attribute parameters: the complete field object
     * Provides access to all field properties (name, qualifiedFieldName, dataType, etc.)
     */
    field?: Field;
}

export declare function validateDashboardAuthoringDatasetScope({ datasets, requireAtLeastOne, }: {
    datasets: readonly unknown[];
    requireAtLeastOne: boolean;
}): DashboardAuthoringDatasetScopeResult;

export declare function validateDashboardChangePlan(plan: DashboardChangePlan): DashboardAuthoringValidationResult;

export declare function validateDashboardPlan(plan: DashboardPlan): DashboardAuthoringValidationResult;

/**
 * Display mode for visual components - controls which UI elements are shown
 */
declare type VisualDisplayMode = 'full' | 'print' | 'table-print';

/**
 * Display preferences for controlling visual component rendering
 */
declare type VisualDisplayPreferences = {
    /**
     * Predefined display mode
     * - 'full': All UI elements (default)
     * - 'print': Optimized for printing (shows title and description, hides interactive elements)
     * - 'table-print': Table-specific print mode (title only, no pagination/toolbar)
     */
    mode?: VisualDisplayMode;
    /**
     * Override specific UI elements visibility
     * These overrides take precedence over the mode presets
     */
    overrides?: {
        showHeader?: boolean;
        showTitle?: boolean;
        showDescription?: boolean;
        showTabs?: boolean;
        showFooter?: boolean;
        showFilters?: boolean;
        showBreadcrumbs?: boolean;
        showRefreshIndicator?: boolean;
        showFilterInfo?: boolean;
        showPagination?: boolean;
        showTableToolbar?: boolean;
        showColumnSettings?: boolean;
    };
};

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 { }
