import { CSVParser } from '@pawel-up/csv';
import { sanitizeInput, toDatabaseColumnName, toDatabaseTableName } from '../helpers/database.js';
let increment = 0;
/**
 * Imports CSV data into a DataDomain.
 *
 * This class parses CSV files and translates the column definitions into DomainProperty instances
 * within a specified DomainModel and DomainEntity.
 */
export class CsvImporter {
    parser;
    domain;
    /**
     * Creates an instance of CsvImporter.
     * @param domain The DataDomain to which the imported data will be added.
     * @param options Optional CSV parsing options.
     */
    constructor(domain, options) {
        this.parser = new CSVParser(options);
        this.domain = domain;
    }
    /**
     * Parses a CSV file or string to extract its structure and data.
     * This is a wrapper around the underlying CSV parser.
     * @param csv The CSV content to parse, as a File object or a string.
     * @returns A promise that resolves with the parsed result.
     */
    async parse(csv) {
        const result = await this.parser.parse(csv);
        return {
            ...result,
            file: typeof csv === 'string' ? 'inline_csv_' + increment++ : csv.name,
        };
    }
    removeExtension(name) {
        if (name.endsWith('.csv')) {
            name = name.slice(0, -4); // Remove .csv extension if present
        }
        return name;
    }
    /**
     * Imports the parsed CSV data structure into the domain as a new model and entity.
     * It creates a `DomainEntity` where each column from the CSV is represented as a `DomainProperty`.
     * The first row of data is used to provide an example value for each property.
     * @param data The result from the `parse` method, containing the CSV structure and values.
     * @param modelName The name to be used for the created `DomainModel` and `DomainEntity`.
     * @returns A promise that resolves when the import is complete.
     */
    async import(data, modelName) {
        modelName = this.removeExtension(modelName);
        const name = toDatabaseTableName(modelName, 'imported_cvs_data');
        const model = this.domain.addModel({ info: { name } });
        const entity = model.addEntity({ info: { name } });
        const sanitizedInputName = sanitizeInput(modelName);
        if (name !== sanitizedInputName) {
            model.info.displayName = sanitizedInputName;
            entity.info.displayName = sanitizedInputName;
        }
        for (const row of data.format) {
            const { index, name, type, format } = row;
            const columnName = toDatabaseColumnName(name, `column_${index}`);
            const schema = {
                info: { name: columnName },
                type,
            };
            if (format) {
                schema.bindings = [
                    {
                        type: 'web',
                        schema: {
                            format: format === 'integer' ? 'int64' : 'double',
                        },
                    },
                ];
            }
            const exampleRow = data.values[0];
            if (Array.isArray(exampleRow) && exampleRow[index]) {
                const value = exampleRow[index];
                if (value !== undefined && value !== null) {
                    schema.schema = {
                        examples: [sanitizeInput(String(value))],
                    };
                }
            }
            const prop = entity.addProperty(schema);
            const sn = sanitizeInput(name);
            if (sn !== columnName) {
                prop.info.displayName = sn;
            }
        }
        return { entity, model };
    }
    /**
     * Imports multiple parsed CSV data structures into the same data model.
     * Creates a single `DomainModel` with multiple `DomainEntity` instances, one for each CSV data structure.
     * Each entity represents the structure of its corresponding CSV file.
     * @param data Array of objects containing parsed CSV data and entity names.
     * @param modelName The name to be used for the created `DomainModel`.
     * @returns A promise that resolves with the created model and all entities.
     */
    async importMany(data, modelName) {
        modelName = this.removeExtension(modelName);
        const name = toDatabaseTableName(modelName, 'imported_cvs_data');
        const model = this.domain.addModel({ info: { name } });
        const sanitizedModelName = sanitizeInput(modelName);
        if (name !== sanitizedModelName) {
            model.info.displayName = sanitizedModelName;
        }
        const entities = [];
        for (const { format, values, file } of data) {
            const cleanFile = this.removeExtension(file);
            const entityDbName = toDatabaseTableName(cleanFile, `entity_${entities.length}`);
            const entity = model.addEntity({ info: { name: entityDbName } });
            const sanitizedEntityName = sanitizeInput(cleanFile);
            if (entityDbName !== sanitizedEntityName) {
                entity.info.displayName = sanitizedEntityName;
            }
            const exampleRow = values[0];
            for (const row of format) {
                const { index, name, type, format } = row;
                const columnName = toDatabaseColumnName(name, `column_${index}`);
                const schema = {
                    info: { name: columnName },
                    type,
                };
                if (format) {
                    schema.bindings = [
                        {
                            type: 'web',
                            schema: {
                                format: format === 'integer' ? 'int64' : 'double',
                            },
                        },
                    ];
                }
                if (Array.isArray(exampleRow) && exampleRow[index]) {
                    const value = exampleRow[index];
                    if (value !== undefined && value !== null) {
                        schema.schema = {
                            examples: [sanitizeInput(String(value))],
                        };
                    }
                }
                const prop = entity.addProperty(schema);
                const sn = sanitizeInput(name);
                if (sn !== columnName) {
                    prop.info.displayName = sn;
                }
            }
            entities.push(entity);
        }
        return { entities, model };
    }
}
//# sourceMappingURL=CsvImporter.js.map