import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { AdminDialogService } from '../../../services/admin-dialog.service';
import { BaseFormComponent, LoadingService, Toaster } from '@iqser/common-ui';
import { rolesTranslations } from '@translations/roles-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { User } from '@red/domain';
import { UserService } from '@users/user.service';
import { HttpStatusCode } from '@angular/common/http';
import { firstValueFrom } from 'rxjs';
import { IProfileUpdateRequest } from '@iqser/common-ui/lib/users';

@Component({
    selector: 'redaction-user-details',
    templateUrl: './user-details.component.html',
    styleUrls: ['./user-details.component.scss'],
})
export class UserDetailsComponent extends BaseFormComponent implements OnChanges {
    /** e.g. a RED_ADMIN is automatically a RED_USER_ADMIN => can't disable RED_USER_ADMIN as long as RED_ADMIN is checked */
    private readonly _ROLE_REQUIREMENTS = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' };
    @Input() user: User;
    @Output() readonly toggleResetPassword = new EventEmitter();
    @Output() readonly closeDialog = new EventEmitter();
    @Output() readonly cancel = new EventEmitter();
    readonly ROLES = ['RED_USER', 'RED_MANAGER', 'RED_USER_ADMIN', 'RED_ADMIN'];
    readonly translations = rolesTranslations;

    constructor(
        private readonly _formBuilder: UntypedFormBuilder,
        private readonly _toaster: Toaster,
        private readonly _dialogService: AdminDialogService,
        private readonly _loadingService: LoadingService,
        private readonly _userService: UserService,
    ) {
        super();
    }

    get activeRoles(): string[] {
        return this.ROLES.reduce((acc, role) => {
            if (this.form.get(role).value) {
                acc.push(role);
            }
            return acc;
        }, []);
    }

    private get _rolesControls(): any {
        return this.ROLES.reduce(
            (prev, role) => ({
                ...prev,
                [role]: [
                    {
                        value: this.user && this.user.has(role),
                        disabled: this.shouldBeDisabled(role),
                    },
                ],
            }),
            {},
        );
    }

    ngOnChanges() {
        this.form = this._getForm();
        this.initialFormValue = this.form.getRawValue();
    }

    shouldBeDisabled(role: string): boolean {
        const isCurrentAdminUser = this.user && this.user.isAdmin && this.user.id === this._userService.currentUser.id;
        return (
            // RED_ADMIN can't remove own RED_ADMIN role
            (role === 'RED_ADMIN' && isCurrentAdminUser) ||
            // only RED_ADMINs can edit RED_ADMIN roles
            (role === 'RED_ADMIN' && !this._userService.currentUser.isAdmin) ||
            Object.keys(this._ROLE_REQUIREMENTS).reduce(
                (value, key) => value || (role === this._ROLE_REQUIREMENTS[key] && this.user?.roles.includes(key)),
                false,
            )
        );
    }

    async save() {
        this._loadingService.start();
        const userData: IProfileUpdateRequest = { ...this.form.getRawValue(), roles: this.activeRoles };

        if (!this.user) {
            await firstValueFrom(this._userService.create(userData))
                .then(() => {
                    this.closeDialog.emit(true);
                })
                .catch(error => {
                    if (error.status === HttpStatusCode.Conflict) {
                        this._toaster.error(_('add-edit-user.error.email-already-used'));
                    } else {
                        this._toaster.error(_('add-edit-user.error.generic'));
                    }
                    this._loadingService.stop();
                });
        } else {
            await firstValueFrom(this._userService.updateProfile(userData, this.user.id));
            this.closeDialog.emit(true);
        }
    }

    delete() {
        this._dialogService.deleteUsers([this.user.id], () => this.closeDialog.emit(true));
    }

    setRolesRequirements(checked: boolean, role: string): void {
        if (Object.keys(this._ROLE_REQUIREMENTS).includes(role)) {
            if (checked) {
                this.form.patchValue({ [this._ROLE_REQUIREMENTS[role]]: true });
                this.form.controls[this._ROLE_REQUIREMENTS[role]].disable();
            } else {
                this.form.controls[this._ROLE_REQUIREMENTS[role]].enable();
            }
        }
    }

    disabledDelete(user: User): boolean {
        const userAdmin = user.isAdmin;
        const currentUserAdmin = this._userService.currentUser.isAdmin;
        return user.id === this._userService.currentUser.id || (userAdmin && !currentUserAdmin);
    }

    private _getForm(): UntypedFormGroup {
        return this._formBuilder.group({
            firstName: [this.user?.firstName, Validators.required],
            lastName: [this.user?.lastName, Validators.required],
            email: [
                {
                    value: this.user?.email,
                    disabled: !!this.user?.email,
                },
                [Validators.required, Validators.email],
            ],
            ...this._rolesControls,
        });
    }
}
