import { Component, HostListener, Input, OnDestroy } from '@angular/core';
import { Dossier, File, FileAttributeConfigTypes, IFileAttributeConfig } from '@red/domain';
import { BaseFormComponent, HelpModeService, ListingService, Toaster } from '@iqser/common-ui';
import { PermissionsService } from '@services/permissions.service';
import { FormBuilder, UntypedFormGroup } from '@angular/forms';
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
import { firstValueFrom, Subscription } from 'rxjs';
import { FilesService } from '@services/files/files.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import dayjs from 'dayjs';
import { NavigationEnd, Router } from '@angular/router';
import { filter, map, tap } from 'rxjs/operators';
import { ConfigService } from '../../config.service';

@Component({
    selector: 'redaction-file-attribute [fileAttribute] [file] [dossier]',
    templateUrl: './file-attribute.component.html',
    styleUrls: ['./file-attribute.component.scss'],
})
export class FileAttributeComponent extends BaseFormComponent implements OnDestroy {
    @Input() fileAttribute!: IFileAttributeConfig;
    @Input() file!: File;
    @Input() dossier!: Dossier;

    isInEditMode = false;
    closedDatepicker = true;
    readonly #subscriptions = new Subscription();

    constructor(
        router: Router,
        private readonly _toaster: Toaster,
        private readonly _formBuilder: FormBuilder,
        private readonly _filesService: FilesService,
        readonly permissionsService: PermissionsService,
        private readonly _listingService: ListingService<File>,
        readonly fileAttributesService: FileAttributesService,
        readonly helpModeService: HelpModeService,
        readonly configService: ConfigService,
    ) {
        super();
        const sub = router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => this.close());
        this.#subscriptions.add(sub);

        const sub2 = this._listingService.selectedLength$.pipe(
            map(selectedLength => !!selectedLength),
            tap(() => this.close()),
        );
        this.#subscriptions.add(sub2.subscribe());
    }

    get isDate(): boolean {
        return this.fileAttribute.type === FileAttributeConfigTypes.DATE;
    }

    get fileAttributeValue(): string {
        return this.file.fileAttributes.attributeIdToValue[this.fileAttribute.id];
    }

    ngOnDestroy() {
        this.#subscriptions.unsubscribe();
    }

    async editFileAttribute($event: MouseEvent): Promise<void> {
        if (!this.file.isInitialProcessing && this.permissionsService.canEditFileAttributes(this.file, this.dossier)) {
            $event.stopPropagation();
            this.#toggleEdit();
        }
    }

    async save() {
        const rawFormValue = this.form.getRawValue();
        const fileAttrValue = rawFormValue[this.fileAttribute.id];
        const attributeIdToValue = {
            ...this.#getForm().getRawValue(),
            [this.fileAttribute.id]: this.#formatAttributeValue(fileAttrValue),
        };
        try {
            await firstValueFrom(
                this.fileAttributesService.setFileAttributes({ attributeIdToValue }, this.file.dossierId, this.file.fileId),
            );
            await this._filesService.reload(this.file.dossierId, this.file);
            this.initialFormValue = rawFormValue;
            this._toaster.success(_('file-attribute.update.success'));
        } catch (e) {
            this._toaster.error(_('file-attribute.update.error'));
        }

        this.#toggleEdit();
    }

    close(): void {
        if (this.isInEditMode) {
            this.form = this.#getForm();
            this.#toggleEdit();
        }
    }

    @HostListener('document:click')
    clickOutside() {
        if (this.isInEditMode && this.closedDatepicker) {
            this.close();
        }
    }

    #initFileAttributes() {
        const configs = this.fileAttributesService.getFileAttributeConfig(this.file.dossierTemplateId).fileAttributeConfigs;
        configs.forEach(config => {
            if (!this.file.fileAttributes.attributeIdToValue[config.id]) {
                this.file.fileAttributes.attributeIdToValue[config.id] = null;
            }
        });
    }

    #getForm(): UntypedFormGroup {
        const config = {};
        const fileAttributes = this.file.fileAttributes.attributeIdToValue;
        Object.keys(fileAttributes).forEach(key => {
            const attrValue = fileAttributes[key];
            config[key] = [dayjs(attrValue, 'YYYY-MM-DD', true).isValid() ? dayjs(attrValue).toDate() : attrValue];
        });
        return this._formBuilder.group(config);
    }

    #formatAttributeValue(attrValue) {
        return this.isDate ? attrValue && dayjs(attrValue).format('YYYY-MM-DD') : attrValue;
    }

    #toggleEdit(): void {
        if (!this.isInEditMode) {
            this.#initFileAttributes();
            this.form = this.#getForm();
            this.initialFormValue = this.form.getRawValue();
        }

        this.isInEditMode = !this.isInEditMode;
        this.fileAttributesService.isEditingFileAttribute$.next(this.isInEditMode);

        if (this.isInEditMode) {
            this.#focusOnEditInput();
        }
    }

    #focusOnEditInput(): void {
        setTimeout(() => {
            const input = document.getElementById(this.fileAttribute.id);
            input?.focus();
        }, 100);
    }
}
