import { CHECKMARK, parseBooleanValue, PROPERTY_HEADERS, } from '../domain/types.js';
function getValuesField(property) {
    if (property.type === 'enum' && property.enumOptions) {
        return property.enumOptions.join(', ');
    }
    if (property.type === 'array' &&
        property.arrayOptions?.type === 'enum' &&
        property.arrayOptions?.enumOptions) {
        return property.arrayOptions.enumOptions.join(', ');
    }
    if (property.type === 'decimal' && property.decimals) {
        return property.decimals.join(', ');
    }
    return '';
}
const RELATIONSHIP_TYPE_MAP = {
    'many-to-many': 'N:N',
    'many-to-one': 'N:1',
    'one-to-many': '1:N',
    'one-to-one': '1:1',
};
const RELATIONSHIP_TYPE_REVERSE_MAP = {
    '1:1': 'one-to-one',
    '1:N': 'one-to-many',
    'N:1': 'many-to-one',
    'N:N': 'many-to-many',
};
function relationshipTypeToSheet(type) {
    if (!type)
        return '';
    return RELATIONSHIP_TYPE_MAP[type] || type;
}
function sheetToRelationshipType(type) {
    if (!type)
        return '';
    return RELATIONSHIP_TYPE_REVERSE_MAP[type] || type;
}
function getModuleNameFromPath(modulePath) {
    if (!modulePath)
        return '';
    const parts = modulePath.split('/');
    return parts.at(-1) || '';
}
function getLengthValue(property) {
    if (property.type === 'char' && property.length !== undefined) {
        return property.length.toString();
    }
    if (property.maxLength !== undefined) {
        return property.maxLength.toString();
    }
    return '';
}
export function propertyToSheetRow(property) {
    return {
        'arrayOptions.enumOptions': formatEnumOptions(property.arrayOptions?.enumOptions),
        'arrayOptions.maxLength': property.arrayOptions?.maxLength?.toString() || '',
        'arrayOptions.type': property.arrayOptions?.type || '',
        autoIncrement: boolToString(property.autoIncrement),
        decimals: formatDecimals(property.decimals),
        defaultValue: formatDefaultValue(property.defaultValue),
        description: cleanDescription(property.description),
        enumOptions: formatEnumOptions(property.enumOptions),
        example: formatExample(property.example),
        index: property.index || '',
        indexUsing: property.indexUsing || '',
        isI18n: boolToString(property.isI18n),
        master: getModuleNameFromPath(property.relationship?.modulePath),
        'maxLength/length': getLengthValue(property),
        name: property.name || '',
        nullable: boolToString(property.nullable),
        primaryKey: boolToString(property.primaryKey),
        'rel.aggregateName': property.relationship?.aggregateName || '',
        'rel.avoidConstraint': boolToString(property.relationship?.avoidConstraint),
        'rel.field': property.relationship?.field || '',
        'rel.key': property.relationship?.key || '',
        'rel.modulePath': property.relationship?.modulePath || '',
        'rel.singularName': property.relationship?.singularName || '',
        'rel.type': property.relationship?.type || '',
        relationship: relationshipTypeToSheet(property.relationship?.type),
        subtype: property.type === 'array' ? property.arrayOptions?.type || '' : '',
        type: property.type || '',
        values: getValuesField(property),
    };
}
export function sheetRowToProperty(row) {
    const property = {
        name: row.name,
        type: row.type,
    };
    if (parseBooleanValue(row.primaryKey))
        property.primaryKey = true;
    property.nullable = Boolean(parseBooleanValue(row.nullable));
    if (row.index)
        property.index = row.index;
    if (row.indexUsing)
        property.indexUsing = row.indexUsing;
    const lengthValue = row['maxLength/length'];
    if (lengthValue) {
        if (row.type === 'char') {
            property.length = Number.parseInt(lengthValue, 10);
        }
        else {
            property.maxLength = Number.parseInt(lengthValue, 10);
        }
    }
    if (row.type === 'enum' && row.values) {
        property.enumOptions = parseEnumOptions(row.values);
    }
    else if (row.enumOptions) {
        property.enumOptions = parseEnumOptions(row.enumOptions);
    }
    if (row.type === 'decimal' && row.values) {
        property.decimals = parseDecimals(row.values);
    }
    else if (row.decimals) {
        property.decimals = parseDecimals(row.decimals);
    }
    if (row.defaultValue) {
        const parsedDefault = parseDefaultValue(row.defaultValue);
        property.defaultValue = row.type === 'array' && !Array.isArray(parsedDefault) ? [parsedDefault] : parsedDefault;
    }
    if (parseBooleanValue(row.autoIncrement))
        property.autoIncrement = true;
    if (parseBooleanValue(row.isI18n))
        property.isI18n = true;
    if (row.example)
        property.example = parseExample(row.example);
    if (row.description)
        property.description = row.description;
    const arrayType = row.subtype || row['arrayOptions.type'];
    if (row.type === 'array' && arrayType) {
        property.arrayOptions = {
            type: arrayType,
        };
        if (row['arrayOptions.maxLength']) {
            property.arrayOptions.maxLength = Number.parseInt(row['arrayOptions.maxLength'], 10);
        }
        if (arrayType === 'enum' && row.values) {
            property.arrayOptions.enumOptions = parseEnumOptions(row.values);
        }
        else if (row['arrayOptions.enumOptions']) {
            property.arrayOptions.enumOptions = parseEnumOptions(row['arrayOptions.enumOptions']);
        }
    }
    const relType = row.relationship
        ? sheetToRelationshipType(row.relationship)
        : row['rel.type'];
    if (relType) {
        property.relationship = {
            aggregateName: row['rel.aggregateName'],
            modulePath: row['rel.modulePath'],
            type: relType,
        };
        if (row['rel.singularName'])
            property.relationship.singularName = row['rel.singularName'];
        if (row['rel.key'])
            property.relationship.key = row['rel.key'];
        if (row['rel.field'])
            property.relationship.field = row['rel.field'];
        if (parseBooleanValue(row['rel.avoidConstraint']))
            property.relationship.avoidConstraint = true;
    }
    return property;
}
export function propertiesToSheetValues(properties) {
    const rows = [PROPERTY_HEADERS];
    for (const prop of properties) {
        const row = propertyToSheetRow(prop);
        const values = PROPERTY_HEADERS.map((header) => row[header] || '');
        rows.push(values);
    }
    return rows;
}
export function sheetValuesToProperties(values) {
    if (values.length < 2)
        return [];
    const headers = values[0];
    const properties = [];
    for (let i = 1; i < values.length; i++) {
        const rowValues = values[i];
        if (!rowValues || !rowValues[0])
            continue;
        const row = {};
        for (const [j, header] of headers.entries()) {
            row[header] = rowValues[j] || '';
        }
        properties.push(sheetRowToProperty(row));
    }
    return properties;
}
function boolToString(value) {
    if (value === true)
        return CHECKMARK;
    return '';
}
function formatDecimals(decimals) {
    if (!decimals || !Array.isArray(decimals))
        return '';
    return `${decimals[0]},${decimals[1]}`;
}
function parseDecimals(value) {
    const parts = value.split(',').map((s) => Number.parseInt(s.trim(), 10));
    return [parts[0], parts[1]];
}
function formatEnumOptions(options) {
    if (!options || !Array.isArray(options))
        return '';
    return options.join(',');
}
function parseEnumOptions(value) {
    if (!value)
        return [];
    return value
        .split(',')
        .map((s) => s.trim())
        .filter(Boolean);
}
function formatDefaultValue(value) {
    if (value === undefined || value === null)
        return '';
    if (typeof value === 'boolean')
        return value ? 'true' : 'false';
    return String(value);
}
function parseDefaultValue(value) {
    if (value === 'true')
        return true;
    if (value === 'false')
        return false;
    if (value === 'null')
        return null;
    const num = Number(value);
    if (!Number.isNaN(num) && value.trim() !== '')
        return num;
    return value;
}
function formatExample(value) {
    if (value === undefined || value === null)
        return '';
    if (typeof value === 'object')
        return JSON.stringify(value);
    return String(value);
}
function parseExample(value) {
    if (!value)
        return undefined;
    try {
        return JSON.parse(value);
    }
    catch {
        return value;
    }
}
function cleanDescription(desc) {
    if (!desc)
        return '';
    return desc
        .split('\n')
        .map((line) => line.trim())
        .join('\n')
        .trim();
}
