import { CubeQuery } from '../types';
/**
 * Binding key configuration - the dimension that links funnel steps together.
 * Can be a simple dimension name or cross-cube mapping for multi-cube funnels.
 */
export interface FunnelBindingKey {
    /**
     * The dimension field name that exists across all cubes in the funnel.
     * For cross-cube funnels where the binding key has different names,
     * specify a mapping array instead.
     *
     * @example Simple: "Employees.userId"
     * @example Cross-cube: [{ cube: "Signups", dimension: "Signups.userId" }, { cube: "Purchases", dimension: "Purchases.customerId" }]
     */
    dimension: string | FunnelBindingKeyMapping[];
}
/**
 * Mapping for cross-cube funnels where the binding key has different names
 * in different cubes.
 */
export interface FunnelBindingKeyMapping {
    /** The cube name (e.g., "Signups", "Purchases") */
    cube: string;
    /** The full dimension field in that cube (e.g., "Signups.userId") */
    dimension: string;
}
/**
 * Configuration for a single funnel step.
 * Each step has its own query and optional time constraints.
 */
export interface FunnelStep {
    /** Unique identifier for this step */
    id: string;
    /** Display name for the step (e.g., "Signup", "First Purchase") */
    name: string;
    /** The cube query for this step */
    query: CubeQuery;
    /**
     * Time window constraint - maximum time allowed between this step
     * and the previous step. Optional - if not set, no time constraint.
     * Format: ISO 8601 duration (e.g., "P7D" for 7 days, "PT1H" for 1 hour)
     */
    timeToConvert?: string;
    /**
     * Time dimension field to use for time window filtering.
     * Required if timeToConvert is specified.
     */
    timeDimension?: string;
}
/**
 * Complete funnel configuration
 */
export interface FunnelConfig {
    /** Unique identifier for the funnel */
    id: string;
    /** Display name for the funnel */
    name: string;
    /** The binding key that links steps together */
    bindingKey: FunnelBindingKey;
    /** Ordered array of funnel steps */
    steps: FunnelStep[];
    /**
     * Global time window for the entire funnel.
     * All steps must complete within this window from the first step.
     */
    globalTimeWindow?: string;
    /**
     * Whether to count unique entities (true) or events (false).
     * Default: true
     */
    countUnique?: boolean;
    /**
     * Maximum number of binding key values to pass between steps.
     * Limits the size of the IN clause to prevent performance issues.
     * Default: 500
     */
    bindingKeyLimit?: number;
}
/**
 * Result for a single funnel step execution
 */
export interface FunnelStepResult {
    /** Step index (0-based) */
    stepIndex: number;
    /** Step name */
    stepName: string;
    /** Step ID */
    stepId: string;
    /** Raw data from the query */
    data: unknown[];
    /** Binding key values extracted from this step */
    bindingKeyValues: (string | number)[];
    /**
     * Total number of unique binding key values before limit was applied.
     * If this differs from bindingKeyValues.length, values were truncated.
     */
    bindingKeyTotalCount: number;
    /** Count at this step (unique entities if countUnique=true, else rows) */
    count: number;
    /** Conversion rate from previous step (null for first step) */
    conversionRate: number | null;
    /** Cumulative conversion rate from first step */
    cumulativeConversionRate: number;
    /** Execution time in milliseconds */
    executionTime: number;
    /** Error if this step failed */
    error: Error | null;
}
/**
 * Complete funnel execution result
 */
export interface FunnelExecutionResult {
    /** Funnel configuration */
    config: FunnelConfig;
    /** Per-step results */
    steps: FunnelStepResult[];
    /** Overall funnel metrics */
    summary: {
        /** Count at first step */
        totalEntries: number;
        /** Count at last step */
        totalCompletions: number;
        /** Overall conversion rate (completions / entries) */
        overallConversionRate: number;
        /** Total execution time for all steps */
        totalExecutionTime: number;
    };
    /** Formatted data for funnel chart visualization */
    chartData: FunnelChartData[];
    /** Execution status */
    status: 'idle' | 'executing' | 'success' | 'error' | 'partial';
    /** First error encountered, if any */
    error: Error | null;
    /** Index of current step being executed (null when not executing) */
    currentStepIndex: number | null;
}
/**
 * Data format for funnel chart visualization
 */
