import { ChangeDetectorRef, Component, HostBinding, Injector, Input, OnChanges, Optional, ViewChild } from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';
import { Router } from '@angular/router';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import {
    CircleButtonTypes,
    getConfig,
    IConfirmationDialogData,
    IqserDialog,
    IqserPermissionsService,
    LoadingService,
    Toaster,
} from '@iqser/common-ui';
import { TenantsService } from '@iqser/common-ui/lib/tenants';
import { getCurrentUser } from '@iqser/common-ui/lib/users';
import { IqserTooltipPositions } from '@iqser/common-ui/lib/utils';
import { Action, ActionTypes, Dossier, File, ProcessingFileStatuses, User } from '@red/domain';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
import { FileManagementService } from '@services/files/file-management.service';
import { FilesService } from '@services/files/files.service';
import { PermissionsService } from '@services/permissions.service';
import { ReanalysisService, ReanalyzeQueryParams } from '@services/reanalysis.service';
import { ExpandableFileActionsComponent } from '@shared/components/expandable-file-actions/expandable-file-actions.component';
import { LongPressEvent } from '@shared/directives/long-press.directive';
import { Roles } from '@users/roles';
import { UserPreferenceService } from '@users/user-preference.service';
import { setLocalStorageDataByFileId } from '@utils/local-storage';
import { firstValueFrom, Observable } from 'rxjs';
import { DocumentInfoService } from '../../../file-preview/services/document-info.service';
import { ExcludedPagesService } from '../../../file-preview/services/excluded-pages.service';
import { PageRotationService } from '../../../pdf-viewer/services/page-rotation.service';
import { ViewerHeaderService } from '../../../pdf-viewer/services/viewer-header.service';
import { ROTATION_ACTION_BUTTONS } from '../../../pdf-viewer/utils/constants';
import { AssignReviewerApproverDialogComponent } from '../../dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { FileAssignService } from '../../services/file-assign.service';

@Component({
    selector: 'redaction-file-actions',
    templateUrl: './file-actions.component.html',
    styleUrls: ['./file-actions.component.scss'],
})
export class FileActionsComponent implements OnChanges {
    @ViewChild(ExpandableFileActionsComponent)
    private readonly _expandableActionsComponent: ExpandableFileActionsComponent;
    readonly #isDocumine = getConfig().IS_DOCUMINE;
    @Input({ required: true }) file: File;
    @Input({ required: true }) dossier: Dossier;
    @Input({ required: true }) type: 'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow';
    @Input() maxWidth: number;
    @Input() minWidth: number;
    @Input() helpModeKeyPrefix: 'dossier' | 'editor' = 'dossier';
    readonly currentUser = getCurrentUser<User>();
    toggleTooltip?: string;
    assignTooltip?: string;
    showSetToNew = false;
    showUndoApproval = false;
    showAssignToSelf = false;
    showImportRedactions = false;
    showAssign = false;
    showDelete = false;
    showOCR = false;
    canReanalyse = false;
    canDisableAutoAnalysis = false;
    canEnableAutoAnalysis = false;
    showUnderReview = false;
    showUnderApproval = false;
    showApprove = false;
    canToggleAnalysis = false;
    showToggleAnalysis = false;
    showStatusBar = false;
    showReanalyseFilePreview = false;
    showReanalyseDossierOverview = false;
    analysisForced = false;
    isDossierOverview = false;
    isDossierOverviewList = false;
    isDossierOverviewWorkflow = false;
    isFilePreview = false;
    tooltipPosition = IqserTooltipPositions.above;
    buttons: Action[];

    constructor(
        private readonly _injector: Injector,
        private readonly _filesService: FilesService,
        private readonly _changeRef: ChangeDetectorRef,
        private readonly _loadingService: LoadingService,
        private readonly _dialogService: DossiersDialogService,
        private readonly _iqserDialog: IqserDialog,
        private readonly _tenantsService: TenantsService,
        private readonly _fileAssignService: FileAssignService,
        private readonly _reanalysisService: ReanalysisService,
        private readonly _permissionsService: PermissionsService,
        private readonly _iqserPermissionsService: IqserPermissionsService,
        private readonly _activeDossiersService: ActiveDossiersService,
        private readonly _fileManagementService: FileManagementService,
        private readonly _userPreferenceService: UserPreferenceService,
        readonly fileAttributesService: FileAttributesService,
        @Optional() private readonly _documentInfoService: DocumentInfoService,
        @Optional() private readonly _excludedPagesService: ExcludedPagesService,
    ) {}

