var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { diffWords } from '../../../../core/utils/index.js';
import { css, customElement, html, nothing, repeat, state, unsafeHTML } from '../../../../../external/lit/index.js';
import { UmbModalBaseElement } from '../../../../core/modal/index.js';
import { UmbTextStyles } from '../../../../core/style/index.js';
import { UmbUserItemRepository } from '../../../../user/user/index.js';
import { UMB_PROPERTY_DATASET_CONTEXT } from '../../../../core/property/index.js';
import { UMB_APP_LANGUAGE_CONTEXT, UmbLanguageItemRepository } from '../../../../language/index.js';
import { UMB_ENTITY_CONTEXT } from '../../../../core/entity/index.js';
import { UmbVariantId } from '../../../../core/variant/index.js';
import { UMB_ACTION_EVENT_CONTEXT } from '../../../../core/action/index.js';
import { UmbEntityUpdatedEvent, UmbRequestReloadStructureForEntityEvent } from '../../../../core/entity-action/index.js';
import { createExtensionApiByAlias } from '../../../../core/extension-registry/index.js';
let UmbContentRollbackModalElement = class UmbContentRollbackModalElement extends UmbModalBaseElement {
    #rollbackRepository;
    #userItemRepository;
    #localizeDateOptions;
    #currentDocument;
    #currentAppCulture;
    #currentDatasetCulture;
    constructor() {
        super();
        this._versions = [];
        this._selectedCulture = null;
        this._isInvariant = true;
        this._availableVariants = [];
        this._diffs = [];
        this._showDiff = false;
        this.#userItemRepository = new UmbUserItemRepository(this);
        this.#localizeDateOptions = {
            day: 'numeric',
            month: 'long',
            hour: 'numeric',
            minute: '2-digit',
        };
        this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (instance) => {
            this.#currentDatasetCulture = instance?.getVariantId().culture ?? undefined;
            this.#selectCulture();
        });
        this.consumeContext(UMB_APP_LANGUAGE_CONTEXT, (instance) => {
            this.#currentAppCulture = instance?.getAppCulture();
            this.#selectCulture();
        });
        this.consumeContext(UMB_ENTITY_CONTEXT, async (instance) => {
            if (!instance)
                return;
            const unique = instance.getUnique();
            if (!unique) {
                throw new Error('Entity unique is not set');
            }
            if (!this.data?.detailRepositoryAlias) {
                throw new Error('detailRepositoryAlias is not configured in the modal data.');
            }
            if (!this.data?.rollbackRepositoryAlias) {
                throw new Error('rollbackRepositoryAlias is not configured in the modal data.');
            }
            const detailRepository = await createExtensionApiByAlias(this, this.data.detailRepositoryAlias);
            const { data } = await detailRepository.requestByUnique(unique);
            if (!data)
                return;
            this.#currentDocument = data;
            const itemVariants = this.#currentDocument?.variants ?? [];
            this._isInvariant = itemVariants.length === 1 && new UmbVariantId(itemVariants[0].culture).isInvariant();
            this.#selectCulture();
            const cultures = itemVariants.map((x) => x.culture).filter((x) => x !== null);
            const { data: languageItems } = await new UmbLanguageItemRepository(this).requestItems(cultures);
            if (languageItems) {
                this._availableVariants = languageItems.map((language) => {
                    return {
                        name: language.name,
                        value: language.unique,
                        selected: language.unique === this._selectedCulture,
                    };
                });
            }
            else {
                this._availableVariants = [];
            }
            this.#rollbackRepository = await createExtensionApiByAlias(this, this.data.rollbackRepositoryAlias);
            this.#requestVersions();
        });
    }
    #selectCulture() {
        const contextCulture = this.#currentDatasetCulture ?? this.#currentAppCulture ?? null;
        this._selectedCulture = this._isInvariant ? null : contextCulture;
    }
    async #requestVersions() {
        if (!this.#currentDocument?.unique) {
            throw new Error('Entity unique is not set');
        }
        if (!this.#rollbackRepository) {
            throw new Error('Rollback repository is not set');
        }
        const { data } = await this.#rollbackRepository.requestVersionsByEntityId(this.#currentDocument.unique, this._selectedCulture ?? undefined);
        if (!data)
            return;
        const tempItems = [];
        const uniqueUserIds = [...new Set(data?.items.map((item) => item.user.id))];
        const { data: userItems } = await this.#userItemRepository.requestItems(uniqueUserIds);
        data?.items.forEach((item) => {
            if (item.isCurrentDraftVersion)
                return;
            tempItems.push({
                date: item.versionDate,
                user: userItems?.find((user) => user.unique === item.user.id)?.name || this.localize.term('general_unknownUser'),
                isCurrentlyPublishedVersion: item.isCurrentPublishedVersion,
                id: item.id,
                preventCleanup: item.preventCleanup,
            });
        });
        this._versions = tempItems;
        const id = tempItems.find((item) => item.isCurrentlyPublishedVersion)?.id;
        if (id) {
            this.#selectVersion(id);
        }
    }
    async #selectVersion(id) {
        const version = this._versions.find((item) => item.id === id);
        if (!version) {
            this._selectedVersion = undefined;
            this._diffs = [];
            return;
        }
        if (!this.#rollbackRepository) {
            throw new Error('Rollback repository is not set');
        }
        const { data } = await this.#rollbackRepository.requestVersionById(id);
        if (!data) {
            this._selectedVersion = undefined;
            this._diffs = [];
            return;
        }
        this._selectedVersion = {
            date: version.date,
            user: version.user,
            name: data.variants.find((x) => x.culture === this._selectedCulture)?.name || data.variants[0].name,
            id: data.id,
            properties: data.values
                .filter((x) => x.culture === this._selectedCulture || !x.culture) // When invariant, culture is undefined or null.
                .map((value) => {
                return {
                    alias: value.alias,
                    value: value.value,
                };
            }),
        };
        if (this._showDiff) {
            await this.#setDiffs();
        }
    }
    async #onRollback() {
        if (!this._selectedVersion)
            return;
        if (!this.#rollbackRepository) {
            throw new Error('Rollback repository is not set');
        }
        const id = this._selectedVersion.id;
        const culture = this._selectedCulture ?? undefined;
        const { error } = await this.#rollbackRepository.rollback(id, culture);
        if (error)
            return;
        const unique = this.#currentDocument?.unique;
        const entityType = this.#currentDocument?.entityType;
        if (!unique || !entityType) {
            throw new Error('Entity unique or entity type is not set');
        }
        const actionEventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT);
        if (!actionEventContext) {
            throw new Error('Action event context not found');
        }
        const reloadStructureEvent = new UmbRequestReloadStructureForEntityEvent({ unique, entityType });
        actionEventContext.dispatchEvent(reloadStructureEvent);
        const entityUpdatedEvent = new UmbEntityUpdatedEvent({ unique, entityType });
        actionEventContext.dispatchEvent(entityUpdatedEvent);
        this.value = {};
        this.modalContext?.submit();
    }
    #onCancel() {
        this.modalContext?.reject();
    }
    #onVersionClicked(id) {
        this.#selectVersion(id);
    }
    async #onPreventCleanup(event, id, preventCleanup) {
        event.preventDefault();
        event.stopImmediatePropagation();
        if (!this.#rollbackRepository) {
            throw new Error('Rollback repository is not set');
        }
        await this.#rollbackRepository.setPreventCleanup(id, preventCleanup);
        const version = this._versions.find((item) => item.id === id);
        if (!version)
            return;
        version.preventCleanup = preventCleanup;
        this.requestUpdate('_versions');
    }
    #onChangeCulture(event) {
        const value = event.target.value;
        this._selectedCulture = value.toString();
        this.#requestVersions();
    }
    #onToggleDiff(event) {
        const checkbox = event.target;
        this._showDiff = checkbox.checked;
        // If we have toggled on and have a selected version, immediately show the diff.
        if (this._showDiff && this._selectedVersion) {
            this.#setDiffs();
        }
    }
    #trimQuotes(str) {
        return str.replace(/^['"]|['"]$/g, '');
    }
    #getPlainValue(alias) {
        if (alias === 'name') {
            return this._selectedVersion?.name ?? '';
        }
        const prop = this._selectedVersion?.properties.find((x) => x.alias === alias);
        return prop ? this.#trimQuotes(JSON.stringify(prop.value)) : '';
    }
    #renderCultureSelect() {
        return html `
			<uui-select
				id="language-select"
				@change=${this.#onChangeCulture}
				.options=${this._availableVariants}></uui-select>
		`;
    }
    #renderVersions() {
        if (!this._versions.length) {
            return html `<uui-box headline=${this.localize.term('rollback_versions')}>No versions available</uui-box>`;
        }
        return html ` <uui-box id="versions-box" headline=${this.localize.term('rollback_versions')}>
			${repeat(this._versions, (item) => item.id, (item) => {
            return html `
						<div
							@click=${() => this.#onVersionClicked(item.id)}
							@keydown=${() => { }}
							class="rollback-item ${this._selectedVersion?.id === item.id ? 'active' : ''}">
							<div>
								<p class="rollback-item-date">
									<umb-localize-date date="${item.date}" .options=${this.#localizeDateOptions}></umb-localize-date>
								</p>
								<p>${item.user}</p>
								<p>${item.isCurrentlyPublishedVersion ? this.localize.term('rollback_currentPublishedVersion') : ''}</p>
							</div>
							<uui-button
								look="secondary"
								@click=${(event) => this.#onPreventCleanup(event, item.id, !item.preventCleanup)}
								label=${item.preventCleanup
                ? this.localize.term('contentTypeEditor_historyCleanupEnableCleanup')
                : this.localize.term('contentTypeEditor_historyCleanupPreventCleanup')}></uui-button>
						</div>
					`;
        })}</uui-box
		>`;
    }
    async #setDiffs() {
        if (!this._selectedVersion)
            return;
        const currentPropertyValues = this.#currentDocument?.values.filter((x) => x.culture === this._selectedCulture || !x.culture); // When invariant, culture is undefined or null.
        if (!currentPropertyValues) {
            throw new Error('Current property values are not set');
        }
        const currentName = this.#currentDocument?.variants.find((x) => x.culture === this._selectedCulture)?.name;
        if (!currentName) {
            throw new Error('Current name is not set');
        }
        const diffs = [];
        const nameDiff = diffWords(currentName, this._selectedVersion.name);
        diffs.push({ alias: 'name', diff: nameDiff });
        this._selectedVersion.properties.forEach((item) => {
            const draftValue = currentPropertyValues.find((x) => x.alias === item.alias);
            if (!draftValue)
                return;
            const draftValueString = this.#trimQuotes(JSON.stringify(draftValue.value));
            const versionValueString = this.#trimQuotes(JSON.stringify(item.value));
            const diff = diffWords(draftValueString, versionValueString);
            diffs.push({ alias: item.alias, diff });
        });
        this._diffs = [...diffs];
    }
    #renderSelectedVersion() {
        if (!this._selectedVersion)
            return html `
				<uui-box id="box-right" style="display: flex; align-items: center; justify-content: center;"
					>No selected version</uui-box
				>
			`;
        // Build list of property aliases to display (name + all properties)
        const propertyAliases = ['name', ...this._selectedVersion.properties.map((p) => p.alias)];
        return html `
			<uui-box headline=${this.currentVersionHeader} id="box-right">
				<uui-toggle
					label=${this.localize.term('rollback_showDiff')}
					@change=${this.#onToggleDiff}
					.checked=${this._showDiff}></uui-toggle>
				${this._showDiff ? html `<p>${unsafeHTML(this.localize.term('rollback_diffHelp'))}</p>` : nothing}
				<uui-table>
					<uui-table-column style="width: 0"></uui-table-column>
					<uui-table-column></uui-table-column>

					<uui-table-head>
						<uui-table-head-cell>${this.localize.term('general_alias')}</uui-table-head-cell>
						<uui-table-head-cell>${this.localize.term('general_value')}</uui-table-head-cell>
					</uui-table-head>
					${repeat(propertyAliases, (alias) => alias, (alias) => {
            const diff = this._diffs.find((x) => x?.alias === alias);
            return html `
								<uui-table-row>
									<uui-table-cell>${alias}</uui-table-cell>
									<uui-table-cell>
										${this._showDiff && diff
                ? diff.diff.map((part) => part.added
                    ? html `<span class="diff-added">${part.value}</span>`
                    : part.removed
                        ? html `<span class="diff-removed">${part.value}</span>`
                        : part.value)
                : this.#getPlainValue(alias)}
									</uui-table-cell>
								</uui-table-row>
							`;
        })}
				</uui-table>
			</uui-box>
		`;
    }
    get currentVersionHeader() {
        return (this.localize.date(this._selectedVersion?.date ?? new Date(), this.#localizeDateOptions) +
            ' - ' +
            this._selectedVersion?.user);
    }
    render() {
        return html `
			<umb-body-layout headline="Rollback">
				<div id="main">
					<div id="box-left">
						${this._availableVariants.length
            ? html `
									<uui-box id="language-box" headline=${this.localize.term('general_language')}>
										${this.#renderCultureSelect()}
									</uui-box>
								`
            : nothing}
						${this.#renderVersions()}
					</div>
					${this.#renderSelectedVersion()}
				</div>
				<umb-footer-layout slot="footer">
					<uui-button
						slot="actions"
						look="secondary"
						@click=${this.#onCancel}
						label=${this.localize.term('general_cancel')}></uui-button>
					<uui-button
						slot="actions"
						look="primary"
						@click=${this.#onRollback}
						label=${this.localize.term('actions_rollback')}
						?disabled=${!this._selectedVersion}></uui-button>
				</umb-footer-layout>
			</umb-body-layout>
		`;
    }
    static { this.styles = [
        UmbTextStyles,
        css `
			:host {
				color: var(--uui-color-text);
			}

			#language-box {
				margin-bottom: var(--uui-size-space-2);
			}

			#language-select {
				width: 100%;
			}

			uui-table {
				--uui-table-cell-padding: var(--uui-size-space-1) var(--uui-size-space-4);
				margin-top: var(--uui-size-space-5);
			}
			uui-table-head-cell:first-child {
				border-top-left-radius: var(--uui-border-radius);
			}
			uui-table-head-cell:last-child {
				border-top-right-radius: var(--uui-border-radius);
			}
			uui-table-head-cell {
				background-color: var(--uui-color-surface-alt);
			}
			uui-table-head-cell:last-child,
			uui-table-cell:last-child {
				border-right: 1px solid var(--uui-color-border);
			}
			uui-table-head-cell,
			uui-table-cell {
				border-top: 1px solid var(--uui-color-border);
				border-left: 1px solid var(--uui-color-border);
			}
			uui-table-row:last-child uui-table-cell {
				border-bottom: 1px solid var(--uui-color-border);
			}
			uui-table-row:last-child uui-table-cell:last-child {
				border-bottom-right-radius: var(--uui-border-radius);
			}
			uui-table-row:last-child uui-table-cell:first-child {
				border-bottom-left-radius: var(--uui-border-radius);
			}

			.diff-added,
			ins {
				background-color: #00c43e63;
			}
			.diff-removed,
			del {
				background-color: #ff35356a;
			}
			.rollback-item {
				position: relative;
				display: flex;
				justify-content: space-between;
				align-items: center;
				padding: var(--uui-size-space-5);
				cursor: pointer;
			}
			.rollback-item::after {
				content: '';
				position: absolute;
				inset: 2px;
				display: block;
				border: 2px solid transparent;
				pointer-events: none;
			}
			.rollback-item.active::after,
			.rollback-item:hover::after {
				border-color: var(--uui-color-selected);
			}
			.rollback-item:not(.active):hover::after {
				opacity: 0.5;
			}
			.rollback-item p {
				margin: 0;
				opacity: 0.5;
			}
			p.rollback-item-date {
				opacity: 1;
			}
			.rollback-item uui-button {
				white-space: nowrap;
			}

			#main {
				display: flex;
				gap: var(--uui-size-space-5);
				width: 100%;
				height: 100%;
			}

			#versions-box {
				--uui-box-default-padding: 0;
			}

			#box-left {
				max-width: 500px;
				flex: 1;
				overflow: auto;
				height: 100%;
			}

			#box-right {
				flex: 1;
				overflow: auto;
				height: 100%;
			}
		`,
    ]; }
};
__decorate([
    state()
], UmbContentRollbackModalElement.prototype, "_versions", void 0);
__decorate([
    state()
], UmbContentRollbackModalElement.prototype, "_selectedVersion", void 0);
__decorate([
    state()
], UmbContentRollbackModalElement.prototype, "_selectedCulture", void 0);
__decorate([
    state()
], UmbContentRollbackModalElement.prototype, "_isInvariant", void 0);
__decorate([
    state()
], UmbContentRollbackModalElement.prototype, "_availableVariants", void 0);
__decorate([
    state()
], UmbContentRollbackModalElement.prototype, "_diffs", void 0);
__decorate([
    state()
], UmbContentRollbackModalElement.prototype, "_showDiff", void 0);
UmbContentRollbackModalElement = __decorate([
    customElement('umb-content-rollback-modal')
], UmbContentRollbackModalElement);
export { UmbContentRollbackModalElement };
export default UmbContentRollbackModalElement;
