import { DomainAssociationKind } from '../../models/kinds.js';
import { validatePropertyName } from './rules.js';
/**
 * AssociationValidation is a class that performs validation on associations in a data domain.
 * Note that an association in most cases is a property of an entity.
 */
export class AssociationValidation {
    domain;
    constructor(domain) {
        this.domain = domain;
    }
    /**
     * Performs all the validation rules on the association.
     * If you are interested in a specific rule, use the specific method.
     * @param target The target association to validate. Can be a string with
     *               the association key or a DomainAssociation object.
     */
    validate(target) {
        const results = [];
        let association;
        if (typeof target === 'string') {
            association = this.domain.findAssociation(target);
        }
        else {
            association = target;
        }
        if (!association) {
            const message = `The "${target}" association does not exist.`;
            const help = `The association must be defined in the domain.`;
            results.push({
                field: '*',
                rule: 'exists',
                message,
                help,
                key: target,
                kind: DomainAssociationKind,
                severity: 'error',
            });
            return results;
        }
        const name = this.validateName(association);
        results.push(...name);
        const targets = this.validateTargets(association);
        results.push(...targets);
        return results;
    }
    /**
     * Validates the association name.
     *
     * @remarks
     * - A association must have a name defined.
     * - The name has to follow the same rules as the names in a PostgreSQL database.
     *   - Column names can only contain letters (a-z, A-Z), numbers (0-9), and underscores (_).
     *   - The name must start with a letter (a-z, A-Z) or an underscore (_).
     *   - PostgreSQL limits column names to a maximum of 59 characters.
     *   - (our rule) Column names are case insensitive.
     *   - (recommendation) Column names should be in lower case.
     * @param association The association to validate
     */
    validateName(association) {
        return validatePropertyName(association);
    }
    /**
     * Validates the association targets.
     * @param association The association to validate
     */
    validateTargets(association) {
        const results = [];
        const label = association.info.getLabel();
        const parentEntity = association.getParentInstance();
        if (!association.targets.length) {
            const message = `The "${label}" association has no target.`;
            const help = `An association must have at least one target.`;
            results.push({
                field: 'targets',
                rule: 'required',
                message,
                help,
                severity: 'error',
                key: association.key,
                kind: association.kind,
                parent: parentEntity.key,
            });
            return results;
        }
        for (const target of association.targets) {
            const entity = target.domain
                ? this.domain.findForeignEntity(target.key, target.domain)
                : this.domain.findEntity(target.key);
            if (!entity) {
                const message = `The "${label}" association has an invalid target "${target.key}".`;
                const help = `The target must be defined in the domain.`;
                results.push({
                    field: 'targets',
                    rule: 'exists',
                    message,
                    help,
                    severity: 'error',
                    key: association.key,
                    kind: association.kind,
                    parent: parentEntity.key,
                });
            }
        }
        return results;
    }
}
//# sourceMappingURL=association_validation.js.map