    @HostBinding('class.keep-visible')
    get expanded() {
        return !!this._expandableActionsComponent?.expanded;
    }

    private get _toggleTooltip(): string {
        if (!this.canToggleAnalysis) {
            return _('file-preview.toggle-analysis.only-managers');
        }

        return this.file?.excluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable');
    }

    private get _buttons(): Action[] {
        const actions: Action[] = [
            {
                id: 'delete-file-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#openDeleteFileDialog(),
                tooltip: _('dossier-overview.delete.action'),
                icon: 'iqser:trash',
                show: this.showDelete,
                helpModeKey: 'delete_file',
            },
            {
                id: 'assign-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#assign(),
                tooltip: this.assignTooltip,
                icon: 'red:assign',
                show: this.showAssign,
                helpModeKey: 'assign_user',
            },
            {
                id: 'assign-to-me-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#assignToMe(),
                tooltip: _('dossier-overview.assign-me'),
                icon: 'red:assign-me',
                show: this.showAssignToSelf,
                helpModeKey: 'assign_user',
            },
            {
                id: 'open-import-redactions-dialog-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#openImportRedactionsDialog(),
                tooltip: _('dossier-overview.import-redactions'),
                icon: 'red:import_redactions',
                show: this.showImportRedactions && !this._iqserPermissionsService.has(Roles.getRss),
            },
            {
                id: 'download-file-btn',
                type: ActionTypes.downloadBtn,
                files: [this.file],
                dossier: this.dossier,
                tooltipClass: 'small',
                show: this._permissionsService.canDownloadRedactedFile() && !!this.file.lastProcessed,
                disabled: this.file.processingStatus === ProcessingFileStatuses.ERROR,
                helpModeKey: 'download',
            },
            {
                id: 'toggle-document-info-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#toggleDocumentInfo(),
                tooltip: _('file-preview.document-info'),
                ariaExpanded: toObservable(this._documentInfoService?.shown, { injector: this._injector }),
                icon: 'red:status-info',
                show: !!this._documentInfoService,
                helpModeKey: 'document_info',
            },
            {
                id: 'toggle-exclude-pages-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#toggleExcludePages(),
                tooltip: _('file-preview.exclude-pages'),
                ariaExpanded: toObservable(this._excludedPagesService?.shown, { injector: this._injector }),
                showDot: !!this.file.excludedPages?.length,
                icon: 'red:exclude-pages',
                show: !!this._excludedPagesService && this._permissionsService.canExcludePages(this.file, this.dossier),
                helpModeKey: 'exclude_pages',
            },
            {
                id: 'set-file-to-new-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#setToNew(),
                tooltip: _('dossier-overview.back-to-new'),
                icon: 'red:undo',
                show: this.showSetToNew,
                helpModeKey: 'change_status',
            },
            {
                id: 'set-file-under-approval-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#setFileUnderApproval(),
                tooltip: _('dossier-overview.under-approval'),
                icon: 'red:ready-for-approval',
                show: this.showUnderApproval,
                helpModeKey: 'change_status',
            },
            {
                id: 'set-file-under-review-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#setFileUnderReview(),
                tooltip: _('dossier-overview.under-review'),
                icon: 'red:undo',
                show: this.showUnderReview,
                helpModeKey: 'change_status',
            },
            {
                id: 'set-file-approved-btn',
                type: ActionTypes.circleBtn,
                action: () => this.setFileApproved(),
                tooltip: this.file.canBeApproved ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'),
                icon: 'red:approved',
                disabled: !this.file.canBeApproved,
                show: this.showApprove,
                helpModeKey: 'change_status',
            },
            {
                id: 'toggle-automatic-analysis-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#toggleAutomaticAnalysis(),
                tooltip: _('dossier-overview.stop-auto-analysis'),
                icon: 'red:disable-analysis',
                show: this.canDisableAutoAnalysis,
                helpModeKey: 'stop_analysis',
            },
            {
                id: 'reanalyse-file-preview-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#reanalyseFile(),
                tooltip: _('file-preview.reanalyse-notification'),
                tooltipClass: 'small',
                icon: 'iqser:refresh',
                show: this.showReanalyseFilePreview,
                disabled: this.file.isProcessing,
                helpModeKey: 'stop_analysis',
            },
            {
                id: 'toggle-automatic-analysis-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#toggleAutomaticAnalysis(),
                tooltip: _('dossier-overview.start-auto-analysis'),
                buttonType: this.isFilePreview ? CircleButtonTypes.warn : CircleButtonTypes.default,
                icon: 'red:enable-analysis',
                show: this.canEnableAutoAnalysis,
                helpModeKey: 'stop_analysis',
            },
            {
                id: 'set-under-approval-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#setFileUnderApproval(),
                tooltip: _('dossier-overview.under-approval'),
                icon: 'red:undo',
                show: this.showUndoApproval,
                helpModeKey: 'change_status',
            },
            {
                id: 'ocr-file-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#ocrFile(),
                tooltip: _('dossier-overview.ocr-file'),
                icon: 'iqser:ocr',
                show: this.showOCR,
            },
            {
                id: 'reanalyse-file-btn',
                type: ActionTypes.circleBtn,
                action: () => this.#reanalyseFile(),
                tooltip: _('dossier-overview.reanalyse.action'),
                icon: 'iqser:refresh',
                show: this.showReanalyseDossierOverview,
                helpModeKey: 'stop_analysis',
            },
            {
                id: 'toggle-analysis-btn',
                type: ActionTypes.toggle,
                action: () => this.#toggleAnalysis(),
                disabled: !this.canToggleAnalysis,
                tooltip: this.toggleTooltip,
                class: { 'mr-24': this.isDossierOverviewList },
                checked: !this.file.excluded,
                show: this.showToggleAnalysis,
                helpModeKey: 'disable_extraction',
            },
        ];

        return actions.filter(btn => btn.show);
    }

