import { SelectOption } from '@ui/select/select-option.model';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { SignalRequest, SignalRequestOmfattning, SignalRequestType } from '@msfa-models/api/signal.request.model';
import { DeltagareAvrop } from '@msfa-models/avrop.model';
import { CustomError } from '@msfa-models/error/custom-error';
import { formatDate } from '@msfa-utils/format-to-date.util';
import { Radiobutton } from '@ui/radiobutton-group/radiobutton.model';
import { add } from 'date-fns';
import { BehaviorSubject, Observable } from 'rxjs';
import { map, shareReplay, switchMap, take } from 'rxjs/operators';
import { SignalFormData, SignalFormKeys, SignalOmfattning, SignalType } from './signal-form.model';
import { SignalFormService } from './signal-form.service';
import { SignalFormValidator } from './signal-form.validator';

@Component({
  selector: 'msfa-signal-form',
  templateUrl: './signal-form.component.html',
  styleUrls: ['./signal-form.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SignalFormComponent {
  readonly typeFormName: SignalFormKeys = 'type';
  readonly omfattningFormName: SignalFormKeys = 'omfattning';
  readonly percentFormName: SignalFormKeys = 'percent';
  readonly startDateFormName: SignalFormKeys = 'startDate';

  shouldValidate$ = new BehaviorSubject<boolean>(false);
  confirmDialogOpen$ = new BehaviorSubject<boolean>(false);
  signalFormGroup = new FormGroup(
    {
      type: new FormControl(null),
      omfattning: new FormControl(SignalOmfattning.Heltid),
      percent: new FormControl(50),
      startDate: new FormControl(new Date()),
    },
    [SignalFormValidator.isSignalValid()]
  );
  submitLoading$ = new BehaviorSubject<boolean>(false);
  lastSubmittedSignal$ = new BehaviorSubject<Date>(null);
  error$ = new BehaviorSubject<CustomError>(null);

  currentGenomforandeReferens$: Observable<number> = this.activatedRoute.params.pipe(
    map(params => +params.genomforandeReferens)
  );
  avrop$: Observable<DeltagareAvrop> = this.currentGenomforandeReferens$.pipe(
    switchMap(genomforandeReferens => this.signalFormService.fetchAvropInformation$(genomforandeReferens)),
    shareReplay(1)
  );

  typeSelectItems: SelectOption[] = [
    { name: 'Arbete', value: SignalType.Arbete },
    { name: 'Utbildning', value: SignalType.Utbildning },
  ];

  omfattningRadioButtons: Radiobutton[] = [
    { label: 'Heltid', value: SignalOmfattning.Heltid },
    { label: 'Deltid', value: SignalOmfattning.Deltid },
  ];

  constructor(private signalFormService: SignalFormService, private activatedRoute: ActivatedRoute) {}

  convertTypeValueToLabel(type: SignalType): string {
    return this.typeSelectItems?.find(selectItem => selectItem.value === type)?.name;
  }
  convertOmfattningValueToLabel(type: SignalOmfattning): string {
    return this.omfattningRadioButtons?.find(radiobuttons => radiobuttons.value === type)?.label;
  }

  get formErrors(): { [key: string]: string } {
    return this.signalFormGroup.errors || {};
  }

  get typeFormControl(): FormControl {
    return this.signalFormGroup.get(this.typeFormName) as FormControl;
  }
  get omfattningFormControl(): FormControl {
    return this.signalFormGroup.get(this.omfattningFormName) as FormControl;
  }
  get percentFormControl(): FormControl {
    return this.signalFormGroup.get(this.percentFormName) as FormControl;
  }
  get startDateFormControl(): FormControl {
    return this.signalFormGroup.get(this.startDateFormName) as FormControl;
  }

  get showPercentFormControl(): boolean {
    return this.omfattningFormControl.value === SignalOmfattning.Deltid;
  }

  get startDateFormValueAsDate(): Date {
    return new Date(this.startDateFormControl.value);
  }

  formControlIsInvalid(formControlName: string): boolean {
    return this.formErrors[formControlName] && this.shouldValidate$.getValue();
  }

  getMaxDate(startDate: Date): Date {
    return add(new Date(startDate), { months: 10, days: 1 });
  }

  openConfirmDialog(): void {
    this.shouldValidate$.next(true);
    if (this.signalFormGroup.invalid) {
      return;
    }

    this.confirmDialogOpen$.next(true);
  }

  cancelConfirmDialog(): void {
    this.confirmDialogOpen$.next(false);
    this.error$.next(null);
  }

  private typeToRequest(type: string): SignalRequestType {
    switch (type) {
      case SignalType.Arbete:
        return SignalRequestType.Work;
      case SignalType.Utbildning:
        return SignalRequestType.Education;
      default:
        return;
    }
  }
  private omfattningToRequest(omfattning: string): SignalRequestOmfattning {
    switch (omfattning) {
      case 'heltid':
        return SignalRequestOmfattning.Heltid;
      case 'deltid':
        return SignalRequestOmfattning.Deltid;
      default:
        return;
    }
  }

  private _formDataToRequest(genomforandereferens: number, formData: SignalFormData): SignalRequest {
    const { type, omfattning, startDate, percent } = formData;

    const requestType: SignalRequestType = this.typeToRequest(type);
    const requestOmfattning: SignalRequestOmfattning = this.omfattningToRequest(omfattning);

    return {
      genomforandereferens,
      type: requestType,
      omfattning: requestOmfattning,
      omfattningPercent: requestOmfattning === SignalRequestOmfattning.Deltid ? percent : null,
      startDate: formatDate(startDate),
    };
  }

  submitAndCloseConfirmDialog(genomforandereferens: number): void {
    this.submitLoading$.next(true);

    const postRequest = this._formDataToRequest(genomforandereferens, this.signalFormGroup.value as SignalFormData);

    this.signalFormService
      .postSignal$(postRequest)
      .pipe(take(1))
      .subscribe({
        next: () => {
          this.lastSubmittedSignal$.next(new Date());
          this.submitLoading$.next(false);
          this.confirmDialogOpen$.next(false);
        },
        error: (customError: CustomError) => {
          this.error$.next({ ...customError, message: customError.error.message });
          this.submitLoading$.next(false);
          throw { ...customError, avoidToast: true };
        },
      });
  }
}
