"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFieldDecoder = void 0;
exports.getFieldDecoderForDatabaseNative = getFieldDecoderForDatabaseNative;
exports.getFieldDatabaseNativeFieldDecoders = getFieldDatabaseNativeFieldDecoders;
exports.getFieldDecoderForId = getFieldDecoderForId;
exports.getFieldDecoderForScalar = getFieldDecoderForScalar;
exports.getFieldDecoderForRelation = getFieldDecoderForRelation;
exports.getZodFieldDiscriminatedUnionDecoder = getZodFieldDiscriminatedUnionDecoder;
const utils_1 = require("@postxl/utils");
/**
 * Returns the string defining the zod decoder for a given field.
 */
const getFieldDecoder = ({ field, context, imports, includeTransformer = true, allowOptional = false, }) => {
    if (field.kind === 'discriminatedUnion') {
        return getZodFieldDiscriminatedUnionDecoder({ field, context, imports });
    }
    return getFieldDecoderForDatabaseNative({ field, context, imports, includeTransformer, allowOptional });
};
exports.getFieldDecoder = getFieldDecoder;
function getFieldDecoderForDatabaseNative({ field, context, imports, includeTransformer = true, allowOptional = false, }) {
    const parsers = getFieldDatabaseNativeFieldDecoders({ field, context, imports, includeTransformer, allowOptional });
    if (!field.isRequired) {
        parsers.push(`nullable()`);
    }
    return `${field.name}: ${parsers.join('.')}`;
}
function getFieldDatabaseNativeFieldDecoders({ field, context, imports, includeTransformer = true, allowOptional = false, }) {
    switch (field.kind) {
        case 'id':
            return getFieldDecoderForId({ field, context, imports, includeTransformer });
        case 'scalar':
            return getFieldDecoderForScalar({ field, allowOptional });
        case 'relation':
            return getFieldDecoderForRelation({ field, context, imports, includeTransformer });
        case 'enum':
            return getZodParsersForEnum({ field, context });
        default:
            throw new utils_1.ExhaustiveSwitchCheck(field);
    }
}
function getFieldDecoderForId({ field, context, imports, includeTransformer = true, }) {
    const parsers = [];
    // TODO: Adjust for number types
    switch (field.idType) {
        case 'Increment': {
            parsers.push('z.number()');
            break;
        }
        case 'UUID': {
            parsers.push('z.string()');
            break;
        }
        default:
            throw new utils_1.ExhaustiveSwitchCheck(field.idType);
    }
    if (includeTransformer) {
        const model = context.models.get(field.modelName);
        parsers.push(`transform((v) => ${model.types.id.toBranded.name}(v))`);
        imports.addImport({ from: model.types.location, items: [model.types.id.toBranded.name] });
    }
    return parsers;
}
function getFieldDecoderForScalar({ field, allowOptional = false, }) {
    const parsers = [];
    switch (field.type) {
        case 'number': {
            parsers.push('z.number()');
            if (field.validations.type === 'int' || field.databaseType === 'Int' || field.databaseType === 'BigInt') {
                parsers.push('int()');
            }
            if (field.validations.min !== undefined) {
                parsers.push(`min(${field.validations.min})`);
            }
            if (field.validations.max !== undefined) {
                parsers.push(`max(${field.validations.max})`);
            }
            break;
        }
        case 'string': {
            parsers.push('z.string()');
            if (field.validations.maxLength) {
                parsers.push(`max(${field.validations.maxLength})`);
            }
            break;
        }
        case 'boolean': {
            parsers.push('z.boolean()');
            break;
        }
        case 'Date': {
            parsers.push('z.date()');
            break;
        }
        default: {
            throw new utils_1.ExhaustiveSwitchCheck(field);
        }
    }
    if (allowOptional && (field.isCreatedAt || field.isUpdatedAt)) {
        parsers.push('optional()');
    }
    return parsers;
}
function getFieldDecoderForRelation({ field, context, imports, includeTransformer = true, }) {
    const parsers = ['z.string()'];
    if (includeTransformer) {
        const model = context.models.get(field.referencedModelName);
        parsers.push(`transform((v) => ${model.types.id.toBranded.name}(v))`);
        imports.addImport({ from: model.types.location, items: [model.types.id.toBranded.name] });
    }
    return parsers;
}
function getZodParsersForEnum({ field, context }) {
    const enum_ = context.enums.get(field.enumName);
    return [
        `z.enum([${Array.from(enum_.members.values())
            .map((v) => `'${v.value}'`)
            .join(', ')}])`,
    ];
}
function getZodFieldDiscriminatedUnionDecoder({ field, context, imports, }) {
    const result = [];
    result.push(`${field.name}: z.enum([${Array.from(field.members.values())
        .map((m) => `'${m.type}'`)
        .join(', ')}])`);
    for (const f of field.commonFields.values()) {
        result.push(getFieldDecoderForDatabaseNative({ field: { ...f, name: f.databaseName }, context, imports }));
    }
    for (const member of field.members.values()) {
        for (const f of member.fields.values()) {
            result.push(getFieldDecoderForDatabaseNative({
                field: { ...f, name: f.databaseName, isRequired: false },
                context,
                imports,
            }));
        }
    }
    return result.join(', ');
}
//# sourceMappingURL=shared.js.map