    ngOnChanges() {
        this.#setup();
    }

    async setFileApproved() {
        if (!this.file.analysisRequired && !this.file.hasUpdates) {
            await this.#setFileApproved();
            return;
        }

        const data: IConfirmationDialogData = {
            title: this.file.analysisRequired
                ? _('confirmation-dialog.approve-file-without-analysis.title')
                : _('confirmation-dialog.approve-file.title'),
            question: this.file.analysisRequired
                ? _('confirmation-dialog.approve-file-without-analysis.question')
                : _('confirmation-dialog.approve-file.question'),
            confirmationText: this.file.analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.confirmationText') : null,
            denyText: this.file.analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.denyText') : null,
        };

        this._dialogService.openDialog('confirm', data, () => this.#setFileApproved());
    }

    forceReanalysisAction($event: LongPressEvent) {
        this.analysisForced = !$event.touchEnd && this._userPreferenceService.isIqserDevMode;
        this.#setup();
    }

    #showOCRConfirmationDialog(): Observable<boolean> {
        const data: IConfirmationDialogData = {
            title: _('ocr.confirmation-dialog.title'),
            question: _('ocr.confirmation-dialog.question'),
            denyText: _('ocr.confirmation-dialog.cancel'),
        };

        const ref = this._dialogService.openDialog('confirm', data);
        return ref.afterClosed();
    }

