import { Injectable } from '@angular/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { IConfirmationDialogData, IqserDialog, LoadingService } from '@iqser/common-ui';
import { Dossier, File, User, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { FileManagementService } from '@services/files/file-management.service';
import { FilesService } from '@services/files/files.service';
import { ReanalysisService } from '@services/reanalysis.service';
import { firstValueFrom, forkJoin } from 'rxjs';
import { AssignReviewerApproverDialogComponent } from '../../shared-dossiers/dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
import { DossiersDialogService } from '../../shared-dossiers/services/dossiers-dialog.service';
import { FileAssignService } from '../../shared-dossiers/services/file-assign.service';
import { getCurrentUser } from '@common-ui/users';

@Injectable()
export class BulkActionsService {
    readonly currentUser = getCurrentUser<User>();

    constructor(
        private readonly _dialogService: DossiersDialogService,
        private readonly _iqserDialog: IqserDialog,
        private readonly _loadingService: LoadingService,
        private readonly _activeDossiersService: ActiveDossiersService,
        private readonly _filesService: FilesService,
        private readonly _fileAssignService: FileAssignService,
        private readonly _reanalysisService: ReanalysisService,
        private readonly _fileManagementService: FileManagementService,
    ) {}

    async setToUnderApproval(files: File[]) {
        const dossier = this.#getDossier(files);
        // If more than 1 approver - show dialog and ask who to assign
        if (dossier.approverIds.length > 1) {
            this.#assignFiles(files, WorkflowFileStatuses.UNDER_APPROVAL, true);
        } else {
            this._loadingService.start();
            await this._filesService.setUnderApproval(files, dossier.approverIds[0]);
            this._loadingService.stop();
        }
    }

    async assignToMe(files: File[]) {
        await this._fileAssignService.assignToMe(files);
    }

    async ocr(files: File[]) {
        this._loadingService.start();
        await this._reanalysisService.ocrFiles(files, files[0].dossierId);
        this._loadingService.stop();
    }

    delete(files: File[]) {
        this._dialogService.openDialog(
            'confirm',
            {
                title: _('confirmation-dialog.delete-file.title'),
                question: _('confirmation-dialog.delete-file.question'),
            } as IConfirmationDialogData,
            async () => {
                this._loadingService.start();
                await firstValueFrom(this._fileManagementService.delete(files, files[0].dossierId));
                this._loadingService.stop();
            },
        );
    }

    async reanalyse(files: File[]) {
        this._loadingService.start();
        await this._reanalysisService.reanalyzeFilesForDossier(files, files[0].dossierId, { force: true, triggeredByUser: true });
        this._loadingService.stop();
    }

    async toggleAutomaticAnalysis(files: File[]) {
        this._loadingService.start();
        await firstValueFrom(this._reanalysisService.toggleAutomaticAnalysis(files[0].dossierId, files));
        this._loadingService.stop();
    }

    async toggleAnalysis(files: File[], excluded: boolean) {
        this._loadingService.start();
        await this._reanalysisService.toggleAnalysis(files[0].dossierId, files, excluded);
        this._loadingService.stop();
    }

    async backToUnderReview(files: File[]): Promise<void> {
        this._loadingService.start();
        const [unassignedFiles, assignedFiles] = files.reduce(
            (result, element) => {
                result[!element.assignee ? 0 : 1].push(element);
                return result;
            },
            [[], []],
        );

        const requests$ = [];
        if (unassignedFiles.length) {
            requests$.push(this._filesService.setReviewer(unassignedFiles, this.currentUser.id));
        }
        if (assignedFiles.length) {
            requests$.push(this._filesService.setUnderReview(assignedFiles));
        }
        await firstValueFrom(forkJoin(requests$));
        this._loadingService.stop();
    }

    async setToNew(files: File[]): Promise<void> {
        this._loadingService.start();
        await this._filesService.setToNew(files);
        this._loadingService.stop();
    }

    async approve(files: File[]): Promise<void> {
        const foundAnalysisRequiredFile = files.find(file => file.analysisRequired);
        const foundUpdatedFile = files.find(file => file.hasUpdates);
        if (foundAnalysisRequiredFile || foundUpdatedFile) {
            this._dialogService.openDialog(
                'confirm',
                {
                    title: foundAnalysisRequiredFile
                        ? _('confirmation-dialog.approve-multiple-files-without-analysis.title')
                        : _('confirmation-dialog.approve-multiple-files.title'),
                    question: foundAnalysisRequiredFile
                        ? _('confirmation-dialog.approve-multiple-files-without-analysis.question')
                        : _('confirmation-dialog.approve-multiple-files.question'),
                    confirmationText: foundAnalysisRequiredFile
                        ? _('confirmation-dialog.approve-multiple-files-without-analysis.confirmationText')
                        : null,
                    denyText: foundAnalysisRequiredFile ? _('confirmation-dialog.approve-multiple-files-without-analysis.denyText') : null,
                } as IConfirmationDialogData,
                async () => {
                    this._loadingService.start();
                    await this._filesService.setApproved(files);
                    this._loadingService.stop();
                },
            );
        } else {
            this._loadingService.start();
            await this._filesService.setApproved(files);
            this._loadingService.stop();
        }
    }

    assign(files: File[]): void {
        this.#assignFiles(files, files[0].workflowStatus, false, true);
    }

    #getDossier(files: File[]): Dossier {
        return this._activeDossiersService.find(files[0].dossierId);
    }

    #assignFiles(files: File[], targetStatus: WorkflowFileStatus, ignoreChanged = false, withUnassignedOption = false): void {
        this._iqserDialog.openDefault(AssignReviewerApproverDialogComponent, {
            data: {
                targetStatus,
                files,
                ignoreChanged,
                withUnassignedOption,
            },
            disableClose: false,
        });
    }
}
