import { NgForOf, NgIf } from '@angular/common';
import { Component, inject, OnInit } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatDialogClose } from '@angular/material/dialog';
import { MatFormField } from '@angular/material/form-field';
import { MatOption, MatSelect, MatSelectTrigger } from '@angular/material/select';
import { MatTooltip } from '@angular/material/tooltip';
import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option';
import {
    CircleButtonComponent,
    HasScrollbarDirective,
    HelpButtonComponent,
    IconButtonComponent,
    IconButtonTypes,
    IqserDenyDirective,
    IqserDialogComponent,
} from '@iqser/common-ui';
import { TranslateModule } from '@ngx-translate/core';
import { Dictionary, SuperTypes } from '@red/domain';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { DictionaryService } from '@services/entity-services/dictionary.service';
import { JustificationsService } from '@services/entity-services/justifications.service';
import { Roles } from '@users/roles';
import { firstValueFrom } from 'rxjs';
import {
    SelectedAnnotationsTableComponent,
    ValueColumn,
} from '../../components/selected-annotations-table/selected-annotations-table.component';
import { DialogHelpModeKeys } from '../../utils/constants';
import { getEditRedactionOptions } from '../../utils/dialog-options';
import { EditRedactionData, EditRedactResult, RedactOrHintOption } from '../../utils/dialog-types';
import { LegalBasisOption } from '../manual-redaction-dialog/manual-annotation-dialog.component';

interface TypeSelectOptions {
    type: string;
    description: string;
    label: string;
}

