import { HttpStatusCode } from '@angular/common/http';
import { Component, Inject } from '@angular/core';
import { AbstractControl, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { BaseDialogComponent, getConfig } from '@iqser/common-ui';
import { DossierTemplate, IDossierTemplate } from '@red/domain';
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
import { downloadTypesTranslations } from '@translations/download-types-translations';
import { applyIntervalConstraints } from '@utils/date-inputs-utils';
import dayjs, { Dayjs } from 'dayjs';

interface EditCloneTemplateData {
    dossierTemplateId: string;
    clone?: boolean;
}

const downloadTypes = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(type => ({
    key: type,
    label: downloadTypesTranslations[type],
}));

@Component({
    templateUrl: './add-edit-clone-dossier-template-dialog.component.html',
    styleUrls: ['./add-edit-clone-dossier-template-dialog.component.scss'],
})
export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogComponent {
    readonly isDocumine = getConfig().IS_DOCUMINE;
    hasValidFrom: boolean;
    hasValidTo: boolean;
    readonly downloadTypes = downloadTypes;
    readonly dossierTemplate: DossierTemplate;
    private _previousValidFrom: Dayjs;
    private _previousValidTo: Dayjs;
    private _lastValidFrom: Dayjs;
    private _lastValidTo: Dayjs;

    get disabled(): boolean {
        if (!this.data?.clone) {
            return super.disabled;
        }
        return !this.valid;
    }

    get translateParams() {
        return {
            type: this.dossierTemplate ? (this.data.clone ? 'clone' : 'edit') : 'create',
            name: this.dossierTemplate?.name,
        };
    }

    constructor(
        private readonly _dossierTemplatesService: DossierTemplatesService,
        protected readonly _dialogRef: MatDialogRef<AddEditCloneDossierTemplateDialogComponent>,
        @Inject(MAT_DIALOG_DATA) readonly data: EditCloneTemplateData,
    ) {
        super(_dialogRef, !!data && !data.clone);
        this.dossierTemplate = this._dossierTemplatesService.find(this.data?.dossierTemplateId);
        this.form = this.#getForm();
        this.initialFormValue = this.form.getRawValue();
        this.hasValidFrom = !!this.dossierTemplate?.validFrom;
        this.hasValidTo = !!this.dossierTemplate?.validTo;

        this._previousValidFrom = this._lastValidFrom = this.form.get('validFrom').value;
        this._previousValidTo = this._lastValidTo = this.form.get('validTo').value;
    }

    toggleHasValid(extremity: string) {
        if (extremity === 'from') {
            this.hasValidFrom = !this.hasValidFrom;
            this.form.controls['validFrom'].setValue(this.hasValidFrom ? this._lastValidFrom : null);
        } else {
            this.hasValidTo = !this.hasValidTo;
            this.form.controls['validTo'].setValue(this.hasValidTo ? this._lastValidTo : null);
        }
        this.applyValidityIntervalConstraints();
    }

    async save() {
        this._loadingService.start();
        const dossierTemplate = {
            dossierTemplateId: this.dossierTemplate?.dossierTemplateId,
            ...this.form.getRawValue(),
            validFrom: this.hasValidFrom ? this.form.get('validFrom').value : null,
            validTo: this.hasValidTo ? this.form.get('validTo').value : null,
        } as IDossierTemplate;

        try {
            if (this.data?.clone) {
                await this._dossierTemplatesService.clone(this.dossierTemplate.id, dossierTemplate);
            } else {
                await this._dossierTemplatesService.createOrUpdate(dossierTemplate);
            }
            this._dialogRef.close(true);
        } catch (error) {
            if (error.status === HttpStatusCode.Conflict) {
                this._toaster.error(_('add-edit-clone-dossier-template.error.conflict'), { error });
            } else {
                this._toaster.rawError(error.error.message);
            }
        }
        this._loadingService.stop();
    }

    applyValidityIntervalConstraints(): void {
        const formValue = this.form.value;
        applyIntervalConstraints(formValue, this._previousValidFrom, this._previousValidTo, this.form, 'validFrom', 'validTo');

        this._previousValidFrom = this.form.get('validFrom').value;
        this._previousValidTo = this.form.get('validTo').value;
        this._lastValidFrom = this._previousValidFrom || this._lastValidFrom;
        this._lastValidTo = this._previousValidTo || this._lastValidTo;
    }

    #getForm() {
        return this._formBuilder.group({
            name: [this.#getCloneName(), Validators.required],
            description: [this.dossierTemplate?.description],
            validFrom: [
                this.dossierTemplate?.validFrom ? dayjs(this.dossierTemplate?.validFrom) : null,
                this.#requiredIfValidator(() => this.hasValidFrom),
            ],
            validTo: [
                this.dossierTemplate?.validTo ? dayjs(this.dossierTemplate?.validTo) : null,
                this.#requiredIfValidator(() => this.hasValidTo),
            ],
            applyDictionaryUpdatesToAllDossiersByDefault: [this.dossierTemplate?.applyDictionaryUpdatesToAllDossiersByDefault],
            ocrByDefault: [this.dossierTemplate?.ocrByDefault],
            removeWatermark: [this.dossierTemplate?.removeWatermark],
            downloadFileTypes: [this.dossierTemplate?.downloadFileTypes || ['PREVIEW', 'REDACTED']],
            keepHiddenText: [this.dossierTemplate?.keepHiddenText],
            keepImageMetadata: [this.dossierTemplate?.keepImageMetadata],
            keepOverlappingObjects: [this.dossierTemplate?.keepOverlappingObjects],
        });
    }

    #getCloneName(): string {
        if (!this.data?.clone) {
            return this.dossierTemplate?.name;
        }

        const templateName = this.dossierTemplate.name.trim();
        let nameOfClonedTemplate: string = templateName.split('Copy of ').filter(n => n)[0];
        nameOfClonedTemplate = nameOfClonedTemplate.split(/\(\s*\d+\s*\)$/)[0].trim();
        const allTemplatesNames = this._dossierTemplatesService.all.map(t => t.name);

        let clonesCount = 0;
        for (const name of allTemplatesNames) {
            const splitName = name.split(nameOfClonedTemplate);
            const suffixRegExp = new RegExp(/^\(\s*\d+\s*\)$/);
            if (splitName[0] === 'Copy of ' && (splitName[1].trim().match(suffixRegExp) || splitName[1] === '')) {
                clonesCount++;
            }
        }

        if (clonesCount >= 1) {
            return `Copy of ${nameOfClonedTemplate} (${clonesCount})`;
        }
        return `Copy of ${nameOfClonedTemplate}`;
    }

    #requiredIfValidator(predicate) {
        return (formControl: AbstractControl) => {
            if (!formControl.parent) {
                return null;
            }
            if (predicate()) {
                return Validators.required(formControl);
            }
            return null;
        };
    }
}
