import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Dossier, DOSSIER_TEMPLATE_ID, IDossierRequest, IDossierTemplate } from '@red/domain';
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
import { PermissionsService } from '@services/permissions.service';
import { Router } from '@angular/router';
import { MatDialogRef } from '@angular/material/dialog';
import { EditDossierDialogComponent } from '../edit-dossier-dialog.component';
import { ConfirmOptions, IconButtonTypes, IConfirmationDialogData, LoadingService, TitleColors, Toaster } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
import { firstValueFrom } from 'rxjs';
import { TranslateService } from '@ngx-translate/core';
import { DossiersService } from '@services/dossiers/dossiers.service';
import { TrashService } from '@services/entity-services/trash.service';
import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.service';
import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service';
import dayjs from 'dayjs';
import { dateWithoutTime } from '@utils/functions';
import { TenantsService } from '@iqser/common-ui/lib/tenants';

@Component({
    selector: 'redaction-edit-dossier-general-info',
    templateUrl: './edit-dossier-general-info.component.html',
    styleUrls: ['./edit-dossier-general-info.component.scss'],
    changeDetection: ChangeDetectionStrategy.OnPush,
})
export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSectionInterface {
    @Input() dossier: Dossier;

    readonly iconButtonTypes = IconButtonTypes;

    form: UntypedFormGroup;
    statusPlaceholder: string;
    hasDueDate: boolean;
    dossierTemplates: IDossierTemplate[];
    states: string[];

    get changed(): boolean {
        for (const key of Object.keys(this.form.getRawValue())) {
            if (key === 'dueDate') {
                if (this.hasDueDate !== !!this.dossier.dueDate) {
                    return true;
                }
                if (this.hasDueDate && !dayjs(this.dossier.dueDate).isSame(dayjs(this.form.get(key).value), 'day')) {
                    return true;
                }
            } else if (this.dossier[key] !== this.form.get(key).value) {
                return true;
            }
        }

        return false;
    }

    get valid(): boolean {
        return this.form.valid;
    }

    get disabled(): boolean {
        return this.hasDueDate && this.form.get('dueDate').value === null;
    }

    get #statusPlaceholder(): string {
        return this._translateService.instant(
            this.states.length === 1
                ? 'edit-dossier-dialog.general-info.form.dossier-state.no-state-placeholder'
                : 'dossier-state.placeholder',
        ) as string;
    }

    constructor(
        readonly permissionsService: PermissionsService,
        private readonly _dossierStatesMapService: DossierStatesMapService,
        private readonly _dossierTemplatesService: DossierTemplatesService,
        private readonly _dossiersService: DossiersService,
        private readonly _trashService: TrashService,
        private readonly _dossierStatsService: DossierStatsService,
        private readonly _formBuilder: UntypedFormBuilder,
        private readonly _dialogService: DossiersDialogService,
        private readonly _router: Router,
        private readonly _tenantsService: TenantsService,
        private readonly _editDossierDialogRef: MatDialogRef<EditDossierDialogComponent>,
        private readonly _toaster: Toaster,
        private readonly _loadingService: LoadingService,
        private readonly _translateService: TranslateService,
        private readonly _archivedDossiersService: ArchivedDossiersService,
    ) {}

    ngOnInit() {
        this.states = [null, ...this._dossierStatesMapService.get(this.dossier.dossierTemplateId).map(s => s.id)];
        this.statusPlaceholder = this.#statusPlaceholder;
        this.#filterInvalidDossierTemplates();
        this.form = this.#getForm();
        if (!this.permissionsService.canEditDossier(this.dossier)) {
            this.form.disable();
        }
        this.hasDueDate = !!this.dossier.dueDate;
    }

    revert() {
        this.form.reset({
            dossierName: this.dossier.dossierName,
            dossierTemplateId: this.dossier.dossierTemplateId,
            dossierStatusId: this.dossier.dossierStatusId,
            description: this.dossier.description,
            dueDate: this.dossier.dueDate,
        });
    }

    async save(): EditDossierSaveResult {
        let dueDate;
        if (this.hasDueDate) {
            dueDate = dateWithoutTime(dayjs(this.form.get('dueDate').value));
        }
        const dossier = {
            ...this.dossier,
            dossierName: this.form.get('dossierName').value,
            description: this.form.get('description').value,
            dueDate: dueDate,
            dossierTemplateId: this.form.get(DOSSIER_TEMPLATE_ID).value,
            dossierStatusId: this.form.get('dossierStatusId').value,
        } as IDossierRequest;

        const updatedDossier = await firstValueFrom(this._dossiersService.createOrUpdate(dossier));
        if (updatedDossier && updatedDossier.dossierTemplateId !== this.dossier.dossierTemplateId) {
            await this._router.navigate([`/${this._tenantsService.activeTenantId}${updatedDossier.routerLink}`]);
        }
        return { success: !!updatedDossier };
    }

    deleteDossier() {
        const data: IConfirmationDialogData = {
            title: _('confirmation-dialog.delete-dossier.title'),
            titleColor: TitleColors.WARN,
            question: _('confirmation-dialog.delete-dossier.question'),
            confirmationText: _('confirmation-dialog.delete-dossier.confirmation-text'),
            requireInput: true,
            denyText: _('confirmation-dialog.delete-dossier.deny-text'),
            translateParams: {
                dossierName: this.dossier.dossierName,
                dossiersCount: 1,
            },
        };

        this._dialogService.openDialog('confirm', data, async () => {
            this._loadingService.start();
            const successful = await this._trashService.deleteDossier(this.dossier);
            if (successful) {
                await this.#closeDialogAndRedirectToDossier();
            }
            this._loadingService.stop();
        });
    }

    archiveDossier() {
        const data: IConfirmationDialogData = {
            title: _('confirm-archive-dossier.title'),
            details: _('confirm-archive-dossier.details'),
            question: _('confirm-archive-dossier.warning'),
            confirmationText: _('confirm-archive-dossier.archive'),
            denyText: _('confirm-archive-dossier.cancel'),
            titleColor: TitleColors.WARN,
            translateParams: { ...this.dossier },
            checkboxes: [{ value: false, label: _('confirm-archive-dossier.checkbox.documents') }],
            toastMessage: _('confirm-archive-dossier.toast-error'),
        };

        this._dialogService.openDialog('confirm', data, async result => {
            if (result === ConfirmOptions.CONFIRM) {
                this._loadingService.start();
                await firstValueFrom(this._archivedDossiersService.archive([this.dossier]));
                this._toaster.success(_('dossier-listing.archive.archive-succeeded'), {
                    params: {
                        dossierName: this.dossier.dossierName,
                    },
                });
                this._editDossierDialogRef.close();
                this._loadingService.stop();
            }
        });
    }

    getStateName(stateId: string): string {
        return (this._dossierStatesMapService.get(this.dossier.dossierTemplateId, stateId)?.name ||
            this._translateService.instant('dossier-state.placeholder')) as string;
    }

    getStateColor(stateId: string): string {
        return this._dossierStatesMapService.get(this.dossier.dossierTemplateId, stateId).color;
    }

    async #closeDialogAndRedirectToDossier() {
        this._editDossierDialogRef.close();
        await this._router.navigate([`/${this._tenantsService.activeTenantId}${this.dossier.dossiersListRouterLink}`]);
        this._toaster.success(_('edit-dossier-dialog.delete-successful'), {
            params: {
                dossierName: this.dossier.dossierName,
            },
        });
    }

    #getForm(): UntypedFormGroup {
        const formFieldWithArchivedCheck = value => ({ value, disabled: !this.dossier.isActive });
        return this._formBuilder.group({
            dossierName: [formFieldWithArchivedCheck(this.dossier.dossierName), Validators.required],
            dossierTemplateId: [
                {
                    value: this.dossier.dossierTemplateId,
                    disabled: this._dossierStatsService.get(this.dossier.id).hasFiles || !this.dossier.isActive,
                },
                Validators.required,
            ],
            dossierStatusId: [
                {
                    value: this.dossier.dossierStatusId,
                    disabled: this.states.length === 1 || !this.dossier.isActive,
                },
            ],
            description: [formFieldWithArchivedCheck(this.dossier.description)],
            dueDate: [formFieldWithArchivedCheck(this.dossier.dueDate)],
        });
    }

    #filterInvalidDossierTemplates() {
        this.dossierTemplates = this._dossierTemplatesService.all.filter(r => {
            if (this.dossier?.dossierTemplateId === r.dossierTemplateId) {
                return true;
            }
            const notYetValid = !!r.validFrom && dayjs(r.validFrom).isAfter(dayjs());
            const notValidAnymore = !!r.validTo && dayjs(r.validTo).add(1, 'd').isBefore(dayjs());
            return !(notYetValid || notValidAnymore) && r.isActive;
        });
    }
}