    #openImportRedactionsDialog() {
        this._dialogService.openDialog('importRedactions', { dossierId: this.file.dossierId, fileId: this.file.fileId });
    }

    #openDeleteFileDialog() {
        this._dialogService.openDialog(
            'confirm',
            {
                title: _('confirmation-dialog.delete-file.title'),
                question: _('confirmation-dialog.delete-file.question'),
            } as IConfirmationDialogData,
            async () => {
                this._loadingService.start();
                try {
                    const dossier = this._activeDossiersService.find(this.file.dossierId);
                    await firstValueFrom(this._fileManagementService.delete([this.file], this.file.dossierId));
                    await this._injector.get(Router).navigate([`/${this._tenantsService.activeTenantId}${dossier.routerLink}`]);
                } catch (error) {
                    this._injector.get(Toaster).error(_('error.http.generic'), { params: error });
                }
                this._loadingService.stop();
            },
        );
    }

    #assign() {
        const files = [this.file];
        const targetStatus = this.file.workflowStatus;
        const withCurrentUserAsDefault = true;
        const withUnassignedOption = true;
        this._iqserDialog.openDefault(AssignReviewerApproverDialogComponent, {
            data: {
                targetStatus,
                files,
                withCurrentUserAsDefault,
                withUnassignedOption,
            },
        });
    }

    async #assignToMe() {
        await this._fileAssignService.assignToMe([this.file]);
    }

    async #reanalyseFile() {
        const params: ReanalyzeQueryParams = {
            force: true,
            triggeredByUser: true,
        };
        await this._reanalysisService.reanalyzeFilesForDossier([this.file], this.file.dossierId, params);
    }

    async #toggleAutomaticAnalysis() {
        this._loadingService.start();
        await firstValueFrom(this._reanalysisService.toggleAutomaticAnalysis(this.file.dossierId, [this.file]));
        this._loadingService.stop();
    }

    async #setFileUnderApproval() {
        await this._fileAssignService.assignApprover(this.file, true);
    }

    async #ocrFile() {
        if (this.file.lastManualChangeDate) {
            const confirm = await firstValueFrom(this.#showOCRConfirmationDialog());
            if (!confirm) {
                return;
            }
        }

        const pageRotationService = this._injector.get(PageRotationService);
        await firstValueFrom(pageRotationService.showConfirmationDialogIfHasRotations());
        const viewerHeaderService = this._injector.get(ViewerHeaderService);
        viewerHeaderService.disable(ROTATION_ACTION_BUTTONS);

        this._loadingService.start();
        await this._reanalysisService.ocrFiles([this.file], this.file.dossierId);
        this._loadingService.stop();
    }

    async #setFileUnderReview() {
        await this._fileAssignService.assignReviewer(this.file, true);
    }

    async #toggleAnalysis() {
        this._loadingService.start();
        await this._reanalysisService.toggleAnalysis(this.file.dossierId, [this.file], !this.file.excluded);
        this._loadingService.stop();
    }

    #setup() {
        this.isDossierOverviewList = this.type === 'dossier-overview-list';
        this.isDossierOverviewWorkflow = this.type === 'dossier-overview-workflow';
        this.isDossierOverview = this.type.startsWith('dossier-overview');
        this.isFilePreview = this.type === 'file-preview';

        this.assignTooltip = this.file.isUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer');
        this.showAssign =
            (this._permissionsService.canAssignUser(this.file, this.dossier) ||
                this._permissionsService.canUnassignUser(this.file, this.dossier)) &&
            this.isDossierOverview;

        this.showAssignToSelf = this._permissionsService.canAssignToSelf(this.file, this.dossier) && this.isDossierOverview;
        this.showImportRedactions = this._permissionsService.canImportRedactions(this.file, this.dossier);

        this.showSetToNew = this._permissionsService.canSetToNew(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
        this.showUndoApproval = this._permissionsService.canUndoApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
        this.showUnderReview = this._permissionsService.canSetUnderReview(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
        this.showUnderApproval = this._permissionsService.canSetUnderApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
        this.showApprove = this._permissionsService.isReadyForApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;

        this.canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.file, this.dossier);
        this.showToggleAnalysis = !!this.file.lastProcessed && this._permissionsService.showToggleAnalysis(this.dossier);
        this.toggleTooltip = this._toggleTooltip;

        this.showDelete = this._permissionsService.canSoftDeleteFile(this.file, this.dossier);
        this.showOCR = this._permissionsService.canOcrFile(this.file, this.dossier);
        this.canReanalyse = this._permissionsService.canReanalyseFile(this.file, this.dossier);
        this.canDisableAutoAnalysis = !this.#isDocumine && this._permissionsService.canDisableAutoAnalysis([this.file], this.dossier);
        this.canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis([this.file], this.dossier);

        this.showStatusBar = !this.file.isError && !this.file.isUnprocessed && this.isDossierOverviewList;

        const showReanalyse = this.canReanalyse || this.file.excludedFromAutomaticAnalysis || this.analysisForced;

        this.showReanalyseFilePreview = showReanalyse && this.isFilePreview && !this.file.isApproved;
        this.showReanalyseDossierOverview = showReanalyse && this.isDossierOverview && !this.file.isApproved;

        this.buttons = this._buttons;

        this._changeRef.markForCheck();
    }

    async #setFileApproved() {
        this._loadingService.start();
        await this._filesService.setApproved(this.file);
        this._loadingService.stop();
    }

    async #setToNew() {
        this._loadingService.start();
        await this._filesService.setToNew(this.file);
        this._loadingService.stop();
    }

    #toggleExcludePages() {
        this._excludedPagesService.toggle();
        const shown = this._excludedPagesService.shown();
        setLocalStorageDataByFileId(this.file.id, 'show-exclude-pages', shown);
        if (shown) {
            setLocalStorageDataByFileId(this.file.id, 'show-document-info', false);
        }
    }

    #toggleDocumentInfo() {
        this._documentInfoService.toggle();
        const shown = this._documentInfoService.shown();
        setLocalStorageDataByFileId(this.file.id, 'show-document-info', shown);
        if (shown) {
            setLocalStorageDataByFileId(this.file.id, 'show-exclude-pages', false);
        }
    }
}
