import { EasyCLITheme } from '../themes';
/**
 * A mapping for a CSV field to a field in an object.
 * @template TType The type of the field after transformation.
 *
 * @interface CsvFieldMapping
 *
 * @property {string[]} aliases The aliases for the field in the CSV.
 * @property {boolean} required If the field is required or not.
 * @property {function} transform The function to transform the value from the CSV. (Default: value => value)
 * @property {boolean} allowEmpty If the field can be empty or not. (Default: false)
 * @property {TType} defaultValue The default value for the field. (Default: undefined)
 */
export type CsvFieldMapping<TType = any> = {
    aliases: string[];
    required: boolean;
    transform?: (value: string) => any | Promise<any>;
    allowEmpty?: boolean;
    defaultValue?: TType;
};
/**
 * A mapping of fields in an object to their CSV field mappings.
 *
 * @interface CsvFieldMappings
 *
 * @template TObject The object type to map to.
 *
 * @property {keyof TObject} The name of the field in the object.
 * @property {CsvFieldMapping<TObject[keyof TObject]>} The rules for mapping the field.
 *
 */
export type CsvFieldMappings<TObject> = Record<keyof TObject, CsvFieldMapping<TObject[keyof TObject]>>;
/**
 * A mapping of CSV columns to their object fields that they map to.
 *
 * @interface ObjectDataMapper
 *
 * @template TObject The output object type.
 * @template TFileObject The CSV file object type.
 *
 * @property {keyof TFileObject} The column in the CSV file.
 * @property {keyof TObject[]} The fields in the object that the column maps to.
 *
 * @example
 * ```typescript
 * {
 * 'Username': ['username'],
 * 'Identifier': ['id'],
 * 'First name': ['firstName', 'firstInital'],
 * }
 * ```
 */
export type ObjectDataMapper<TObject, TFileObject> = Record<keyof TFileObject, (keyof TObject)[]>;
/**
 * The settings for the CSV Mapper instance.
 *
 * @interface CsvMapperOptions
 *
 * @property {CsvFieldMappings<TObject>} mappings The field mappings for the CSV file.
 * @property {boolean} interactive If it should interactively ask for other field mappings. (Default: false)
 * @property {boolean} discardOriginalFields If it should discard any fields that are not mapped or not. If false, will store them with their name from the CSV. (Default: true)
 * @property {EasyCLITheme} theme The theme to use for the prompts.
 * @property {boolean} validate If it should validate the data against the mappings. (Default: true)
 *
 * @example
 * ```typescript
 * {
 *   mappings: {
 *     username: {
 *       aliases: ['Username'],
 *       required: true,
 *       transform: value => value,
 *     },
 *     ...
 *   },
 *   interactive?: true, // If it should interactively ask for other field mappings. (Default: false)
 *   discardOriginalFields?: true, // If it should discard any fields that are not mapped or not. If false, will store them with their name from the CSV along with the mapped fields (Default: true)
 *   theme?: EasyCLITheme | null, // The theme to use for the prompts.
 *   validate?: true, // If it should validate the data against the mapping rules, if errors are detected it will throw an error (Default: true)
 * }
 * ```
 */
export type CsvMapperOptions<TObject extends Record<string, any>> = {
    interactive?: boolean;
    discardOriginalFields?: boolean;
    mappings: CsvFieldMappings<TObject>;
    theme?: EasyCLITheme | null;
    validate?: boolean;
};
export declare class CSVMapper<TObject extends Record<string, any> = Record<string, any>, TFileObject extends Record<string, any> = Record<string, any>> {
    private mappings;
    private interactive;
    private discardOriginalFields;
    private theme;
    private validate;
    /**
     * Create a new CSV Mapper instance.
     *
     * @param options The options for the CSV Mapper.
     * @returns {CSVMapper<TObject, TFileObject>} A new CSV Mapper instance.
     *
     * @example
     * const csvProcessor = new CSVMapper({
     * mappings: {
     *  username: {
     *   aliases: ['Username'],
     *   required: true,
     *   transform: value => value,
     *  },
     *  id: {
     *   aliases: ['Identifier'],
     *   required: true,
     *   transform: value => parseInt(value),
     *  },
     *  lastName: {
     *   aliases: [],
     *   required: true,
     *   transform: value => value,
     *  },
     *  firstName: {
     *   aliases: ['First name', 'First Name'],
     *   required: true,
     *   transform: value => value,
     *  },
     *  firstInital: {
     *   aliases: ['First name', 'First Name'],
     *   required: true,
     *   transform: value => value[0],
     *  },
     * },
     * interactive: true,
     * });
     */
    constructor(options: CsvMapperOptions<TObject>);
    /**
     * Read a CSV file and parse it into an array of objects.
     *
     * @param path The path to the CSV file to read.
     * @throws {Error} If the file is not found or there is an error reading the file.
     *
     * @returns The parsed CSV file as an array of objects.
     */
    private readFile;
    /**
     * Prompt the user for missing fields in the mappings.
     *
     * @param missingFields What fields are missing from the mappings
     * @param unmappedColumns What columns are not mapped
     *
     * @returns Additional mappings for the CSV columns
     */
    private promptMissingFields;
    /**
     * Process a CSV file and return the data as an array of transformed objects.
     *
     * @param path The path to the CSV file to process
     *
     * @throws {Error} If there are validation errors in the CSV file and the validate option is set to true.
     *
     * @returns {Promise<TObject[]>} The data from the CSV file as an array of transformed objects
     *
     * @example
     * ```typescript
     * const csvProcessor = new CSVMapper({...});
     * const data = await csvProcessor.processFile('./username.csv');
     * ```
     */
    processFile: (path: string) => Promise<TObject[]>;
    /**
     * Validation for the CSV file, comparing the fields to the mappings.
     *
     * @param rows The rows to validate
     * @param fieldMap The field map to use for validation
     *
     * @throws {Error} If there are validation errors in the CSV file
     */
    private validateData;
    /**
     * Transforn a row from the CSV file into the correct output.
     *
     * @param row The row data to transform
     * @param fieldMapping How to map the fields from the CSV to the object
     *
     * @returns {Promise<TObject>} A normalized row object
     */
    private transformRow;
    /**
     * Build a field map from the columns found in the CSV file.
     *
     * @param {(keyof TFileObject)[]} columns The columns found in the CSV file
     *
     * @returns {ObjectDataMapper<TObject, TFileObject>} A field map that maps the CSV columns to the object fields
     */
    private buildFieldMap;
    /**
     * Find the mapped field for a CSV column.
     *
     * @param {keyof TFileObject} field The field to find the mapped field for
     *
     * @returns {(keyof TObject[])} The mapped fields for the CSV column
     */
    private findMappedField;
}
