import { Component, OnInit, signal, untracked, WritableSignal } from '@angular/core';
import {
    BaseFormComponent,
    getConfig,
    HasScrollbarDirective,
    IconButtonComponent,
    IconButtonTypes,
    LoadingService,
    Toaster,
} from '@iqser/common-ui';
import { getParam } from '@iqser/common-ui/lib/utils';
import { DOSSIER_TEMPLATE_ID, type DossierTemplate, IDossierTemplate } from '@red/domain';
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
import { dossierTemplateStatusTranslations } from '@translations/dossier-template-status-translations';
import dayjs, { Dayjs } from 'dayjs';
import { HttpStatusCode } from '@angular/common/http';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { applyIntervalConstraints } from '@utils/date-inputs-utils';
import { AbstractControl, ReactiveFormsModule, UntypedFormBuilder, Validators } from '@angular/forms';
import { downloadTypesTranslations } from '@translations/download-types-translations';
import { Observable } from 'rxjs';
import { DossierTemplateDetailsComponent } from '../dossier-template-details/dossier-template-details.component';
import { TranslateModule } from '@ngx-translate/core';
import { MatCheckbox } from '@angular/material/checkbox';
import { NgIf } from '@angular/common';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatIcon } from '@angular/material/icon';
import { SelectComponent } from '@shared/components/select/select.component';

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

@Component({
    templateUrl: './dossier-template-info-screen.component.html',
    styleUrls: ['./dossier-template-info-screen.component.scss'],
    standalone: true,
    imports: [
        HasScrollbarDirective,
        ReactiveFormsModule,
        DossierTemplateDetailsComponent,
        TranslateModule,
        MatCheckbox,
        NgIf,
        MatDatepickerModule,
        SelectComponent,
        IconButtonComponent,
        MatIcon,
    ],
})
export default class DossierTemplateInfoScreenComponent extends BaseFormComponent implements OnInit {
    readonly translations = dossierTemplateStatusTranslations;
    readonly iconButtonTypes = IconButtonTypes;
    readonly isDocumine = getConfig().IS_DOCUMINE;
    readonly downloadTypes = downloadTypes;

    readonly dossierTemplate$: Observable<DossierTemplate>;
    readonly dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
    readonly hasValidFrom: WritableSignal<boolean>;
    readonly hasValidTo: WritableSignal<boolean>;
    #previousValidFrom: Dayjs;
    #previousValidTo: Dayjs;
    #lastValidFrom: Dayjs;
    #lastValidTo: Dayjs;

    get disabled(): boolean {
        return !this.valid || !this.changed;
    }

    constructor(
        private readonly _dossierTemplatesService: DossierTemplatesService,
        private readonly _loadingService: LoadingService,
        private readonly _toaster: Toaster,
        private readonly _formBuilder: UntypedFormBuilder,
    ) {
        super();
        this.dossierTemplate$ = this._dossierTemplatesService.get(this.dossierTemplateId);
        this.form = this.#getForm(this._dossierTemplatesService.find(this.dossierTemplateId));
        this.initialFormValue = this.form.getRawValue();

        this.hasValidFrom = signal(!!this.form.get('validFrom').value);
        this.hasValidTo = signal(!!this.form.get('validTo').value);

        this.#previousValidFrom = this.#lastValidFrom = this.form.get('validFrom').value;
        this.#previousValidTo = this.#lastValidTo = this.form.get('validTo').value;
    }

    ngOnInit() {
        this._loadingService.stop();
    }

    toggleHasValid(extremity: 'from' | 'to') {
        if (extremity === 'from') {
            const prevValue = untracked(this.hasValidFrom);
            this.hasValidFrom.set(!prevValue);
            this.form.controls['validFrom'].setValue(!prevValue ? this.#lastValidFrom : null);
        } else {
            const prevValue = untracked(this.hasValidTo);
            this.hasValidTo.set(!prevValue);
            this.form.controls['validTo'].setValue(!prevValue ? this.#lastValidTo : null);
        }
        this.applyValidityIntervalConstraints();
    }

    async save() {
        this._loadingService.start();
        const dossierTemplate = {
            dossierTemplateId: this.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 {
            await this._dossierTemplatesService.createOrUpdate(dossierTemplate);
            this.initialFormValue = this.form.getRawValue();
        } 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(dossierTemplate: DossierTemplate) {
        return this._formBuilder.group({
            name: [dossierTemplate.name, Validators.required],
            description: [dossierTemplate?.description],
            validFrom: [
                dossierTemplate?.validFrom ? dayjs(dossierTemplate?.validFrom) : null,
                this.#requiredIfValidator(() => this.hasValidFrom()),
            ],
            validTo: [
                dossierTemplate?.validTo ? dayjs(dossierTemplate?.validTo) : null,
                this.#requiredIfValidator(() => this.hasValidTo()),
            ],
            applyDictionaryUpdatesToAllDossiersByDefault: [dossierTemplate?.applyDictionaryUpdatesToAllDossiersByDefault],
            ocrByDefault: [dossierTemplate?.ocrByDefault],
            removeWatermark: [dossierTemplate?.removeWatermark],
            downloadFileTypes: [dossierTemplate?.downloadFileTypes || ['PREVIEW', 'REDACTED']],
            keepHiddenText: [dossierTemplate?.keepHiddenText],
            keepImageMetadata: [dossierTemplate?.keepImageMetadata],
            keepOverlappingObjects: [dossierTemplate?.keepOverlappingObjects],
        });
    }

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