import { AnalyticsEvent, AnalyticsSink } from '../analytics/index.js';

/**
 * Minimal structural shape of the bits of `@microsoft/applicationinsights-web`
 * we use. Declared locally so the vendor lib stays an OPTIONAL peer with NO
 * type-level hard dependency — it is only ever reached via dynamic import.
 */
interface AppInsightsLike {
    loadAppInsights?: () => unknown;
    trackEvent: (event: {
        name: string;
    }, customProperties?: Record<string, unknown>) => void;
    trackPageView: (pageView?: {
        name?: string;
        uri?: string;
        properties?: Record<string, unknown>;
        measurements?: Record<string, number>;
    }) => void;
    setAuthenticatedUserContext?: (authenticatedUserId: string, accountId?: string, storeInCookie?: boolean) => void;
    clearAuthenticatedUserContext?: () => void;
    flush?: (async?: boolean) => void;
}
/** Fan-out mode for the App Insights sink. */
type AppInsightsSinkMode = 'client-sdk' | 'http';
interface BaseOptions {
    /** Consent categories this sink requires. Default `['analytics']`. */
    consentCategories?: string[];
    /** Stable sink name. Default `'app-insights'`. */
    name?: string;
}
/**
 * `client-sdk` mode — runs in the browser via `@microsoft/applicationinsights-web`.
 *
 * The vendor SDK is loaded **lazily via dynamic import** the first time a
 * batch is delivered, so it never enters the bundle unless this sink is used.
 * Callers may instead inject a ready instance (`appInsights`) or a custom
 * `loadSdk` factory (used by tests with a mock transport — no network).
 */
interface ClientSdkOptions extends BaseOptions {
    mode: 'client-sdk';
    /** App Insights connection string (preferred) or instrumentation key. */
    connectionString?: string;
    /** Legacy instrumentation key (used when `connectionString` is absent). */
    instrumentationKey?: string;
    /**
     * Pre-constructed App Insights instance. When provided, no dynamic import
     * or `loadAppInsights()` happens — used for DI/testing.
     */
    appInsights?: AppInsightsLike;
    /**
     * Custom async SDK factory. Overrides the built-in dynamic import of
     * `@microsoft/applicationinsights-web`. Receives the resolved config.
     */
    loadSdk?: (config: {
        connectionString?: string;
        instrumentationKey?: string;
    }) => Promise<AppInsightsLike>;
}
/**
 * `http` mode — POSTs to the App Insights `/v2/track` ingestion endpoint.
 * No browser library is loaded; server-relay friendly.
 */
interface HttpOptions extends BaseOptions {
    mode: 'http';
    /** Instrumentation key (iKey) for the ingestion envelope. Required. */
    instrumentationKey: string;
    /**
     * Ingestion endpoint base. Default the public global endpoint
     * `https://dc.services.visualstudio.com`. Region endpoints are accepted.
     * Events POST to `{endpoint}/v2/track`.
     */
    endpoint?: string;
    /** Injected fetch (defaults to global fetch). */
    fetchImpl?: typeof fetch;
    /** Max retries for 429/5xx (exponential backoff). Default 3. */
    maxRetries?: number;
    /** Base backoff delay in ms. Default 500. */
    backoffBaseMs?: number;
}
type AppInsightsSinkOptions = ClientSdkOptions | HttpOptions;
interface IngestEnvelope {
    name: string;
    time: string;
    iKey: string;
    tags: Record<string, string>;
    data: {
        baseType: 'EventData' | 'PageViewData';
        baseData: {
            ver: 2;
            name: string;
            properties: Record<string, string>;
            measurements: Record<string, number>;
        };
    };
}
/**
 * Build an App Insights ingestion envelope (Breeze schema) for one canonical
 * event. `tags` carry session/user/operation correlation; `baseData` carries
 * the custom event with the properties/measurements split.
 */
declare function buildIngestEnvelope(ev: AnalyticsEvent, iKey: string): IngestEnvelope;
/**
 * Create an Azure Application Insights {@link AnalyticsSink}.
 *
 * Dual-mode:
 *  - `client-sdk` — browser, lazy `@microsoft/applicationinsights-web`
 *    (`trackEvent` / `trackPageView`); the vendor lib is an OPTIONAL peer
 *    loaded only via dynamic import, never a hard/static dependency.
 *  - `http` — App Insights `/v2/track` ingestion endpoint; no browser lib,
 *    server-relay friendly.
 *
 * Both modes map the canonical envelope to App Insights custom events with a
 * properties/measurements split and surface identity as
 * `authenticatedUserId` / `anonymous`.
 */
declare function createAppInsightsSink(options: AppInsightsSinkOptions): AnalyticsSink;

/**
 * App Insights custom-event payload after mapping the canonical envelope.
 *
 * App Insights splits a custom event's bag into two dictionaries:
 *  - `properties`  — string-valued dimensions (everything non-numeric)
 *  - `measurements`— numeric metrics (queryable/aggregatable in KQL)
 *
 * We additionally surface identity:
 *  - `authenticatedUserId` — present iff the envelope has `userId`
 *  - `anonymous` — `'true'` when no `userId`, else `'false'` (string for the
 *     properties bag; App Insights properties are always strings)
 */
interface AppInsightsEvent {
    /** App Insights custom-event name. */
    name: string;
    /** String-valued custom dimensions. */
    properties: Record<string, string>;
    /** Numeric custom metrics. */
    measurements: Record<string, number>;
}
/**
 * Derive the App Insights custom-event name for a canonical event.
 *
 * - `page`  → `Page View: <name|path>` (also routed to `trackPageView` in the
 *   client-sdk mode; the name here is the http-mode/event fallback)
 * - `screen`→ `Screen: <name>`
 * - `identify` → `Identify`
 * - `group` → `Group`
 * - `alias` → `Alias`
 * - `track` → the event name (or `track` when absent)
 */
declare function eventName(ev: AnalyticsEvent): string;
/**
 * Map a canonical {@link AnalyticsEvent} to an {@link AppInsightsEvent}.
 *
 * Properties bag composition:
 *  - canonical context: `app`, `env`, library name/version, page fields
 *  - envelope identity/routing: `messageId`, `anonymousId`, `sessionId`,
 *    `type`, `groupId?`, `previousId?`, `timestamp`, `schemaVersion`
 *  - identity surface: `authenticatedUserId` (iff `userId`), `anonymous`
 *  - the event's `properties` and `traits`, numbers → `measurements`
 *
 * The split is stable and lossless: every scalar lands in exactly one of the
 * two dictionaries; nested objects are dot-flattened.
 */
declare function mapEvent(ev: AnalyticsEvent): AppInsightsEvent;

export { type AppInsightsEvent, type AppInsightsLike, type AppInsightsSinkMode, type AppInsightsSinkOptions, type ClientSdkOptions, type HttpOptions, buildIngestEnvelope, createAppInsightsSink, eventName, mapEvent };
