import { Component, OnInit } from '@angular/core';
import { DetailsRadioOption, IconButtonTypes, IqserPermissionsService } from '@iqser/common-ui';
import { Dictionary, Dossier, File, IAddRedactionRequest, IManualRedactionEntry, SuperTypes } from '@red/domain';
import { FormBuilder, UntypedFormGroup } from '@angular/forms';
import { Roles } from '@users/roles';
import { firstValueFrom } from 'rxjs';
import { JustificationsService } from '@services/entity-services/justifications.service';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { LegalBasisOption } from '../manual-redaction-dialog/manual-annotation-dialog.component';
import { DictionaryService } from '@services/entity-services/dictionary.service';

import {
    ManualRedactionEntryType,
    ManualRedactionEntryTypes,
    ManualRedactionEntryWrapper,
} from '@models/file/manual-redaction-entry.wrapper';
import { redactTextTranslations } from '@translations/redact-text-translations';
import { RedactTextOption, RedactTextOptions } from './redact-text-options';
import { tap } from 'rxjs/operators';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { IqserDialogComponent } from '../../../../../../../../libs/common-ui/src/lib/dialog/iqser-dialog-component.directive';

const PIN_ICON = 'red:push-pin';
const FOLDER_ICON = 'red:folder';

interface RedactTextData {
    manualRedactionEntryWrapper: ManualRedactionEntryWrapper;
    dossierId: string;
    file: File;
    applyToAllDossiers: boolean;
}

interface DialogResult {
    redaction: IManualRedactionEntry;
    dictionary: Dictionary;
    applyToAllDossiers: boolean | null;
}

