import { Component, Input, OnInit, signal, ViewChildren } from '@angular/core';
import { List } from '@common-ui/utils';
import { IconButtonTypes, LoadingService } from '@iqser/common-ui';
import { ComponentLogEntry, Dictionary, File, IComponentLogEntry, WorkflowFileStatuses } from '@red/domain';
import { ComponentLogService } from '@services/files/component-log.service';
import { UserPreferenceService } from '@users/user-preference.service';
import { combineLatest, firstValueFrom, Observable } from 'rxjs';
import { EditableStructuredComponentValueComponent } from '../editable-structured-component-value/editable-structured-component-value.component';
import { FilterService, PopupFilterComponent } from '@common-ui/filtering';
import { ComponentLogFilterService } from '../../services/component-log-filter.service';
import { map } from 'rxjs/operators';
import { toObservable } from '@angular/core/rxjs-interop';
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';

@Component({
    selector: 'redaction-structured-component-management',
    templateUrl: './structured-component-management.component.html',
    styleUrls: ['./structured-component-management.component.scss'],
    standalone: true,
    imports: [PopupFilterComponent, NgIf, AsyncPipe, TranslateModule, NgForOf, EditableStructuredComponentValueComponent],
})
export class StructuredComponentManagementComponent implements OnInit {
    protected readonly componentLogData = signal<ComponentLogEntry[] | undefined>(undefined);
    protected readonly componentLogData$ = toObservable(this.componentLogData);
    protected readonly openScmDialogByDefault = signal(this.userPreferences.getOpenScmDialogByDefault());
    protected readonly iconButtonTypes = IconButtonTypes;
    protected displayedComponents$: Observable<ComponentLogEntry[]>;
    @Input() file: File;
    @Input() dictionaries: Dictionary[];
    @ViewChildren('editableComponent') editableComponents: List<EditableStructuredComponentValueComponent>;

    constructor(
        private readonly _componentLogService: ComponentLogService,
        private readonly _loadingService: LoadingService,
        private readonly _componentLogFilterService: ComponentLogFilterService,
        private readonly _filterService: FilterService,
        readonly userPreferences: UserPreferenceService,
    ) {}

    get canEdit() {
        return this.file.workflowStatus !== WorkflowFileStatuses.APPROVED;
    }

    async ngOnInit(): Promise<void> {
        await this.#loadData();
        this.displayedComponents$ = this.#displayedComponents$();
    }

    deselectLast() {
        const lastSelected = this.editableComponents.find(c => c.selected);
        if (lastSelected) {
            lastSelected.deselect();
        }
    }

    async toggleOpenScmDialogByDefault() {
        await this.userPreferences.toggleOpenScmDialogByDefault();
        await this.userPreferences.reload();
        this.openScmDialogByDefault.set(this.userPreferences.getOpenScmDialogByDefault());
    }

    async revertOverride(originalKey: string) {
        this._loadingService.start();
        await firstValueFrom(
            this._componentLogService.revertOverride(this.file.dossierTemplateId, this.file.dossierId, this.file.fileId, [originalKey]),
        );
        await this.#loadData();
    }

    async overrideValue(componentLogEntry: IComponentLogEntry) {
        this._loadingService.start();
        await firstValueFrom(
            this._componentLogService.override(this.file.dossierTemplateId, this.file.dossierId, this.file.fileId, componentLogEntry),
        );
        await this.#loadData();
    }

    #displayedComponents$() {
        const componentLogFilters$ = this._filterService.getFilterModels$('componentLogFilters');
        return combineLatest([this.componentLogData$, componentLogFilters$]).pipe(
            map(([components, filters]) => this._componentLogFilterService.filterComponents(components, filters)),
        );
    }

    async #loadData(): Promise<void> {
        this._loadingService.start();
        const componentLogData = await firstValueFrom(
            this._componentLogService.getComponentLogData(
                this.file.dossierTemplateId,
                this.file.dossierId,
                this.file.fileId,
                this.dictionaries,
            ),
        );
        this.#computeFilters(componentLogData);
        this.componentLogData.set(componentLogData);
        this._loadingService.stop();
    }

    #computeFilters(componentLogs: ComponentLogEntry[]) {
        const filterGroups = this._componentLogFilterService.filterGroups(componentLogs);
        this._filterService.addFilterGroups(filterGroups);
    }
}