@Component({
    templateUrl: './edit-redaction-dialog.component.html',
    styleUrls: ['./edit-redaction-dialog.component.scss'],
    standalone: true,
    imports: [
        ReactiveFormsModule,
        TranslateModule,
        SelectedAnnotationsTableComponent,
        MatFormField,
        NgIf,
        MatSelectTrigger,
        MatSelect,
        MatOption,
        NgForOf,
        MatTooltip,
        IconButtonComponent,
        IqserDenyDirective,
        CircleButtonComponent,
        HelpButtonComponent,
        MatDialogClose,
        HasScrollbarDirective,
    ],
})
export class EditRedactionDialogComponent
    extends IqserDialogComponent<EditRedactionDialogComponent, EditRedactionData, EditRedactResult>
    implements OnInit
{
    readonly #dossier = inject(ActiveDossiersService).find(this.data.dossierId);
    readonly #applyToAllDossiers = this.data.applyToAllDossiers;
    protected readonly roles = Roles;
    readonly annotations = this.data.annotations;
    readonly iconButtonTypes = IconButtonTypes;
    readonly isModifyDictionary = this.annotations.every(annotation => annotation.isModifyDictionary);
    readonly isImage = this.annotations.reduce((acc, next) => acc && next.isImage, true);
    readonly redactedTexts = !this.isImage ? this.annotations.map(annotation => annotation.value).filter(value => !!value) : null;
    readonly isManualRedaction = this.annotations.some(annotation => annotation.type === SuperTypes.ManualRedaction);
    readonly isHint = this.annotations.every(annotation => annotation.HINT || annotation.IMAGE_HINT);
    readonly isRedacted = this.annotations.every(annotation => annotation.isRedacted);
    readonly isImported: boolean = this.annotations.every(annotation => annotation.imported);
    readonly allRectangles = this.annotations.reduce((acc, a) => acc && a.AREA, true);
    readonly tableColumns = [
        {
            label: 'Value',
            show: true,
        },
        {
            label: 'Type',
            show: true,
        },
    ];
    readonly tableData: ValueColumn[][] = this.data.annotations.map(redaction => [
        { label: redaction.value, show: true, bold: true },
        { label: redaction.typeLabel, show: true },
    ]);
    options: DetailsRadioOption<RedactOrHintOption>[] | undefined;
    legalOptions: LegalBasisOption[] = [];
    dictionaries: Dictionary[] = [];
    typeSelectOptions: TypeSelectOptions[] = [];
    readonly form = this.#getForm();
    hasTypeChanged = false;
    initialReasonDisabled = this.someSkipped;

    constructor(
        private readonly _justificationsService: JustificationsService,
        private readonly _dictionaryService: DictionaryService,
    ) {
        super();
    }

    get displayedDictionaryLabel() {
        const selectedDictionaryType = this.form.controls.type.value;
        if (selectedDictionaryType) {
            return this.typeSelectOptions.find(option => option.type === selectedDictionaryType)?.label ?? null;
        }
        return null;
    }

    get showExtras() {
        return (this.isImage && this.isRedacted) || !(this.isImage || this.isHint);
    }

    get disabled() {
        return (
            this.form.invalid ||
            (!this.isImage && this.showExtras && !this.form.controls.reason.disabled ? !this.form.controls.reason.value : false)
        );
    }

    get someSkipped() {
        return this.annotations.some(annotation => annotation.isSkipped);
    }

    get redactBasedTypes() {
        return this._dictionaryService.getRedactionTypes(this.#dossier.dossierTemplateId).map(dictionary => dictionary.type);
    }

    get isRedactBasedType() {
        return this.redactBasedTypes.includes(this.form.controls.type.value);
    }

    get hideReasonPlaceholder() {
        return (this.hasTypeChanged && this.isRedactBasedType) || this.#isFieldEmpty('legalBasisValue');
    }

    get hideParagraphPlaceholder() {
        return this.form.controls.section.value !== this.initialFormValue['section'] || this.#isFieldEmpty('section');
    }

    get hiddenReason() {
        return this.isImage && this.form.controls.reason.disabled;
    }

    get isBulkEdit() {
        return this.annotations.length > 1;
    }

    get helpButtonKey() {
        if (this.isHint) {
            return DialogHelpModeKeys.HINT_EDIT;
        }
        if (this.someSkipped) {
            return DialogHelpModeKeys.SKIPPED_EDIT;
        }
        return DialogHelpModeKeys.REDACTION_EDIT;
    }

    get sameType() {
        return this.annotations.every(annotation => annotation.type === this.annotations[0].type);
    }

    async ngOnInit() {
        this.#setTypes();
        const data = await firstValueFrom(this._justificationsService.loadAll(this.#dossier.dossierTemplateId));
        this.legalOptions = data.map(lbm => ({
            legalBasis: lbm.reason,
            description: lbm.description,
            label: lbm.name,
        }));

        const reason = this.legalOptions.find(o => o.legalBasis === this.annotations[0].legalBasis);
        const sameLegalBasis = this.annotations.every(annotation => annotation.legalBasis === reason?.legalBasis);
        this.form.patchValue({
            reason: sameLegalBasis ? reason : null,
        });

        this.legalOptions.sort((a, b) => a.label.localeCompare(b.label));
        this.initialFormValue = this.form.getRawValue();
    }

    typeChanged() {
        const selectedDictionaryType = this.form.controls.type.value;
        this.#setOptions(selectedDictionaryType);

        const initialReason = this.form.get('type').value === this.initialFormValue.type && !this.initialReasonDisabled;
        if (this.redactBasedTypes.includes(selectedDictionaryType) || initialReason) {
            this.form.controls.reason.enable();
            this.hasTypeChanged = true;
            if (initialReason) {
                setTimeout(() => {
                    this.form.controls.reason.setValue(this.initialFormValue.reason);
                });
            }
        } else {
            this.form.controls.reason.disable();
        }
        this.form.patchValue({ reason: null, option: null });
    }

    save() {
        const value = this.form.value;
        const initialReason: LegalBasisOption = this.initialFormValue.reason;
        const initialLegalBasis = initialReason?.legalBasis ?? '';
        this.close({
            legalBasis: value.reason?.legalBasis ?? (this.isImage ? initialLegalBasis : ''),
            section: value.section,
            comment: value.comment,
            type: value.type,
            value: this.allRectangles ? value.value : null,
        });
    }

    #setTypes() {
        this.dictionaries = this._dictionaryService.getEditableRedactionTypes(
            this.#dossier.dossierId,
            this.isImage,
            this.isHint,
            this.annotations.every(annotation => annotation.isOCR),
            this.sameType ? this.annotations[0].type : null,
        );

        this.typeSelectOptions = this.dictionaries.map(dictionary => ({
            type: dictionary.type,
            label: dictionary.label,
            description: dictionary.description,
        }));

        if (this.isImported) {
            const importedAnnotation = this.annotations[0];
            this.typeSelectOptions.push({ type: this.annotations[0].type, label: importedAnnotation.typeLabel, description: '' });
        }
    }

    #setOptions(type: string, reasonChanged = false) {
        const selectedDictionary = this.dictionaries.find(d => d.type === type);
        this.options = getEditRedactionOptions(
            this.#dossier.dossierName,
            this.#applyToAllDossiers,
            !!selectedDictionary?.dossierDictionaryOnly,
            this.isModifyDictionary,
        );
        this.form.patchValue(
            {
                option: !this.isModifyDictionary || reasonChanged ? this.options[0] : this.options[1],
            },
            { emitEvent: false },
        );
    }

    #getForm() {
        const sameSection = this.annotations.every(annotation => annotation.section === this.annotations[0].section);
        return new FormGroup({
            reason: new FormControl<LegalBasisOption>({ value: null, disabled: this.someSkipped }),
            comment: new FormControl<string>(null),
            type: new FormControl<string>({
                value: this.sameType ? this.annotations[0].type : null,
                disabled: this.isImported,
            }),
            section: new FormControl<string>({ value: sameSection ? this.annotations[0].section : null, disabled: this.isImported }),
            option: new FormControl<LegalBasisOption>(null),
            value: new FormControl<string>(this.allRectangles ? this.annotations[0].value : null),
        });
    }

    #isFieldEmpty(field: string) {
        return this.annotations.every(annotation => !annotation[field]?.length);
    }
}
