import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { UserService } from '@users/user.service';
import { IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { FormBuilder, Validators } from '@angular/forms';
import { File, User, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { FilesService } from '@services/files/files.service';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { PermissionsService } from '@services/permissions.service';
import { moveElementInArray } from '@utils/functions';
import { getCurrentUser } from '@iqser/common-ui/lib/users';

class DialogData {
    targetStatus: WorkflowFileStatus;
    files: File[];
    ignoreChanged?: boolean;
    withUnassignedOption?: boolean;
    withCurrentUserAsDefault?: boolean;
}

@Component({
    templateUrl: './assign-reviewer-approver-dialog.component.html',
})
export class AssignReviewerApproverDialogComponent {
    readonly iconButtonTypes = IconButtonTypes;
    readonly currentUser = getCurrentUser<User>();
    readonly mode = this.#mode;
    readonly dossier = this._activeDossiersService.find(this.data.files[0].dossierId);
    readonly userOptions = this.#userOptions;
    readonly form = this.#form;

    constructor(
        readonly userService: UserService,
        private readonly _toaster: Toaster,
        private readonly _formBuilder: FormBuilder,
        private readonly _activeDossiersService: ActiveDossiersService,
        private readonly _filesService: FilesService,
        private readonly _loadingService: LoadingService,
        readonly permissionsService: PermissionsService,
        private readonly _dialogRef: MatDialogRef<AssignReviewerApproverDialogComponent, boolean>,
        @Inject(MAT_DIALOG_DATA) readonly data: DialogData,
    ) {}

    get selectedUser(): string {
        const value = this.form.controls.user.value;
        return value === 'undefined' ? undefined : value;
    }

    get changed(): boolean {
        if (this.data.ignoreChanged) {
            return true;
        }

        const selectedUser = this.selectedUser;
        for (const file of this.data.files) {
            if (file.assignee !== selectedUser) {
                return true;
            }
        }

        return false;
    }

    get #mode() {
        const isUnderApproval = this.data.targetStatus === WorkflowFileStatuses.UNDER_APPROVAL;
        const isApproved = this.data.targetStatus === WorkflowFileStatuses.APPROVED;
        return isUnderApproval || isApproved ? 'approver' : 'reviewer';
    }

    get #userOptions() {
        const unassignUser = this.#canUnassignUser && this.data.withUnassignedOption ? ['undefined'] : [];
        const cannotAssignUser = !this.permissionsService.canAssignUser(this.data.files, this.dossier);

        if (this.mode === 'reviewer') {
            if (this.dossier.hasReviewers && cannotAssignUser) {
                return [...unassignUser];
            }

            return this.#customSort([...this.dossier.memberIds, ...unassignUser]);
        }

        if (this.dossier.approverIds.length > 1 && cannotAssignUser) {
            return [...unassignUser];
        }

        return this.#customSort([...this.dossier.approverIds, ...unassignUser]);
    }

    get #canUnassignUser() {
        return this.permissionsService.canUnassignUser(this.data.files, this.dossier);
    }

    get #user(): string {
        if (this.data.files.every(file => !file.assignee)) {
            return null;
        }
        return this.data.files.length === 1 ? this.data.files[0].assignee : this.currentUser.id;
    }

    get #form() {
        const user = this.#user;
        return this._formBuilder.group({
            // Allow a null reviewer if a previous reviewer exists (= it's not the first assignment) & current user is allowed to unassign
            user: [user, this.#canUnassignUser && !user ? Validators.required : null],
        });
    }

    async save() {
        this._loadingService.start();
        const selectedUser = this.selectedUser;

        try {
            if (!selectedUser || this.data.targetStatus === WorkflowFileStatuses.APPROVED) {
                await this._filesService.setAssignee(this.data.files, selectedUser);
            } else if (this.mode === 'reviewer') {
                await this._filesService.setReviewer(this.data.files, selectedUser);
            } else {
                await this._filesService.setUnderApproval(this.data.files, selectedUser);
            }
        } catch (error) {
            this._toaster.error(_('error.http.generic'), { params: error });
        }

        this._loadingService.stop();
        this._dialogRef.close(true);
    }

    #customSort(ids: string[]) {
        let sorted = ids.sort((a, b) => this.userService.getName(a).localeCompare(this.userService.getName(b)));

        sorted = moveElementInArray(sorted, this.currentUser.id, 0);

        if (sorted.includes('undefined')) {
            sorted = moveElementInArray(sorted, 'undefined', 1);
        }

        return sorted;
    }
}