@Component({
    templateUrl: './redact-text-dialog.component.html',
    styleUrls: ['./redact-text-dialog.component.scss'],
})
export class RedactTextDialogComponent
    extends IqserDialogComponent<RedactTextDialogComponent, RedactTextData, DialogResult>
    implements OnInit
{
    readonly roles = Roles;
    readonly iconButtonTypes = IconButtonTypes;
    readonly options: DetailsRadioOption<RedactTextOption>[];
    readonly type: ManualRedactionEntryType;
    dictionaryRequest = false;
    legalOptions: LegalBasisOption[] = [];
    dictionaries: Dictionary[] = [];
    form!: UntypedFormGroup;

    #manualRedactionTypeExists = true;
    #applyToAllDossiers: boolean;

    readonly #translations = redactTextTranslations;
    readonly #dossier: Dossier;
    readonly #hint: boolean;

    constructor(
        private readonly _justificationsService: JustificationsService,
        private readonly _activeDossiersService: ActiveDossiersService,
        private readonly _dictionaryService: DictionaryService,
        private readonly _iqserPermissionsService: IqserPermissionsService,
        private readonly _formBuilder: FormBuilder,
    ) {
        super();
        this.#dossier = _activeDossiersService.find(this.data.dossierId);
        this.type = this.data.manualRedactionEntryWrapper.type;
        this.#hint = this.type === ManualRedactionEntryTypes.HINT;
        this.#applyToAllDossiers = this.data.applyToAllDossiers ?? true;
        this.#manualRedactionTypeExists = this._dictionaryService.hasManualType(this.#dossier.dossierTemplateId);
        this.options = this.#options();

        this.form = this.#getForm();

        this.form
            .get('option')
            .valueChanges.pipe(
                tap((option: DetailsRadioOption<RedactTextOption>) => {
                    this.dictionaryRequest = option.value === RedactTextOptions.IN_DOSSIER;
                    this.#resetValues();
                }),
                takeUntilDestroyed(),
            )
            .subscribe();
    }

    get displayedDictionaryLabel() {
        const dictType = this.form.get('dictionary').value;
        if (dictType) {
            return this.dictionaries.find(d => d.type === dictType)?.label ?? null;
        }
        return null;
    }

    get disabled() {
        if (this.dictionaryRequest || this.#hint) {
            return !this.form.get('dictionary').value;
        }
        return !this.form.get('reason').value;
    }

    async ngOnInit(): Promise<void> {
        this.dictionaries = this._dictionaryService.getPossibleDictionaries(this.#dossier.dossierTemplateId, this.#hint);

        const data = await firstValueFrom(this._justificationsService.getForDossierTemplate(this.#dossier.dossierTemplateId));
        this.legalOptions = data.map(lbm => ({
            legalBasis: lbm.reason,
            description: lbm.description,
            label: lbm.name,
        }));
        this.legalOptions.sort((a, b) => a.label.localeCompare(b.label));

        this.#selectReason();
        this.#formatSelectedTextValue();
    }

    extraOptionChanged(option: DetailsRadioOption<RedactTextOption>): void {
        this.#applyToAllDossiers = option.extraOption.checked;
    }

    save(): void {
        this.#enhanceManualRedaction(this.data.manualRedactionEntryWrapper.manualRedactionEntry);
        const redaction = this.data.manualRedactionEntryWrapper.manualRedactionEntry;
        this.dialogRef.close({
            redaction,
            dictionary: this.dictionaries.find(d => d.type === this.form.get('dictionary').value),
            applyToAllDossiers: this.dictionaryRequest ? this.#applyToAllDossiers : null,
        });
    }

    #getForm(): UntypedFormGroup {
        return this._formBuilder.group({
            selectedText: this.data?.manualRedactionEntryWrapper?.manualRedactionEntry?.value,
            reason: [null],
            comment: [null],
            dictionary: [this.#manualRedactionTypeExists ? SuperTypes.ManualRedaction : null],
            classification: ['non-readable content'],
            section: [null],
            option: [this.options[0]],
        });
    }

    #formatSelectedTextValue(): void {
        this.data.manualRedactionEntryWrapper.manualRedactionEntry.value =
            this.data.manualRedactionEntryWrapper.manualRedactionEntry.value.replace(
                // eslint-disable-next-line no-control-regex,max-len
                /([^\s\d-]{2,})[-\u00AD]\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]/gi,
                '$1',
            );
    }

    #selectReason() {
        if (this.legalOptions.length === 1) {
            this.form.get('reason').setValue(this.legalOptions[0]);
        }
    }

    #enhanceManualRedaction(addRedactionRequest: IAddRedactionRequest) {
        const legalOption: LegalBasisOption = this.form.get('reason').value;
        addRedactionRequest.type = this.form.get('dictionary').value;
        if (legalOption) {
            addRedactionRequest.reason = legalOption.description;
            addRedactionRequest.legalBasis = legalOption.legalBasis;
        }

        if (this._iqserPermissionsService.has(Roles.getRss)) {
            const selectedType = this.dictionaries.find(d => d.type === addRedactionRequest.type);
            addRedactionRequest.addToDictionary = selectedType.hasDictionary;
        } else {
            addRedactionRequest.addToDictionary = this.dictionaryRequest && addRedactionRequest.type !== 'dossier_redaction';
            addRedactionRequest.addToDossierDictionary = this.dictionaryRequest && addRedactionRequest.type === 'dossier_redaction';
        }

        if (!addRedactionRequest.reason) {
            addRedactionRequest.reason = 'Dictionary Request';
        }
        const commentValue = this.form.get('comment').value;
        addRedactionRequest.comment = commentValue ? { text: commentValue } : null;
        addRedactionRequest.section = this.form.get('section').value;
        addRedactionRequest.value = addRedactionRequest.rectangle
            ? this.form.get('classification').value
            : this.form.get('selectedText').value;
    }

    #options() {
        const options: DetailsRadioOption<RedactTextOption>[] = [
            {
                label: this.#translations[this.type].onlyHere.label,
                description: this.#translations[this.type].onlyHere.description,
                icon: PIN_ICON,
                value: RedactTextOptions.ONLY_HERE,
            },
        ];
        if (!this._iqserPermissionsService.has(Roles.getRss)) {
            options.push({
                label: this.#translations[this.type].inDossier.label,
                description: this.#translations[this.type].inDossier.description,
                descriptionParams: { dossierName: this.#dossier.dossierName },
                icon: FOLDER_ICON,
                value: RedactTextOptions.IN_DOSSIER,
                extraOption: {
                    label: this.#translations[this.type].inDossier.extraOptionLabel,
                    checked: this.data.applyToAllDossiers ?? true,
                },
            });
        }
        return options;
    }

    #resetValues() {
        this.#applyToAllDossiers = this.data.applyToAllDossiers ?? true;
        this.options[1].extraOption.checked = this.#applyToAllDossiers;
        if (this.dictionaryRequest) {
            this.form.get('reason').setValue(null);
            this.form.get('dictionary').setValue(null);
            return;
        }
        this.form.get('dictionary').setValue(this.#manualRedactionTypeExists ? SuperTypes.ManualRedaction : null);
    }
}
