import { HttpStatusCode } from '@angular/common/http';
import { Component, ElementRef, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import {
    defaultDialogConfig,
    IconButtonTypes,
    largeDialogConfig,
    ListingComponent,
    listingProvidersFactory,
    LoadingService,
    TableColumnConfig,
    Toaster,
} from '@iqser/common-ui';
import { getCurrentUser } from '@iqser/common-ui/lib/users';
import { getParam } from '@iqser/common-ui/lib/utils';
import { DOSSIER_TEMPLATE_ID, FileAttributeConfig, IFileAttributeConfig, IFileAttributesConfig, User } from '@red/domain';
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
import { PermissionsService } from '@services/permissions.service';
import { fileAttributeTypesTranslations } from '@translations/file-attribute-types-translations';
import { Roles } from '@users/roles';
import { firstValueFrom } from 'rxjs';
import { AdminDialogService } from '../../services/admin-dialog.service';
import {
    AddEditFileAttributeDialogComponent,
    AddEditFileAttributeDialogData,
} from './add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
import { FileAttributesConfigurationsDialogComponent } from './file-attributes-configurations-dialog/file-attributes-configurations-dialog.component';
import {
    FileAttributesCsvImportDialogComponent,
    IFileAttributesCSVImportData,
} from './file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';

@Component({
    templateUrl: './file-attributes-listing-screen.component.html',
    styleUrls: ['./file-attributes-listing-screen.component.scss'],
    providers: listingProvidersFactory(FileAttributesListingScreenComponent),
})
export class FileAttributesListingScreenComponent extends ListingComponent<FileAttributeConfig> implements OnInit, OnDestroy {
    @ViewChild('impactedTemplates') private readonly _impactedTemplatesRef: TemplateRef<unknown>;
    #existingConfiguration: IFileAttributesConfig;
    @ViewChild('fileInput') private _fileInput: ElementRef;
    readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
    readonly iconButtonTypes = IconButtonTypes;
    readonly currentUser = getCurrentUser<User>();
    readonly translations = fileAttributeTypesTranslations;
    readonly tableHeaderLabel = _('file-attributes-listing.table-header.title');
    readonly tableColumnConfigs: TableColumnConfig<FileAttributeConfig>[] = [
        { label: _('file-attributes-listing.table-col-names.name'), sortByKey: 'searchKey', width: '2fr' },
        { label: _('file-attributes-listing.table-col-names.type'), sortByKey: 'type' },
        { label: _('file-attributes-listing.table-col-names.read-only'), sortByKey: 'editable', class: 'flex-center' },
        { label: _('file-attributes-listing.table-col-names.csv-column') },
        { label: _('file-attributes-listing.table-col-names.filterable'), class: 'flex-center' },
        { label: _('file-attributes-listing.table-col-names.displayed-in-file-list'), class: 'flex-center' },
        {
            label: _('file-attributes-listing.table-col-names.primary'),
            class: 'flex-center',
            rightIcon: 'red:status-info',
            rightIconTooltip: _('file-attributes-listing.table-col-names.primary-info-tooltip'),
        },
    ];
    readonly roles = Roles;

    constructor(
        readonly permissionsService: PermissionsService,
        private readonly _toaster: Toaster,
        private readonly _loadingService: LoadingService,
        private readonly _dialogService: AdminDialogService,
        private readonly _dialog: MatDialog,
        private readonly _fileAttributesService: FileAttributesService,
        private readonly _dossierTemplatesService: DossierTemplatesService,
    ) {
        super();
    }

    private get _numberOfDisplayedAttrs(): number {
        return this.entitiesService.all.filter(attr => attr.displayedInFileList).length;
    }

    private get _numberOfFilterableAttrs(): number {
        return this.entitiesService.all.filter(attr => attr.filterable).length;
    }

    async ngOnInit() {
        await this.#loadData();
    }

    async openAddEditAttributeDialog(fileAttribute?: IFileAttributeConfig) {
        const data = {
            fileAttribute,
            dossierTemplateId: this.#dossierTemplateId,
            numberOfDisplayedAttrs: this._numberOfDisplayedAttrs,
            numberOfFilterableAttrs: this._numberOfFilterableAttrs,
        };

        const ref = this._dialog.open<AddEditFileAttributeDialogComponent, AddEditFileAttributeDialogData, IFileAttributeConfig>(
            AddEditFileAttributeDialogComponent,
            {
                ...defaultDialogConfig,
                autoFocus: true,
                data,
            },
        );

        const result = await firstValueFrom(ref.afterClosed());
        if (result) {
            this._loadingService.loadWhile(this.#createNewFileAttributeAndRefreshView(result));
        }
    }

    async openConfirmDeleteAttributeDialog(attributes: FileAttributeConfig[] = this.listingService.selected): Promise<void> {
        await this._dialogService.deleteAttributes(attributes, this.#dossierTemplateId, this._impactedTemplatesRef, 'file', async () => {
            this._loadingService.start();
            const ids = attributes.map(a => a.id);
            await firstValueFrom(this._fileAttributesService.deleteFileAttributes(ids, this.#dossierTemplateId));
            await firstValueFrom(this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId));
            await this.#loadData();
        });
    }

    async importCSV(files: FileList | File[]) {
        const csv = files[0];
        this._fileInput.nativeElement.value = null;

        const ref = this._dialog.open<FileAttributesCsvImportDialogComponent, IFileAttributesCSVImportData, boolean>(
            FileAttributesCsvImportDialogComponent,
            {
                ...largeDialogConfig,
                disableClose: false,
                data: {
                    csv,
                    dossierTemplateId: this.#dossierTemplateId,
                    existingConfiguration: this.#existingConfiguration,
                },
            },
        );

        const result = await firstValueFrom(ref.afterClosed());
        if (result) {
            await this.#loadData();
        }
    }

    async openConfigurationsDialog() {
        const ref = this._dialog.open<FileAttributesConfigurationsDialogComponent, IFileAttributesConfig, IFileAttributesConfig>(
            FileAttributesConfigurationsDialogComponent,
            {
                ...defaultDialogConfig,
                data: this.#existingConfiguration,
            },
        );

        const configuration = await firstValueFrom(ref.afterClosed());

        if (configuration) {
            await this.#setConfigAndLoadData(configuration);
        }
    }

    async #setConfigAndLoadData(configuration: IFileAttributesConfig) {
        const request = this._fileAttributesService.setFileAttributeConfig(configuration, this.#dossierTemplateId);
        try {
            await firstValueFrom(request);
            this._toaster.success(_('file-attributes-configurations.update.success'));
            await this.#loadData();
        } catch (e) {
            this._toaster.error(_('file-attributes-configurations.update.error'));
        }
    }

    async #createNewFileAttributeAndRefreshView(newValue: IFileAttributeConfig): Promise<void> {
        const request = this._fileAttributesService.setFileAttributesConfig(newValue, this.#dossierTemplateId);
        await firstValueFrom(request).catch(error => {
            if (error.status === HttpStatusCode.Conflict) {
                this._toaster.error(_('file-attributes-listing.error.conflict'));
            } else {
                this._toaster.error(_('file-attributes-listing.error.generic'));
            }
            this._loadingService.stop();
        });
        await firstValueFrom(this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId));
        await this.#loadData();
    }

    async #loadData() {
        this._loadingService.start();

        try {
            const response = await firstValueFrom(this._fileAttributesService.loadFileAttributesConfig(this.#dossierTemplateId));
            this.#existingConfiguration = response;
            const fileAttributeConfig = response?.fileAttributeConfigs.map(item => new FileAttributeConfig(item)) || [];
            this.entitiesService.setEntities(fileAttributeConfig);
        } catch (e) {}

        this._loadingService.stop();
    }
}
