import { NgStyle } from '@angular/common';
import { Component, computed } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { FormBuilder, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
import { MatDialogClose } from '@angular/material/dialog';
import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option';
import { DetailsRadioComponent } from '@common-ui/inputs/details-radio/details-radio.component';
import {
    CircleButtonComponent,
    HasScrollbarDirective,
    HelpButtonComponent,
    IconButtonComponent,
    IconButtonTypes,
    IqserDenyDirective,
    IqserDialogComponent,
} from '@iqser/common-ui';
import { TranslateModule } from '@ngx-translate/core';
import { Roles } from '@users/roles';
import { UserPreferenceService } from '@users/user-preference.service';
import { stringToBoolean } from '@utils/functions';
import { map } from 'rxjs/operators';
import { SystemDefaultOption, SystemDefaults } from '../../../account/utils/dialog-defaults';
import {
    SelectedAnnotationsTableComponent,
    ValueColumn,
} from '../../components/selected-annotations-table/selected-annotations-table.component';
import { getRectangleRedactOptions, getRemoveRedactionOptions } from '../../utils/dialog-options';
import {
    RectangleRedactOption,
    RectangleRedactOptions,
    RemoveRedactionData,
    RemoveRedactionOption,
    RemoveRedactionOptions,
    RemoveRedactionResult,
    ResizeOptions,
} from '../../utils/dialog-types';
import { isJustOne } from '@common-ui/utils';
import { validatePageRange } from '../../utils/form-validators';
import { parseRectanglePosition, parseSelectedPageNumbers, prefillPageRange } from '../../utils/enhance-manual-redaction-request.utils';

@Component({
    templateUrl: './remove-redaction-dialog.component.html',
    styleUrls: ['./remove-redaction-dialog.component.scss'],
    standalone: true,
    imports: [
        ReactiveFormsModule,
        TranslateModule,
        NgStyle,
        SelectedAnnotationsTableComponent,
        DetailsRadioComponent,
        IconButtonComponent,
        CircleButtonComponent,
        HasScrollbarDirective,
        MatDialogClose,
        IqserDenyDirective,
        HelpButtonComponent,
    ],
})
export class RemoveRedactionDialogComponent extends IqserDialogComponent<
    RemoveRedactionDialogComponent,
    RemoveRedactionData,
    RemoveRedactionResult
> {
    protected readonly roles = Roles;
    readonly iconButtonTypes = IconButtonTypes;
    readonly recommendation = this.data.redactions.every(redaction => redaction.isRecommendation);
    readonly hint = this.data.redactions.every(redaction => redaction.isHint);
    readonly annotationsType = this.hint ? 'hint' : this.recommendation ? 'recommendation' : 'redaction';
    readonly optionByType = {
        recommendation: {
            main: this._userPreferences.getRemoveRecommendationDefaultOption(),
            extra: this._userPreferences.getRemoveRecommendationDefaultExtraOption(),
        },
        hint: {
            main: this._userPreferences.getRemoveHintDefaultOption(),
            extra: this._userPreferences.getRemoveHintDefaultExtraOption(),
        },
        redaction: {
            main: this._userPreferences.getRemoveRedactionDefaultOption(),
            extra: this._userPreferences.getRemoveRedactionDefaultExtraOption(),
        },
    };
    readonly systemDefaultByType = {
        recommendation: {
            main: SystemDefaults.REMOVE_RECOMMENDATION_DEFAULT,
            extra: this.data.applyToAllDossiers,
        },
        hint: {
            main: SystemDefaults.REMOVE_HINT_DEFAULT,
            extra: this.data.applyToAllDossiers,
        },
        redaction: {
            main: SystemDefaults.REMOVE_REDACTION_DEFAULT,
            extra: false,
        },
    };
    readonly #allRectangles = this.data.redactions.reduce((acc, a) => acc && a.AREA, true);
    readonly #applyToAllDossiers = this.systemDefaultByType[this.annotationsType].extra;
    readonly isSystemDefault = this.optionByType[this.annotationsType].main === SystemDefaultOption.SYSTEM_DEFAULT;
    readonly isExtraOptionSystemDefault = this.optionByType[this.annotationsType].extra === 'undefined';
    readonly defaultOptionPreference = this.isSystemDefault
        ? this.systemDefaultByType[this.annotationsType].main
        : this.optionByType[this.annotationsType].main;
    readonly extraOptionPreference = stringToBoolean(this.optionByType[this.annotationsType].extra);
    readonly options: DetailsRadioOption<RectangleRedactOption | RemoveRedactionOption>[] = this.#allRectangles
        ? getRectangleRedactOptions('remove')
        : getRemoveRedactionOptions(
              this.data,
              this.isSystemDefault || this.isExtraOptionSystemDefault ? this.#applyToAllDossiers : this.extraOptionPreference,
          );
    readonly skipped = this.data.redactions.some(annotation => annotation.isSkipped);
    readonly redactedTexts = this.data.redactions.map(annotation => annotation.value);
    form: UntypedFormGroup = this._formBuilder.group({
        comment: [null],
        option: [this.defaultOption, validatePageRange(this.data.file.numberOfPages, true)],
    });

    readonly selectedOption = toSignal(this.form.get('option').valueChanges.pipe(map(value => value.value)));
    readonly isFalsePositive = computed(() => this.selectedOption() === RemoveRedactionOptions.FALSE_POSITIVE);
    readonly tableColumns = computed<ValueColumn[]>(() => [
        { label: 'Value', width: '25%' },
        { label: 'Type', width: '25%' },
        {
            label: 'Context',
            hide: !this.isFalsePositive(),
            width: '50%',
        },
    ]);

    readonly tableData = computed<ValueColumn[][]>(() =>
        this.data.redactions.map((redaction, index) => [
            { label: redaction.value, bold: true },
            { label: redaction.typeLabel },
            { label: this.data.falsePositiveContext[index], hide: !this.isFalsePositive() },
        ]),
    );

    constructor(
        private readonly _formBuilder: FormBuilder,
        private readonly _userPreferences: UserPreferenceService,
    ) {
        super();

        if (this.#allRectangles) {
            prefillPageRange(
                this.data.redactions[0],
                this.data.allFileRedactions,
                this.options as DetailsRadioOption<RectangleRedactOption>[],
            );
        }
    }

    get hasFalsePositiveOption() {
        return !!this.options.find(option => option.value === RemoveRedactionOptions.FALSE_POSITIVE);
    }

    get defaultOption() {
        const removeDefaultOption = this.#getOption(this.defaultOptionPreference as RemoveRedactionOption);
        if (!!removeDefaultOption && !removeDefaultOption.disabled) return removeDefaultOption;
        return this.options[0];
    }

    get typeTranslationArg() {
        return { type: this.annotationsType };
    }

    get isBulk() {
        return !isJustOne(this.data.redactions);
    }

    get redactedTextsAreaHeight() {
        return this.redactedTexts.length <= 10 ? 18 * this.redactedTexts.length : 180;
    }

    get dialogContentHeight() {
        return this.options.length * 75 + 230;
    }

    extraOptionChanged(option: DetailsRadioOption<RemoveRedactionOption | RectangleRedactOption>): void {
        if (option.value === RectangleRedactOptions.MULTIPLE_PAGES) {
            setTimeout(() => {
                this.form.get('option')?.updateValueAndValidity();
            }, 0);
        }
    }

    save(): void {
        const optionValue = this.form.controls.option?.value?.value;
        const optionInputValue = this.form.controls.option?.value?.additionalInput?.value;
        const pageNumbers = parseSelectedPageNumbers(optionInputValue, this.data.file, this.data.redactions[0]);
        const position = parseRectanglePosition(this.data.redactions[0]);

        this.close({
            ...this.form.getRawValue(),
            bulkLocal: optionValue === ResizeOptions.IN_DOCUMENT || optionValue === RectangleRedactOptions.MULTIPLE_PAGES,
            pageNumbers,
            position,
        });
    }

    #getOption(option: RemoveRedactionOption): DetailsRadioOption<RectangleRedactOption | RemoveRedactionOption> {
        return this.options.find(o => o.value === option);
    }
}
