import { ShowToast, TaskStatus, PatternsErrorHandler } from '../../model';
import type { HttpClient } from '../../model/httpClient';
import { Translate } from '../../services';
import { ModalState } from '../ModalState';
import { ConditionalModalState } from '../ConditionalModalState';
import { CreateExportAsyncJobRequest } from '@wix/bex-utils/@wix/ambassador-fedinfra-exportservice-v1-export-async-job/types';
import { WritePolicy, type Destination } from '@wix/bex-utils/@wix/ambassador-hub-v1-job/types';
import { type DetectColumnType, type NewFieldType } from './detectFieldType';
import type { FieldSpec, NonReferenceField } from '../../types/Field';
import type { Schema } from '../../types/Schema';
export interface ImportCollection {
    clearResultAndMoveToStart(params?: {
        force?: boolean;
    }): void;
}
/** Outcome of a server-side import job, derived from the job's progress. */
export interface ImportResult {
    succeeded: number;
    failed: number;
}
export interface BackupResult {
    /**
     * Reverts the collection to its pre-import state. Called only when the user
     * cancels mid-import (matching the previous client-side behavior); a job
     * failure leaves partial rows in place and offers "Try again".
     *
     * Must fully revert to the snapshot taken before the import — including rows
     * the import overwrote in place. The default `writePolicy` is upsert (OVERWRITE
     * by `_id`), so it is NOT enough to delete newly-inserted ids; previously
     * existing rows may have been overwritten and must be restored to their prior
     * values.
     */
    restore(signal: AbortSignal): Promise<void>;
}
/**
 * Optional snapshot taken before the import runs, returning a `restore` used to
 * undo the import on cancel. See {@link BackupResult.restore} for the revert
 * contract under upsert.
 */
export type BackupFn = (signal: AbortSignal) => Promise<BackupResult | void>;
export type DownloadCsvFn = (content: string, fileName: string) => void;
/**
 * Consumer hook for resolving a failed import job's message. An import runs
 * server-side, so a failure arrives on a 200 (the poll succeeds; the job
 * doesn't) with no HTTP error to carry the application error. Cairo hands the
 * consumer `run` — an operation that rejects with a synthetic, HTTP-error-shaped
 * error carrying the job's application error — and the consumer wraps it with
 * their own `withErrorHandler` + error-code map (their codes, their
 * translations), keeping the map coupled to the `withErrorHandler` call as
 * everywhere else (e.g. `fetchData`). The map is keyed by application-error code
 * (the v2 errorHandler shape, like `getExportAsyncJobErrors`):
 *
 *   onJobError: (run) =>
 *     errorHandler.withErrorHandler(run, {
 *       [jobErrorCode]: (error) => ({ message: translate(...) }),
 *     })
 *
 * `withErrorHandler` attaches the map to the error object and re-rejects it, so
 * the progress step resolves a consumer-specific message via `getResolvedError`.
 * When omitted, the error still surfaces but resolves to the generic message.
 */
export type OnImportJobError = (run: () => Promise<unknown>) => Promise<unknown>;
export type ImportField = NonNullable<CreateExportAsyncJobRequest['fields']>[number];
export { WritePolicy } from '@wix/bex-utils/@wix/ambassador-hub-v1-job/types';
export type { Destination } from '@wix/bex-utils/@wix/ambassador-hub-v1-job/types';
export interface NewFieldConfig {
    validation?: NonReferenceField['validation'];
    isPii?: boolean;
    helpText?: string;
}
export interface NewFieldDefinition {
    key: string;
    type: NewFieldType;
    displayName: string;
    config?: NewFieldConfig;
}
/**
 * Consumer-supplied callback that adds the given new fields to the collection
 * schema in a single call, before the rows are uploaded. Mirrors the cm-import
 * `beforeImport`/`updateSchema` flow: Cairo decides the fields (and their keys),
 * the consumer performs one schema mutation (e.g. `updateSchema(collectionId,
 * ...addField(key, config))`). Its presence is also the opt-in for the "create
 * new field" default — see `getDefaultMapping`.
 *
 * Optionally returns the collection's updated fields map, mirroring the schema's
 * `FieldActions`. When it does, the import merges that map into the table's field
 * source on success so the new columns appear with no manual reload (CAIRO-4400).
 * Returning `void` still imports fine — the columns just wait for the next schema
 * load.
 */
