import { Component, OnDestroy, OnInit } from '@angular/core';
import { SettingsDataService } from 'src/app/modules/admin/administration/settings/settings.data.service';
import { Setting } from 'src/app/model/entities/setting';
import { SpinnerService } from 'src/app/service/spinner.service';
import { catchError, takeUntil } from 'rxjs/operators';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { Subject } from 'rxjs';
import { AuthService } from 'src/app/service/auth.service';
import { PermissionsEnum } from 'src/app/model/auth/permissionsEnum';

@Component({
  selector: 'app-settings',
  templateUrl: './settings.page.html',
  styleUrl: './settings.page.scss',
})
export class SettingsPage implements OnInit, OnDestroy {
  settings: Setting[] = [];
  settingsForm: FormGroup = this.fb.group({});

  get hasChanges(): boolean {
    return !this.settingsForm.pristine;
  }

  protected unsubscribe$ = new Subject<void>();

  constructor(
    private spinner: SpinnerService,
    private data: SettingsDataService,
    private fb: FormBuilder,
    private auth: AuthService
  ) {}

  async ngOnInit() {
    const isAllowed = await this.auth.hasAnyPermissionLazy([
      PermissionsEnum.settings,
    ]);
    if (!isAllowed) {
      throw new Error('Unauthorized');
    }

    this.data
      .onUpdate()
      .pipe(takeUntil(this.unsubscribe$))
      .subscribe(() => {
        this.load();
      });

    this.spinner.show();
    this.load();
  }

  ngOnDestroy(): void {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }

  load() {
    this.settingsForm = this.fb.group({});
    this.data
      .load()
      .pipe(
        catchError(err => {
          this.spinner.hide();
          throw err;
        })
      )
      .subscribe(settings => {
        this.settings = settings;
        this.settings.forEach(setting => {
          this.settingsForm.addControl(
            setting.key,
            new FormControl(setting.value)
          );
        });
        this.spinner.hide();
      });
  }

  async save() {
    const isAllowed = await this.auth.hasAnyPermissionLazy([
      PermissionsEnum.settingsUpdate,
    ]);
    if (!isAllowed) {
      throw new Error('Unauthorized');
    }

    if (this.settingsForm.pristine) {
      return;
    }

    const updatedSettings: Setting[] = this.settings
      .filter(x => this.settingsForm.get(x.key)?.dirty)
      .map(setting => ({
        key: setting.key,
        value: this.settingsForm.get(setting.key)?.value,
      }));

    for (const setting of updatedSettings) {
      this.spinner.show();
      this.data
        .change(setting)
        .pipe(
          catchError(err => {
            this.spinner.hide();
            throw err;
          })
        )
        .subscribe(() => this.spinner.hide());
    }
  }
}
