import { action, computed, makeObservable, observable } from 'mobx';
import { isPIISupportedByFieldType, isSelectableFieldType, } from './fieldTypeUtils';
function defaultProperties() {
    return {
        type: undefined,
        name: '',
        isPii: false,
        helpText: '',
    };
}
// TODO: confirm vs cms-web
const NAME_MAX_LENGTH = 50;
export class CmsFormState {
    constructor(params) {
        this.properties = defaultProperties();
        this.fieldRules = { validationRules: {} };
        this.touchedFields = new Set();
        this.showValidationError = false;
        this.errorToastConfig = undefined;
        this.schemaConfig = params.schemaConfig;
        this.getValidationRules = params.getValidationRules;
        this.mode = params.mode ?? 'new';
        this.editingFieldId = params.editingFieldId;
        makeObservable(this, {
            properties: observable.ref,
            fieldRules: observable.ref,
            mode: observable.ref,
            editingFieldId: observable.ref,
            touchedFields: observable,
            showValidationError: observable.ref,
            errorToastConfig: observable.ref,
            fieldTypeError: computed,
            nameError: computed,
            hasInvalidFields: computed,
            visibleErrors: computed,
            supportedValidationRules: computed,
            validationErrorMessage: computed,
            setProperty: action,
            setValidationRule: action.bound,
            blurField: action,
            enableShowValidationError: action,
            setMode: action,
            setErrorToastConfig: action,
            loadField: action,
            reset: action,
            hideValidationError: action.bound,
            changeType: action.bound,
            changeName: action.bound,
            setIsPii: action.bound,
            setHelpText: action.bound,
        });
    }
    get fieldTypeError() {
        if (!this.properties.type) {
            return 'Field type is required';
        }
        return undefined;
    }
    get nameError() {
        const name = this.properties.name.trim();
        if (!name) {
            return 'Field name is required';
        }
        if (name.length > NAME_MAX_LENGTH) {
            return `Field name must be ${NAME_MAX_LENGTH} characters or fewer`;
        }
        return undefined;
    }
    get hasInvalidFields() {
        return !!(this.fieldTypeError || this.nameError);
    }
    // Spec §3 specifies booleans; returning the error string directly is more useful for rendering
    // (one property read instead of two). Deviation is intentional — update spec if accepted.
    get visibleErrors() {
        const { showValidationError, touchedFields } = this;
        return {
            type: showValidationError ? this.fieldTypeError : undefined,
            name: showValidationError || touchedFields.has('name')
                ? this.nameError
                : undefined,
        };
    }
    get supportedValidationRules() {
        return this.properties.type
            ? this.getValidationRules(this.properties.type)
            : [];
    }
    get validationErrorMessage() {
        return (this.fieldTypeError ||
            this.nameError ||
            'Please fix the errors before saving');
    }
    setProperty(key, value) {
        this.properties = { ...this.properties, [key]: value };
    }
    setValidationRule(rule, value) {
        this.fieldRules = {
            ...this.fieldRules,
            validationRules: { ...this.fieldRules.validationRules, [rule]: value },
        };
    }
    blurField(field) {
        this.touchedFields.add(field);
    }
    enableShowValidationError() {
        this.showValidationError = true;
    }
    setMode(mode) {
        this.mode = mode;
    }
    setErrorToastConfig(cfg) {
        this.errorToastConfig = cfg;
    }
    reset() {
        this.properties = defaultProperties();
        this.fieldRules = { validationRules: {} };
        this.editingFieldId = undefined;
        this.touchedFields.clear();
        this.showValidationError = false;
        this.errorToastConfig = undefined;
    }
    hideValidationError() {
        this.showValidationError = false;
    }
    changeType(v) {
        this.setProperty('type', v);
        this._onTypeChange(v);
    }
    changeName(v) {
        this.setProperty('name', v);
    }
    setIsPii(v) {
        this.setProperty('isPii', v);
    }
    setHelpText(v) {
        this.setProperty('helpText', v);
    }
    loadField(field) {
        const mappedType = isSelectableFieldType(field.type)
            ? field.type
            : undefined;
        this.properties = {
            type: mappedType,
            name: field.displayName,
            isPii: field.isPii ?? false,
            helpText: field.helpText ?? '',
        };
        this.fieldRules = {
            validationRules: {
                ...(field.validation?.required !== undefined && {
                    required: field.validation.required,
                }),
                ...(field.validation?.stringLengthRange !== undefined && {
                    charactersLimit: field.validation.stringLengthRange,
                }),
            },
        };
        this.editingFieldId = field.id;
        this.errorToastConfig = undefined;
    }
    _onTypeChange(newType) {
        const supported = new Set(this.getValidationRules(newType));
        this.fieldRules = {
            validationRules: Object.fromEntries(Object.entries(this.fieldRules.validationRules).filter(([k]) => supported.has(k))),
        };
        if (!isPIISupportedByFieldType(newType)) {
            this.properties = { ...this.properties, isPii: false };
        }
        this.touchedFields.clear();
    }
}
//# sourceMappingURL=CmsFormState.js.map