import {
    ChangeDetectorRef,
    Component,
    EventEmitter,
    Input,
    OnChanges,
    OnInit,
    Output,
    signal,
    SimpleChanges,
    ViewChild,
} from '@angular/core';
import { CircleButtonComponent, IconButtonComponent, IconButtonTypes, LoadingService } from '@iqser/common-ui';
import { Dictionary, DictionaryEntryType, DictionaryEntryTypes, DictionaryType, Dossier, DossierTemplate, IDictionary } from '@red/domain';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { DictionaryService } from '@services/entity-services/dictionary.service';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
import { EditorComponent } from '@shared/components/editor/editor.component';
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
import { saveAs } from 'file-saver';
import { List } from '@iqser/common-ui/lib/utils';
import { firstValueFrom } from 'rxjs';
import { MatIcon } from '@angular/material/icon';
import { NgForOf, NgIf } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { MatTooltip } from '@angular/material/tooltip';
import { MatCheckbox } from '@angular/material/checkbox';
import { MatFormField } from '@angular/material/form-field';
import { MatOption, MatSelect } from '@angular/material/select';
import { MatDivider } from '@angular/material/divider';

const COMPARE_ENTRIES_ERROR = 'compare-entries-error';
const HELP_MODE_KEYS = {
    dictionary: 'dictionary_entity',
    'false-positive': 'false_recommendations_entity',
    'false-recommendations': 'false_recommendations_entity',
};

@Component({
    selector: 'redaction-dictionary-manager',
    templateUrl: './dictionary-manager.component.html',
    styleUrls: ['./dictionary-manager.component.scss'],
    standalone: true,
    imports: [
        MatIcon,
        NgIf,
        FormsModule,
        TranslateModule,
        CircleButtonComponent,
        MatTooltip,
        MatCheckbox,
        MatFormField,
        MatSelect,
        MatOption,
        MatDivider,
        NgForOf,
        IconButtonComponent,
        EditorComponent,
    ],
})
export class DictionaryManagerComponent implements OnChanges, OnInit {
    @Input() type: DictionaryType = 'dictionary';
    @Input() entityType?: string;
    @Input() currentDossierId: string;
    @Input() currentDossierTemplateId: string;
    @Input() withFloatingActions = true;
    @Input() initialEntries: List;
    @Input() canEdit = false;
    @Input() canDownload = false;
    @Input() isLeavingPage = false;
    @Input() hint = false;
    @Input() selectedDictionaryType = 'dossier_redaction';
    @Input() selectedDictionaryTypeLabel: string;
    @Input() activeEntryType: DictionaryEntryType = DictionaryEntryTypes.ENTRY;
    @Output() readonly saveDictionary = new EventEmitter<string[]>();
    @ViewChild(EditorComponent) readonly editor: EditorComponent;
    readonly iconButtonTypes = IconButtonTypes;
    dossiers: Dossier[];
    dossierTemplates: DossierTemplate[] = this.dossierTemplatesService.all;
    diffEditorText = '';
    showDiffEditor = false;
    selectDossier = { dossierName: _('dictionary-overview.compare.select-dossier') } as Dossier;
    selectDictionary = {
        label: _('dictionary-overview.compare.select-dictionary'),
    } as Dictionary;
    selectDossierTemplate = { name: _('dictionary-overview.compare.select-dossier-template') } as DossierTemplate;
    compare = false;
    dictionaries: List<Dictionary> = this.#dictionaries;
    protected readonly _isSearchOpen = signal(false);
    protected initialDossierTemplateId: string;
    readonly #currentTab = window.location.href.split('/').pop();
    #dossierTemplate = this.dossierTemplatesService.all[0];
    #dossier = this.selectDossier;
    #dictionary = this.selectDictionary;

    constructor(
        private readonly _dictionaryService: DictionaryService,
        private readonly _dictionariesMapService: DictionariesMapService,
        private readonly _activeDossiersService: ActiveDossiersService,
        private readonly _changeRef: ChangeDetectorRef,
        protected readonly _loadingService: LoadingService,
        readonly dossierTemplatesService: DossierTemplatesService,
    ) {}

    get selectedDossierTemplate() {
        return this.#dossierTemplate;
    }

    set selectedDossierTemplate(value: DossierTemplate) {
        if (!value) {
            value = this.initialDossierTemplateId
                ? this.dossierTemplates.find(t => t.id === this.initialDossierTemplateId)
                : this.selectDossierTemplate;
        }
        this.#dossierTemplate = value;
        this.currentDossierTemplateId = value.dossierTemplateId;
        this.#dossier = this.selectDossier;
        this.dictionaries = this.#dictionaries;
        this.#disableDiffEditor();

        if (!this.initialDossierTemplateId && !this.currentDossierId) {
            this.selectedDictionary = this.selectDictionary;
        }

        this.#updateDropdownsOptions(false);
    }

    get selectedDossier() {
        return this.#dossier;
    }

    set selectedDossier(dossier: Dossier) {
        this.#dossier = dossier;

        if (dossier.dossierName === this.selectDossier.dossierName) {
            this.#disableDiffEditor();
            return;
        }

        this.#onDossierChanged(dossier.dossierTemplateId, dossier.id).then(entries => this.#updateDiffEditorText(entries));
    }