export interface FunnelChartData {
    /** Step name */
    name: string;
    /** Count at this step */
    value: number;
    /** Percentage of first step (cumulative conversion) */
    percentage: number;
    /** Conversion rate from previous step (null for first step) */
    conversionRate: number | null;
    /** Step index for ordering */
    stepIndex: number;
    /** Optional fill color */
    fill?: string;
    /** Average seconds to reach this step from previous step (from server) */
    avgSecondsToConvert?: number | null;
    /** Median seconds to reach this step from previous step (from server) */
    medianSecondsToConvert?: number | null;
    /** 90th percentile seconds to reach this step (from server) */
    p90SecondsToConvert?: number | null;
}
/**
 * Validation error for funnel configuration
 */
export interface FunnelValidationError {
    /** Error type */
    type: 'binding_key' | 'cross_cube' | 'time_window' | 'step_query' | 'general';
    /** Error message */
    message: string;
    /** Step index if error is step-specific */
    stepIndex?: number;
}
/**
 * Validation result for funnel configuration
 */
export interface FunnelValidationResult {
    /** Whether the configuration is valid */
    isValid: boolean;
    /** Validation errors (block execution) */
    errors: FunnelValidationError[];
    /** Validation warnings (notify but allow) */
    warnings: FunnelValidationError[];
}
/**
 * Options for funnel query hook
 */
export interface UseFunnelQueryOptions {
    /** Skip execution */
    skip?: boolean;
    /** Debounce delay in milliseconds */
    debounceMs?: number;
    /** Callback when a step completes */
    onStepComplete?: (stepResult: FunnelStepResult) => void;
    /** Callback when all steps complete */
    onComplete?: (result: FunnelExecutionResult) => void;
    /** Callback when execution fails */
    onError?: (error: Error, stepIndex: number) => void;
    /**
     * Pre-built server funnel query. When provided, skips building
     * the server query from FunnelConfig and uses this directly.
     * Use this with the new dedicated funnel mode (analysisType === 'funnel').
     */
    prebuiltServerQuery?: ServerFunnelQuery | null;
}
/**
 * Result from funnel query hook
 */
export interface UseFunnelQueryResult {
    /** Funnel execution result */
    result: FunnelExecutionResult | null;
    /** Current execution status */
    status: 'idle' | 'executing' | 'success' | 'error' | 'partial';
    /** Whether currently executing */
    isExecuting: boolean;
    /** Whether waiting for debounce */
    isDebouncing: boolean;
    /** Index of step currently being executed */
    currentStepIndex: number | null;
    /** Per-step loading states */
    stepLoadingStates: boolean[];
    /** Per-step results (for progressive rendering) */
    stepResults: FunnelStepResult[];
    /** Chart-ready data */
    chartData: FunnelChartData[];
    /** Cache metadata when served from cache */
    cacheInfo?: {
        hit: true;
        cachedAt: string;
        ttlMs: number;
        ttlRemainingMs: number;
    } | null;
    /** Error if execution failed */
    error: Error | null;
    /** Execute the funnel */
    execute: () => Promise<FunnelExecutionResult | null>;
    /** Cancel current execution */
    cancel: () => void;
    /** Reset to initial state */
    reset: () => void;
    /**
     * The actually executed queries (with binding key dimension and IN filters).
     * These differ from the original queries in the following ways:
     * - Binding key dimension is automatically added if not present
     * - For steps 2+, an IN filter is added with binding key values from the previous step
     * Use these for debug/inspection to see what was actually sent to the server.
     * @deprecated Server-side funnel execution doesn't use per-step queries. Use serverQuery instead.
     */
    executedQueries: CubeQuery[];
    /**
     * The actual server query sent to the API with { funnel: {...} }.
     * This is a single unified query, not per-step queries.
     * Use this for debug panel display to show what's actually executed.
     */
    serverQuery: ServerFunnelQuery | null;
}
/**
 * Server-side funnel query format
 * This is the { funnel: {...} } object sent to the server API
 */
export interface ServerFunnelQuery {
    funnel: {
        bindingKey: string | {
            cube: string;
            dimension: string;
        }[];
        timeDimension: string | {
            cube: string;
            dimension: string;
        }[];
        steps: ServerFunnelStep[];
        includeTimeMetrics?: boolean;
        globalTimeWindow?: string;
    };
}
/**
 * Server-side funnel step format
 */
export interface ServerFunnelStep {
    name: string;
    cube?: string;
    filter?: unknown;
    timeToConvert?: string;
}
