import { DataExtensionSchemaService, } from '../services';
import { TaskState } from './TaskState';
import { action, computed, makeObservable, observable, runInAction, } from 'mobx';
import { fqdnToString } from '../util';
import { includesAllReadPermissions } from './DataExtension/DataExtensionField';
import { ConditionalModalState } from './ConditionalModalState';
import { DeleteFieldModalState } from './DeleteFieldModalState';
export const MAX_CUSTOM_FIELDS = 50;
/**
 * Manages data extension schemas and custom fields for a collection
 */
export class DataExtensionState {
    get fqdnString() {
        return fqdnToString(this.fqdn);
    }
    get isFqdnValid() {
        return this.fqdn.resource !== undefined;
    }
    constructor(params) {
        this.initTask = new TaskState();
        this._dataExtensionSchemasBase = [];
        this.isArchivedPanelOpen = false;
        this.deleteConfirmModal = new ConditionalModalState();
        this.container = params.container;
        this.disableUserDefinedWriting = params.disableUserDefinedWriting;
        this.filterable = params.filterable;
        this.enableArchive = params.enableArchive ?? true;
        this.closeSidePanel = params.closeSidePanel;
        this.fqdn = params.fqdn;
        this._extensionPoint = params.extensionPoint;
        this.dataExtensionService = new DataExtensionSchemaService(params.container);
        this.containsPii = params.containsPii;
        this.defaultPermissions = params.defaultPermissions;
        // Initialize deleteFieldModal with proper reportBi
        this.deleteFieldModal = new DeleteFieldModalState({
            dataExtension: this,
            reportBi: params.container.createBILogger({
                componentType: 'DataExtension',
                ...params.fqdn,
            }),
        });
        makeObservable(this, {
            allUserCustomFields: computed,
            allAppsCustomFields: computed,
            allCustomFields: computed,
            archivedItems: computed,
            shouldDisplayArchive: computed,
            filterableCustomFields: computed,
            availableUserCustomFields: computed,
            availableAppsCustomFields: computed,
            availableCustomFields: computed,
            isReachedMaxCustomFields: computed,
            disableAddCustomField: computed,
            disableAddCustomFieldContent: computed,
            _dataExtensionSchemasBase: observable.ref,
            _dataExtensionSchemas: computed,
            userSchema: computed,
            appSchemas: computed,
            _upsertSchema: action,
            containsPii: observable,
            defaultPermissions: observable,
            isArchivedPanelOpen: observable,
            deleteFieldModal: observable.ref,
            openArchivedPanel: action,
            closeArchivedPanel: action,
            openDeleteConfirmModal: action,
        });
    }
    get hasWritePermissions() {
        if (this._hasWritePermissions == null) {
            this._hasWritePermissions = this.container.user.permissions.includes('DATA_EXTENSION_SCHEMA.WRITE');
        }
        return this._hasWritePermissions;
    }
    get disableAddCustomField() {
        return !this.hasWritePermissions || this.isReachedMaxCustomFields;
    }
    get disableAddCustomFieldContent() {
        if (!this.hasWritePermissions) {
            return this.container.translate('cairo.customFields.writePermission.tooltip');
        }
        if (this.isReachedMaxCustomFields) {
            return this.container.translate('cairo.customFields.maxFields.tooltip', {
                max: MAX_CUSTOM_FIELDS,
            });
        }
        return '';
    }
    getArchiveSuccessToastMessage(fieldName) {
        return this.enableArchive && fieldName
            ? this.container.translate('cairo.customFields.archive.success.toast.enabled', { selectedField: fieldName })
            : this.container.translate('cairo.customFields.archive.success.toast');
    }
    getArchiveSuccessToastAction() {
        return this.enableArchive
            ? {
                text: this.container.translate('cairo.customFields.archive.success.toast.CTA'),
                uiType: 'LINK',
                onClick: () => this.openArchivedPanel?.(),
            }
            : undefined;
    }
    /**
     * Lazily loads the field operations service to reduce bundle size.
     * Only loads when archive/restore/delete operations are needed.
     */
    async getFieldOperationsService() {
        if (this._fieldOperationsService) {
            return this._fieldOperationsService;
        }
        // Reuse the same promise if already loading
        if (this._fieldOperationsServicePromise) {
            return this._fieldOperationsServicePromise;
        }
        this._fieldOperationsServicePromise = import('../services/DataExtensionFieldOperationsService').then((module) => {
            const self = this;
            this._fieldOperationsService =
                new module.DataExtensionFieldOperationsService({
                    container: this.container,
                    dataExtensionService: this.dataExtensionService,
                    get userSchema() {
                        return self.userSchema;
                    },
                    fqdnString: this.fqdnString,
                    enableArchive: this.enableArchive,
                    extractFieldValuesFromSchema: this.extractFieldValuesFromSchema.bind(this),
                    upsertSchema: this._upsertSchema.bind(this),
                    openArchivedPanel: this.openArchivedPanel.bind(this),
                });
            return this._fieldOperationsService;
        });
        return this._fieldOperationsServicePromise;
    }
    async archiveField({ id, origin, reportBi, }) {
        const service = await this.getFieldOperationsService();
        return service.archiveField({ id, origin, reportBi });
    }
    async restoreField({ id, origin, reportBi, }) {
        const service = await this.getFieldOperationsService();
        return service.restoreField({ id, origin, reportBi });
    }
    async deleteField({ id, origin, reportBi, }) {
        const service = await this.getFieldOperationsService();
        return service.deleteField({ id, origin, reportBi });
    }
    extractFieldValuesFromSchema(fieldId) {
        if (!this.userSchema) {
            return;
        }
        const customField = DataExtensionSchemaService.toCustomField(this.userSchema, fieldId);
        if (!customField || !customField.type || !customField.title) {
            return;
        }
        const { read, write } = customField['x-wix-permissions'];
        const isPiiField = customField['x-wix-pii']?.enabled;
        const readApps = read?.includes('apps');
        const readUsers = read?.includes('users-of-users');
        const writeApps = write?.includes('apps');
        const writeUsers = write?.includes('users-of-users');
        return {
            type: DataExtensionSchemaService.toCustomType(customField),
            name: customField.title,
            key: customField.id,
            readApps,
            readUsers,
            writeApps,
            writeUsers,
            containsPii: Boolean(isPiiField),
        };
    }
    _toCustomField({ key, schema, editable, owner, namespace, }) {
        if (!DataExtensionSchemaService.toCustomType(schema)) {
            return;
        }
        return {
            id: key,
            label: schema?.title || key,
            maxLength: schema?.maxLength,
            options: schema?.enum,
            type: DataExtensionSchemaService.toCustomType(schema),
            editable,
            filterable: schema['x-wix-filterable'],
            owner,
            properties: schema?.properties ?? {},
            namespace,
            isPii: Boolean(schema['x-wix-pii']?.enabled),
            permissions: schema['x-wix-permissions'],
        };
    }
    isSupportedFieldType(type) {
        if (!type) {
            return false;
        }
        return ['string', 'number', 'integer', 'boolean', 'array'].includes(type);
    }
    getAvailableCustomFieldsInSchema(properties, { editable, requiredPermissions, owner, namespace, }) {
        const filteredFields = Object.keys(properties).filter((key) => {
            const field = properties[key];
            const isAllowedType = this.isSupportedFieldType(field.type) ||
                (field.type === 'object' && field['x-wix-object-type'] === 'FILE/V1');
            const isPermitted = requiredPermissions == null ||
                includesAllReadPermissions(field, requiredPermissions);
            return !field['x-wix-archived'] && isAllowedType && isPermitted;
        });
        const sorted = filteredFields.sort((a, b) => {
            const aVal = new Date(properties[a]['x-wix-created-date']);
            const bVal = new Date(properties[b]['x-wix-created-date']);
            if (isNaN(bVal.valueOf()) || isNaN(aVal.valueOf())) {
                return 0;
            }
            return aVal.valueOf() - bVal.valueOf();
        });
        return sorted
            .map((key) => this._toCustomField({
            key,
            schema: properties[key],
            editable,
            owner,
            namespace,
        }))
            .filter(Boolean);
    }
    /**
     * Available custom fields, excluding archived fields
     */
    get availableUserCustomFields() {
        const properties = this.userSchema?.jsonSchema?.properties || {};
        return this.getAvailableCustomFieldsInSchema(properties, {
            editable: true,
            owner: 'user',
            namespace: '_user_fields',
        });
    }
    get availableAppsCustomFields() {
        return (this.appSchemas?.reduce((prev, schema) => {
            return [...prev, ...this.getAvailableCustomFieldsForApp(schema)];
        }, []) ?? []);
    }
    getSchemaAndFieldsByNamespace(namespace) {
        const { _dataExtensionSchemas, dataExtensionService: { userFieldsNamespace }, } = this;
        const schema = _dataExtensionSchemas.find((s) => s.namespace === namespace);
        if (!schema) {
            return {};
        }
        const isAppNamespace = namespace !== userFieldsNamespace;
        const fields = this.getAvailableCustomFieldsInSchema(schema.jsonSchema?.properties || {}, {
            editable: false,
            owner: isAppNamespace ? 'app' : 'user',
            namespace,
            requiredPermissions: isAppNamespace ? ['users'] : undefined,
        });
        return {
            schema,
            fields,
        };
    }
    getAvailableCustomFieldsForApp(appSchema) {
        const properties = appSchema.jsonSchema?.properties || {};
        return this.getAvailableCustomFieldsInSchema(properties, {
            editable: false,
            requiredPermissions: ['users'],
            owner: 'app',
            namespace: appSchema.namespace,
        });
    }
    get availableCustomFields() {
        return [
            ...this.availableUserCustomFields,
            ...this.availableAppsCustomFields,
        ];
    }
    get allUserCustomFields() {
        const properties = this.userSchema?.jsonSchema?.properties || {};
        return Object.keys(properties)
            .map((key) => this._toCustomField({
            key,
            schema: properties[key],
            editable: true,
            owner: 'user',
            namespace: '_user_fields',
        }))
            .filter(Boolean);
    }
    get allAppsCustomFields() {
        return (this.appSchemas?.reduce((prev, appSchema) => {
            const properties = appSchema?.jsonSchema?.properties || {};
            return prev.concat(Object.keys(properties)
                .map((key) => this._toCustomField({
                key,
                schema: properties[key],
                editable: false,
                owner: 'app',
                namespace: appSchema.namespace,
            }))
                .filter(Boolean));
        }, []) ?? []);
    }
    get allCustomFields() {
        return [...this.allUserCustomFields, ...this.allAppsCustomFields];
    }
    get archivedItems() {
        const userSchema = this.userSchema;
        if (!userSchema?.jsonSchema?.properties) {
            return [];
        }
        const properties = userSchema.jsonSchema.properties;
        return Object.keys(properties)
            .filter((key) => properties[key]['x-wix-archived'])
            .map((key) => ({
            ...properties[key],
            id: key,
            label: properties[key]?.title || key,
            isPii: Boolean(properties[key]?.['x-wix-pii']?.enabled),
        }));
    }
    get shouldDisplayArchive() {
        return this.enableArchive && this.archivedItems.length > 0;
    }
    get filterableCustomFields() {
        if (!this.filterable) {
            return [];
        }
        return this.availableCustomFields.filter((field) => field.filterable);
    }
    get isReachedMaxCustomFields() {
        return this.allUserCustomFields.length >= MAX_CUSTOM_FIELDS;
    }
    get allNamespaces() {
        return [
            this.userSchema?.namespace,
            ...(this.appSchemas || []).map((schema) => schema.namespace),
        ].filter(Boolean);
    }
    init() {
        const { initTask } = this;
        initTask.runOnce(async () => {
            await this.fetchSchemas();
        });
        return () => { };
    }
    _upsertSchema(newSchema) {
        const { _dataExtensionSchemasBase } = this;
        const index = _dataExtensionSchemasBase.findIndex((schema) => schema.namespace === newSchema?.namespace);
        if (index === -1) {
            this._dataExtensionSchemasBase = [
                ..._dataExtensionSchemasBase,
                newSchema,
            ];
        }
        else {
            this._dataExtensionSchemasBase = _dataExtensionSchemasBase.map((schema) => schema.namespace === newSchema.namespace ? newSchema : schema);
        }
    }
    get userSchema() {
        const { _dataExtensionSchemas, dataExtensionService: { userFieldsNamespace }, } = this;
        return _dataExtensionSchemas.find((s) => s.namespace === userFieldsNamespace);
    }
    get _dataExtensionSchemas() {
        const { _extensionPoint, _dataExtensionSchemasBase } = this;
        return _dataExtensionSchemasBase.filter((s) => _extensionPoint
            ? s.extensionPoint === _extensionPoint
            : s.extensionPoint == null || s.extensionPoint === 'ROOT');
    }
    get appSchemas() {
        const { _dataExtensionSchemas, dataExtensionService: { userFieldsNamespace }, } = this;
        return _dataExtensionSchemas.filter((s) => s.namespace !== userFieldsNamespace);
    }
    async fetchSchemas() {
        const { dataExtensionService } = this;
        if (this.isFqdnValid) {
            const { dataExtensionSchemas } = await dataExtensionService.fetchSchemas(this.fqdnString);
            runInAction(() => {
                this._dataExtensionSchemasBase = dataExtensionSchemas ?? [];
            });
        }
    }
    openArchivedPanel() {
        if (this.enableArchive) {
            this.isArchivedPanelOpen = true;
        }
    }
    closeArchivedPanel() {
        this.isArchivedPanelOpen = false;
    }
    openDeleteConfirmModal({ id, origin }) {
        this.deleteConfirmModal.open({ id, origin });
    }
}
//# sourceMappingURL=DataExtensionState.js.map