import { NgIf } from '@angular/common';
import { Component, computed, HostListener, inject, NgZone, OnDestroy, OnInit } from '@angular/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { StatusBarComponent } from '@common-ui/shared';
import { Bind } from '@common-ui/utils';
import { CircleButtonComponent, LoadingService, StopPropagationDirective, Toaster } from '@iqser/common-ui';
import { getCurrentUser, InitialsAvatarComponent } from '@iqser/common-ui/lib/users';
import { TranslateModule } from '@ngx-translate/core';
import { File, User } from '@red/domain';
import { FilesService } from '@services/files/files.service';
import { PermissionsService } from '@services/permissions.service';
import { AssignUserDropdownComponent } from '@shared/components/assign-user-dropdown/assign-user-dropdown.component';
import { workflowFileStatusTranslations } from '@translations/file-status-translations';
import { UserService } from '@users/user.service';
import { moveElementInArray } from '@utils/functions';
import { PdfViewer } from '../../../pdf-viewer/services/pdf-viewer.service';
import { FileAssignService } from '../../../shared-dossiers/services/file-assign.service';
import { FileDataService } from '../../services/file-data.service';
import { FilePreviewStateService } from '../../services/file-preview-state.service';

@Component({
    selector: 'redaction-user-management',
    templateUrl: './user-management.component.html',
    styleUrls: ['./user-management.component.scss'],
    standalone: true,
    imports: [
        AssignUserDropdownComponent,
        NgIf,
        StopPropagationDirective,
        InitialsAvatarComponent,
        StatusBarComponent,
        TranslateModule,
        CircleButtonComponent,
    ],
})
export class UserManagementComponent implements OnInit, OnDestroy {
    protected readonly _canAssignToSelf = computed(() => this.permissionsService.canAssignToSelf(this.state.file(), this.state.dossier()));
    protected readonly _canAssignUser = computed(() => this.permissionsService.canAssignUser(this.state.file(), this.state.dossier()));
    protected readonly _canUnassignUser = computed(() => this.permissionsService.canUnassignUser(this.state.file(), this.state.dossier()));
    protected readonly _canAssignOrUnassign = computed(() => this._canAssignUser() || this._canUnassignUser());
    protected readonly _canAssign = computed(() => this._canAssignToSelf() || this._canAssignOrUnassign());
    protected readonly _canAssignReviewer = computed(() => this._canAssignUser() && !this.state.file().assignee);
    protected readonly _usersOptions = computed(() => {
        const file = this.state.file();
        const dossier = this.state.dossier();
        const canUnassignUser = this._canUnassignUser();
        const unassignUser = canUnassignUser && file.assignee ? [undefined] : [];
        return file.isUnderApproval
            ? this.#customSort([...dossier.approverIds, ...unassignUser])
            : this.#customSort([...dossier.memberIds, ...unassignUser]);
    });
    protected readonly _currentUserId = getCurrentUser().id;
    protected readonly fileDataService = inject(FileDataService);
    readonly translations = workflowFileStatusTranslations;
    readonly statusBarConfig = computed(() => [{ length: 1, color: this.state.file().workflowStatus }]);
    readonly assignTooltip = computed(() => {
        const file = this.state.file();
        return file.isUnderApproval
            ? _('dossier-overview.assign-approver')
            : file.assignee
              ? _('file-preview.change-reviewer')
              : _('file-preview.assign-reviewer');
    });

    constructor(
        readonly fileAssignService: FileAssignService,
        readonly permissionsService: PermissionsService,
        readonly userService: UserService,
        readonly filesService: FilesService,
        readonly toaster: Toaster,
        readonly loadingService: LoadingService,
        readonly state: FilePreviewStateService,
        readonly pdf: PdfViewer,
        readonly ngZone: NgZone,
    ) {}

    async assignToMe(file: File) {
        await this.fileAssignService.assignToMe([file]);
        //TODO: check which one to call
        // await firstValueFrom(this.fileDataService.updateAnnotations(file, file.numberOfAnalyses));
        await this.fileDataService.loadEntityLog();
    }

    async assignReviewer(file: File, user: User | string) {
        const assigneeId = typeof user === 'string' ? user : user?.id;

        this.loadingService.start();

        if (!assigneeId || file.isApproved) {
            await this.filesService.setAssignee(file, assigneeId);
        } else if (file.isNew || file.isUnderReview) {
            await this.filesService.setReviewer(file, assigneeId);
        } else {
            await this.filesService.setUnderApproval(file, assigneeId);
        }

        if (assigneeId === this._currentUserId) {
            // await firstValueFrom(this.fileDataService.updateAnnotations(file, file.numberOfAnalyses));
            await this.fileDataService.loadEntityLog();
        }

        this.loadingService.stop();

        const translateParams = { reviewerName: this.userService.getName(assigneeId), filename: file.filename };
        this.toaster.success(_('assignment.reviewer'), { params: translateParams });
        this.state.isEditingReviewer.set(false);
    }

    ngOnInit() {
        this.pdf.instance.UI.iframeWindow.document.addEventListener('click', this.handleViewerClick);
    }

    ngOnDestroy() {
        this.pdf.instance.UI.iframeWindow.document.removeEventListener('click', this.handleViewerClick);
    }

    @Bind()
    handleViewerClick() {
        this.ngZone.run(() => {
            this.state.isEditingReviewer.set(false);
        });
    }

    @HostListener('document:click')
    clickOutside() {
        if (this.state.isEditingReviewer()) {
            this.state.isEditingReviewer.set(false);
        }
    }

    @HostListener('document:keyup', ['$event'])
    handleEsc($event: KeyboardEvent) {
        if ($event.key === 'Escape' && this.state.isEditingReviewer()) {
            this.state.isEditingReviewer.set(false);
        }
    }

    #customSort(ids: string[]) {
        let sorted = [...ids].sort((a, b) => this.userService.getName(a).localeCompare(this.userService.getName(b)));
        sorted = moveElementInArray(sorted, this._currentUserId, 0);
        if (sorted.includes(undefined)) {
            sorted = moveElementInArray(sorted, undefined, 1);
        }
        return sorted;
    }
}