export type UpdateSchemaFn = (fields: NewFieldDefinition[]) => Promise<Schema['fields'] | void>;
/**
 * How a CSV column is mapped:
 * - `existing` — into an existing collection field by id
 * - `new` — into a new field created during import. `fieldType` is the detected
 *   type, or the type the user picked in the field editor. `displayName` and
 *   `config` are present only once the user edited the pending field via the
 *   "Edit field" editor — `displayName` overrides the header-derived name and
 *   `config` carries the per-type configuration.
 * - `null` — don't import (skip)
 */
export type ColumnMapping = {
    kind: 'existing';
    fieldId: string;
} | {
    kind: 'new';
    fieldType: NewFieldType;
    displayName?: string;
    config?: NewFieldConfig;
} | null;
/**
 * The import inputs a consumer supplies. Satisfied both by a plain object (the
 * manual case) and by a live schema reference (`useSchemaImport` in
 * `@wix/patterns`) whose members are getters read on demand — so the async
 * schema load needn't resolve before `ImportState` is built. `ImportState` holds
 * it by reference (never spreads it) so those getters stay live.
 */
export interface ImportButtonConfig {
    /** Existing collection fields, for column auto-mapping. */
    fields: ImportField[];
    /** Wix Data collection the import writes into (the common CMS case). */
    collectionId?: string;
    /**
     * Platformized (non–Wix-Data) destination, sent to the job verbatim (e.g.
     * `{ storesCatalogProducts: {} }`). When provided, `collectionId`/`writePolicy`
     * are ignored.
     */
    destination?: Destination;
    backup?: BackupFn;
    /** Creates new fields before upload; resolves with the updated fields map. */
    updateSchema?: UpdateSchemaFn;
    /**
     * Merges `updateSchema`'s returned fields map into the table after a successful
     * import, so the new columns appear with no reload (CAIRO-4400). A schema-backed
     * config (see `useSchemaImport` in `@wix/patterns`) wires this to its live
     * schema; when omitted, the new columns wait for the next schema load.
     */
    mergeFields?: (fields: Schema['fields']) => void;
    /** See {@link OnImportJobError}. */
    onJobError?: OnImportJobError;
    /**
     * The collection's id-field key, for the id-collision write policy. Defaults
     * to `_id` (the Wix Data default) when unset.
     */
    idFieldKey?: string;
    /**
     * Whether the user may create new fields. When set, it gates create-new-field
     * directly (e.g. a schema's `createField` permission); when unset, the presence
     * of `updateSchema` is the opt-in.
     */
    canAddFields?: boolean;
}
export interface ImportStateProps {
    /** The import inputs (existing fields, destination, create-new-field, backup). */
    config: ImportButtonConfig;
    /** Wix httpClient used to drive the Hub Job (data-movement) API. */
    httpClient: HttpClient;
    /**
     * Infers a new field's type from its column data. Defaults to the primitive
     * detector (number / date / boolean / url / text). `@wix/patterns` injects a
     * media-aware detector from `@wix/patterns-fields` (image / video / document /
     * audio) — that detection needs the media URI parser, which core can't depend
     * on.
     */
    detectColumnType?: DetectColumnType;
    collection: ImportCollection;
    importModalState: ModalState;
    translate: Translate;
    errorHandler: PatternsErrorHandler;
    showToast?: ShowToast;
    downloadCsv?: DownloadCsvFn;
}
export type ImportStep = 'upload' | 'configuration' | 'progress';
export declare class ImportState {
    private readonly config;
    readonly collection: ImportCollection;
    readonly importModalState: ModalState;
    readonly translate: Translate;
    readonly errorHandler: PatternsErrorHandler;
    readonly showToast?: ShowToast;
    readonly downloadCsv?: DownloadCsvFn;
    private readonly hubJobClient;
    private readonly _detectColumnType;
    readonly discardChangesModal: ConditionalModalState<"close" | "goBack">;
    currentStep: ImportStep;
    importStatus: TaskStatus<ImportResult, unknown>;
    fileName: string;
    csvHeaders: string[];
    csvRows: string[][];
    orderedHeaders: string[];
    mappingByHeader: Record<string, ColumnMapping>;
    writePolicy: WritePolicy;
    processedCount: number;
    totalCount: number;
    result: ImportResult;
    isBackingUp: boolean;
    isRestoring: boolean;
    private restoreFn;
    private _cancelled;
    private _abortController;
    private _jobId;
    private _editingHeader;
    private _pendingFieldsMap?;
    constructor(props: ImportStateProps);
    /** Existing collection fields, for column auto-mapping. */
    get fields(): ImportField[];
    /** Wix Data collection the import writes into (unset for platformized). */
    get collectionId(): string | undefined;
    get destination(): Destination | undefined;
    get backup(): BackupFn | undefined;
    get updateSchema(): UpdateSchemaFn | undefined;
    get onJobError(): OnImportJobError | undefined;
    private get idFieldKey();
    init(): () => void;
    get hasParsedRows(): boolean;
    get hasMappings(): boolean;
    /**
     * True when there are mappings but none of the mapped columns contain any
     * data in any row (including the case of zero data rows). Drives the
     * non-blocking "no rows found" warning in the configuration step. Returns
     * false when nothing is mapped yet — that case is handled by the disabled
     * import button instead.
     */
    get hasNoMappedData(): boolean;
    get selectedFieldIds(): Set<string>;
    /**
     * The CSV header currently mapped to the collection's `_id` field, or `null`
     * when no column targets it. Drives both the "When items share the same ID"
     * control (only shown on this row) and whether `writePolicy` is sent at all —
     * with no `_id` mapped, every row is a fresh insert and collisions can't occur.
     */
    get idMappedHeader(): string | null;
    setWritePolicy(policy: WritePolicy): void;
    /**
     * Whether columns may be mapped to a brand-new field created during import.
     * When the config sets `canAddFields` (e.g. a schema's create-field permission)
     * that gates it; otherwise the presence of `updateSchema` is the opt-in (see
     * `getDefaultMapping`).
     */
    get canCreateNewField(): boolean;
    /**
     * Whether the write-policy (id-collision) choice is meaningful for this import.
     * `writePolicy` is a `wixDataCollection`-only concept, and `_destination` only
     * attaches it when Cairo builds that destination itself. A consumer-supplied
     * (platformized) `destination` is sent verbatim with no place to carry it, so
     * the choice would be a no-op — the UI hides the control in that case. Fixed at
     * construction (depends only on the `destination` prop), so it isn't an
     * observable.
     */
    get canConfigureWritePolicy(): boolean;
    reset(): void;
    close(): Promise<void>;
    private _restoreBackup;
    goToUpload(): void;
    discardAndGoBack(): Promise<void>;
    discardAndClose(): Promise<void>;
    onUploadContinue(): void;
    private getDefaultMapping;
    private _columnValues;
    private _orderHeadersWithIdFirst;
    private applyParsedCsv;
    onFileSelected(file: File | null): Promise<void>;
    private _readFileBytes;
    private _decodeUtf8;
    private _rejectFile;
    private _showFileReadErrorToast;
    private _showPartialSuccessToast;
    /**
     * Builds a plain, re-importable CSV of the rows the server rejected — the
     * original headers plus just the failed rows — and hands it to `downloadCsv`.
     * The failed rows come from the job's movement logs (which row failed), mapped
     * back to the parsed `csvRows` we still hold in memory.
     */
    private _downloadFailedRows;
    private _fetchFailedRowIndices;
    setMapping(header: string, fieldId: string | null): void;
    setNewFieldMapping(header: string): void;
    /**
     * Persists the result of the "Edit field" editor for a column's pending new
     * field: the (possibly overridden) type, an optional display-name override,
     * and the per-type configuration. No-op if the column isn't currently mapped
     * to a new field.
     */
    setNewFieldConfig(header: string, edit: {
        fieldType: NewFieldType;
        displayName?: string;
        config?: NewFieldConfig;
    }): void;
    /**
     * Marks which column's pending new field the field editor is currently
     * editing, so a later `applyFieldEdit` (the editor's `onSubmit`) knows where to
     * write the result.
     */
    beginFieldEdit(header: string): void;
    /**
     * `onSubmit` handler for the field editor: maps the edited field spec into the
     * column being edited (set via `beginFieldEdit`). No-op if nothing is being
     * edited.
     */
    applyFieldEdit(field: FieldSpec): void;
    /**
     * Runs the server-side import: align the CSV to the resolved field keys,
     * upload it, submit a data-movement job, then poll until terminal. Throws on
     * a failed job so `startImport` surfaces the error state; partial success is
     * reported via `result.failed` and the partial toast.
     */
    private _runImportJob;
    private _destination;
    private _applyJobProgress;
    private _runBackup;
    private _lingerOnCompletion;
    /**
     * Resolves every column to the final destination key used in the upload
     * payload: an existing field id, a new field's (Cairo-decided) key, or `null`
     * to skip. All new fields are added to the schema in a single `updateSchema`
     * call before the rows upload — mirroring the cm-import `beforeImport` flow.
     * `updateSchema` may throw — `startImport` surfaces that as the error state.
     */
    private _resolveFieldMapping;
    startImport(): Promise<void>;
}
//# sourceMappingURL=ImportState.d.ts.map