import { clientFrameworkTypes, fieldTypes, validations } from '../../../lib/jhipster/index.js';
import getTypescriptKeyType from './types-utils.js';
import { filterRelevantRelationships, generateTestEntityId } from './template-utils.js';
const dbTypes = fieldTypes;
const { Validations: { REQUIRED }, } = validations;
const { STRING: TYPE_STRING, INTEGER: TYPE_INTEGER, LONG: TYPE_LONG, BIG_DECIMAL: TYPE_BIG_DECIMAL, FLOAT: TYPE_FLOAT, DOUBLE: TYPE_DOUBLE, UUID: TYPE_UUID, BOOLEAN: TYPE_BOOLEAN, LOCAL_DATE: TYPE_LOCAL_DATE, ZONED_DATE_TIME: TYPE_ZONED_DATE_TIME, INSTANT: TYPE_INSTANT, DURATION: TYPE_DURATION, LOCAL_TIME: TYPE_TIME, } = dbTypes.CommonDBTypes;
const TYPE_BYTES = dbTypes.RelationalOnlyDBTypes.BYTES;
const TYPE_BYTE_BUFFER = dbTypes.RelationalOnlyDBTypes.BYTE_BUFFER;
const { ANGULAR, VUE } = clientFrameworkTypes;
const generateEntityClientFields = (primaryKey, fields, relationships, dto, customDateType = 'dayjs.Dayjs', embedded = false, clientFramework = ANGULAR) => {
    const variablesWithTypes = [];
    if (!embedded && primaryKey) {
        const tsKeyType = getTypescriptKeyType(primaryKey);
        if (clientFramework === VUE) {
        }
    }
    fields.forEach(field => {
        const fieldType = field.fieldType;
        const fieldName = field.fieldName;
        const nullable = !field.id && field.nullable;
        const comment = field.bcTitle || field.javadoc || '';
        let tsType = 'any';
        if (field.fieldIsEnum) {
            tsType = `keyof typeof ${fieldType}`;
        }
        else if (fieldType === TYPE_BOOLEAN) {
            tsType = 'boolean';
        }
        else if ([TYPE_INTEGER, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_BIG_DECIMAL].includes(fieldType)) {
            tsType = 'number';
        }
        else if ([TYPE_STRING, TYPE_UUID, TYPE_DURATION, TYPE_BYTES, TYPE_BYTE_BUFFER, TYPE_TIME].includes(fieldType)) {
            tsType = 'string';
            if ([TYPE_BYTES, TYPE_BYTE_BUFFER].includes(fieldType) && field.fieldTypeBlobContent !== 'text') {
                variablesWithTypes.push({ field: `${fieldName}ContentType?: ${nullable ? 'string | null' : 'string'}`, comment });
            }
            if (field.customWrapType) {
                const fieldCustomTypeData = field.customWrapType.split('_');
                if (fieldCustomTypeData.length === 2) {
                    if (fieldCustomTypeData[0].toLowerCase() === 'array' || fieldCustomTypeData[0].toLowerCase() === 'list') {
                        if ([TYPE_INTEGER, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_BIG_DECIMAL]
                            .map(item => item.toLowerCase())
                            .includes(fieldCustomTypeData[1].toLowerCase())) {
                            tsType = 'number';
                        }
                        tsType = `${tsType}[]`;
                    }
                }
            }
        }
        else if ([TYPE_LOCAL_DATE, TYPE_INSTANT, TYPE_ZONED_DATE_TIME].includes(fieldType)) {
            tsType = customDateType;
        }
        if (nullable) {
            tsType += ' | null';
        }
        variablesWithTypes.push({ field: `${fieldName}?: ${tsType}`, comment });
    });
    const relevantRelationships = filterRelevantRelationships(relationships);
    relevantRelationships.forEach(relationship => {
        let fieldType;
        let fieldName;
        const comment = relationship.bcTitle || relationship.javadoc || '';
        const nullable = !relationship.relationshipValidateRules?.includes(REQUIRED);
        const relationshipType = relationship.relationshipType;
        if (relationshipType === 'one-to-many' || relationshipType === 'many-to-many') {
            if (relationshipType === 'one-to-many' &&
                relationship?.source?.annotationOnSource?.includes('unidirectional') &&
                relationship?.source?.annotationOnSource?.includes('countByPrimaryKey')) {
                fieldType = 'number';
                fieldName = `${relationship.relationshipFieldNamePlural}Count`;
            }
            else {
                fieldType = `I${relationship.otherEntityAngularName}[]`;
                fieldName = relationship.relationshipFieldNamePlural;
            }
        }
        else {
            fieldType = `I${relationship.otherEntityAngularName}`;
            fieldName = relationship.relationshipFieldName;
            if (relationshipType === 'many-to-one' && !relationship.options?.source?.annotationOnSource?.includes('relateByIdEntity')) {
                let addFieldType = `${relationship.otherEntity.primaryKey.tsType}`;
                addFieldType += ' | null';
                const addFieldName = `${relationship.relationshipFieldName}${relationship.otherEntity.primaryKey.nameCapitalized}`;
                const addComment = `${relationship.relationshipFieldName}ID`;
                variablesWithTypes.push({ field: `${addFieldName}?: ${addFieldType}`, addComment });
            }
        }
        if (nullable) {
            fieldType += ' | null';
        }
        variablesWithTypes.push({ field: `${fieldName}?: ${fieldType}`, comment });
    });
    return variablesWithTypes;
};
export const generateTestEntity = (references, index = 'random') => {
    const entries = references
        .map(reference => {
        if (index === 'random') {
            const field = reference.field;
            const fakeData = field.generateFakeData('json-serializable');
            if (reference.field.fieldWithContentType) {
                return [
                    [reference.name, fakeData],
                    [field.contentTypeFieldName, 'unknown'],
                ];
            }
            return [[reference.name, fakeData]];
        }
        return [[reference.name, generateTestEntityId(reference.type, index, false)]];
    })
        .flat();
    return Object.fromEntries(entries);
};
export default generateEntityClientFields;