    get selectedDictionary() {
        return this.#dictionary;
    }

    set selectedDictionary(dictionary: Dictionary) {
        if (dictionary.type) {
            this.selectedDictionaryType = dictionary.type;
            this.#dictionary = dictionary;
            console.log(dictionary);
            this.#onDossierChanged(this.#dossier.dossierTemplateId).then(entries => this.#updateDiffEditorText(entries));
        }
    }

    get optionNotSelected() {
        if (this.initialDossierTemplateId) {
            return this.selectedDossier.dossierName === this.selectDossier.dossierName;
        }
        return this.selectedDictionary.label === this.selectDictionary.label;
    }

    get templateSelected() {
        return this.selectDossierTemplate.name !== this.selectedDossierTemplate.name;
    }

    get helpModeKey(): string {
        return HELP_MODE_KEYS[this.#currentTab];
    }

    get #dictionaries(): Dictionary[] {
        if (!this.#dossierTemplate || this.#dossierTemplate.name === this.selectDossierTemplate.name) {
            return;
        }
        return [
            this.selectDictionary,
            ...this._dictionariesMapService.get(this.selectedDossierTemplate?.dossierTemplateId).filter(dict => !dict.virtual),
        ];
    }

    get #templatesWithCurrentEntityType() {
        return this.dossierTemplatesService.all.filter(t =>
            this._dictionaryService.hasType(t.dossierTemplateId, this.selectedDictionaryType),
        );
    }

    ngOnInit() {
        this.initialDossierTemplateId = this.currentDossierTemplateId;
        this.#updateDropdownsOptions();
    }

    download(): void {
        const content = this.editor.currentEntries.join('\n');
        const blob = new Blob([content], {
            type: 'text/plain;charset=utf-8',
        });
        saveAs(blob, `${this.entityType}-${this.type}.txt`);
    }

    revert() {
        this.editor?.revert();
    }

    toggleCompareMode() {
        this.compare = !this.compare;
        if (!this.compare) {
            this.selectedDossier = this.selectDossier;
        }
    }

    ngOnChanges(changes: SimpleChanges): void {
        if (changes.activeEntryType && this.#dossier?.dossierTemplateId && this.selectedDossier?.dossierId) {
            this.#onDossierChanged(this.#dossier.dossierTemplateId, this.#dossier.dossierId).then(entries =>
                this.#updateDiffEditorText(entries),
            );
        }

        if (changes.selectedDictionaryType) {
            this.#disableDiffEditor();
            this.#updateDropdownsOptions();
        }
    }

    async #onDossierChanged(dossierTemplateId: string, dossierId?: string) {
        let dictionary: IDictionary;
        if (dossierId === 'template') {
            dictionary = await this._dictionaryService.getForType(dossierTemplateId, this.selectedDictionaryType);
        } else {
            if (dossierId) {
                dictionary = (
                    await firstValueFrom(
                        this._dictionaryService.loadDictionaryEntriesByType([this.selectedDictionaryType], dossierTemplateId, dossierId),
                    ).catch(() => {
                        return [{ entries: [COMPARE_ENTRIES_ERROR], type: '' }];
                    })
                )[0];
            } else {
                dictionary = this.selectedDictionaryType
                    ? await this._dictionaryService.getForType(this.currentDossierTemplateId, this.selectedDictionaryType)
                    : { entries: [COMPARE_ENTRIES_ERROR], type: '' };
            }
        }

        const activeEntries =
            this.activeEntryType === DictionaryEntryTypes.ENTRY || this.hint
                ? [...dictionary.entries]
                : this.activeEntryType === DictionaryEntryTypes.FALSE_POSITIVE
                  ? [...dictionary.falsePositiveEntries]
                  : [...dictionary.falseRecommendationEntries];
        return activeEntries.join('\n');
    }

    #updateDropdownsOptions(updateSelectedDossierTemplate = true) {
        if (updateSelectedDossierTemplate) {
            this.currentDossierTemplateId = this.initialDossierTemplateId ?? this.currentDossierTemplateId;
            this.dossierTemplates = this.currentDossierTemplateId ? this.#templatesWithCurrentEntityType : this.dossierTemplatesService.all;
            if (!this.currentDossierTemplateId) {
                this.dossierTemplates = [this.selectDossierTemplate, ...this.dossierTemplates];
            }
            this.selectedDossierTemplate = this.dossierTemplates.find(t => t.id === this.currentDossierTemplateId);
        }
        this.dossiers = this._activeDossiersService.all.filter(
            d => d.dossierTemplateId === this.currentDossierTemplateId && d.id !== this.currentDossierId,
        );
        const templateDictionary = {
            id: 'template',
            dossierId: 'template',
            dossierName: 'Template Dictionary',
            dossierTemplateId: this.currentDossierTemplateId,
        } as Dossier;
        this.dossiers.push(templateDictionary);
    }

    #disableDiffEditor() {
        this.showDiffEditor = false;
        this.diffEditorText = '';
    }

    #updateDiffEditorText(entries: string) {
        if (!entries.startsWith(COMPARE_ENTRIES_ERROR)) {
            this.diffEditorText = entries;
            this.showDiffEditor = true;
            this._changeRef.markForCheck();
        }
    }
}
