import { Component, OnInit, Optional } from '@angular/core';
import { IUserModel } from '@fleio-api/client-user/model/user.model';
import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, Validators } from '@angular/forms';
import { BehaviorSubject, EMPTY, Observable, of } from 'rxjs';
import { IActionResult } from '@objects-view/interfaces/actions/action-result';
import { Router } from '@angular/router';
import { ConfigService } from '@shared/config/config.service';
import { UsersApiService } from '@fleio-api/client-user/user/users-api.service';
import { DetailsFormBase } from '@objects-view/details-form-base';
import { PanelLayoutComponent } from '@shared/layout/panel-layout/panel-layout.component';
import { FleioId } from '@fleio-api/base-model/base-fleio-object.model';
import { IIcon } from '@shared/ui/common/interfaces/icon';
import { IUserCreateOptionsModel } from '@fleio-api/client-user/model/user-create-options.model';

@Component({
  selector: 'app-user-edit-form',
  templateUrl: './user-edit-form.component.html',
  styleUrls: ['./user-edit-form.component.scss']
})
export class UserEditFormComponent extends DetailsFormBase<IUserModel> implements OnInit {
  createOptions: IUserCreateOptionsModel;
  country: UntypedFormControl = new UntypedFormControl('', Validators.required);

  userForm = this.formBuilder.group({
    first_name: ['', Validators.required],
    last_name: ['', Validators.required],
    email: ['', Validators.required],
    external_billing_id: [''],
    password: ['', Validators.required],
    is_active: [true, Validators.required],
    email_verified: [false, Validators.required],
  });
  passwordCtrl = this.userForm.controls.password;
  email = this.userForm.controls.email;
  isStaffPanel = false;
  editStaffTicketNotificationsSettings = false;
  isActiveInfoIcon = {
    name: 'info',
    tooltip: $localize`Only active users receive notifications.`,
    verticalAlign: 'middle',
    marginLeft: '8px'
  } as IIcon;
  userSaveBS: BehaviorSubject<FleioId> = new BehaviorSubject<FleioId>(null);
  public readonly observableUserSave: Observable<FleioId> = this.userSaveBS.asObservable();

  constructor(
    private formBuilder: UntypedFormBuilder, private usersApi: UsersApiService, private router: Router,
    private config: ConfigService,
    @Optional() public panelLayout?: PanelLayoutComponent,
  ) {
    super();
  }

  ngOnInit() {
    if (this.objectController) {
      this.createOptions = this.objectController.additionalObjects?.createOptions;
      this.objectController.actionCallback = () => this.saveUser();
    }
    this.isStaffPanel = this.authSvc.feature('ui.staff');
    this.editStaffTicketNotificationsSettings = (
      this.object && this.object.is_staff && this.authSvc.feature('plugins.tickets') && this.isStaffPanel
    );

    if (this.isStaffPanel) {
      this.userForm.addControl('is_superuser', this.formBuilder.control([false]));
      this.userForm.controls.is_superuser.setValue(false);
      this.userForm.addControl('is_staff', this.formBuilder.control([false]));
      this.userForm.controls.is_staff.setValue(false);
      this.userForm.get('is_superuser').valueChanges.subscribe(isSuperuserValue => {
        if (isSuperuserValue === true) {
          this.userForm.controls.is_staff.setValue(true);
          this.userForm.controls.is_staff.disable();
        } else {
          this.userForm.controls.is_staff.enable();
        }
      });
    }

    if (this.object) {
      this.userForm.patchValue(this.object);
      if (this.object.id) {
        this.userForm.controls.password.clearValidators();
        if (this.object.is_staff) {
          this.setStaffNotificationSettingsControls();
        }
      }
      if (this.isStaffPanel) {
        this.userForm.controls.is_staff.valueChanges.subscribe(value => {
          if (value) {
            this.editStaffTicketNotificationsSettings = (
              this.object && this.authSvc.feature('plugins.tickets')
            );
            this.setStaffNotificationSettingsControls();
          } else {
            this.editStaffTicketNotificationsSettings = false;
            this.userForm.removeControl('staff_notification_settings');
          }
        });
      }
    }
  }

  private setStaffNotificationSettingsControls() {
    if (this.userForm.contains('staff_notification_settings')) {
      return;
    }
    this.userForm.addControl('staff_notification_settings', this.formBuilder.array([]));
    const staffNotifSettings = this.userForm.get('staff_notification_settings') as UntypedFormArray;
    if (this.object?.id) {
      if (this.object.staff_notifications) {
        for (const notificationName of Object.keys(this.object.staff_notifications)) {
          staffNotifSettings.push(
            this.formBuilder.group({
              name: [notificationName],
              enabled: [this.object.staff_notifications[notificationName].enabled],
              title: [this.object.staff_notifications[notificationName].title],
            })
          );
        }
        return;
      }
    }
    // new user, or edited user was not staff and did not have staff notifications set,
    // fallback to list from create options
    for (const notificationName of Object.keys(this.createOptions.staff_notification_settings)) {
      staffNotifSettings.push(
        this.formBuilder.group({
          name: [notificationName],
          enabled: [this.createOptions.staff_notification_settings[notificationName].enabled],
          title: [this.createOptions.staff_notification_settings[notificationName].title],
        })
      );
    }
  }

  onUserSave(router: Router, config: ConfigService) {
    router.navigateByUrl(config.getPrevUrl('clients-users/users')).catch(() => {
    });
  }

  private saveUser(): Observable<IActionResult> {
    const value = this.userForm.getRawValue() as IUserModel;
    this.validate();
    if (this.formGroup.invalid) {
      this.displayControlErrors();
      return EMPTY;
    }

    if (!value.password) {
      delete value.password;
    }

    let request;

    if (this.object.id) {
      value.id = this.object.id;
      request = this.usersApi.update(value.id, value);
    } else {
      request = this.usersApi.create(value);
    }

    this.objectController.loading = true;
    request.subscribe((response) => {
      if (this.editStaffTicketNotificationsSettings) {
        this.userSaveBS.next(response.id);
      } else {
        this.onUserSave(this.router, this.config);
      }
    }, (error) => {
      this.objectController.loading = false;
      this.setErrors(error.error);
    });

    return of(null);
  }
}
