import { RadiobuttonModel } from '@af/digi-ng/_form/form-radiobutton-group';
import { FormTextareaSize } from '@af/digi-ng/_form/form-textarea';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Alternative } from '@msfa-enums/alternative.enum';
import { ConfirmDialog } from '@msfa-enums/confirm-dialog.enum';
import { DayOrPartOfDay } from '@msfa-enums/day-or-part-of-day.enum';
import { FranvaroOrsaksKodEnum } from '@msfa-enums/franvaro-orsak-kod.enum';
import { KandaOrsakerEnum } from '@msfa-enums/kanda-orsaker-kod.enum';
import { ContactInformationCompact } from '@msfa-models/api/contact-information.response.model';
import { AvvikelseAlternativ } from '@msfa-models/avvikelse-alternativ.model';
import { Avvikelse } from '@msfa-models/avvikelse.model';
import { FragorForAvvikelser } from '@msfa-models/fragor-for-avvikelser.model';
import { FranvaroAlternativ } from '@msfa-models/franvaro-alternativ.model';
import { OrsaksKoderAvvikelse } from '@msfa-models/orsaks-koder-avvikelse.model';
import { KandaAvvikelseKoder, OrsaksKoderFranvaro } from '@msfa-models/orsaks-koder-franvaro.model';
import {
  AnnanKandOrsakeIsRequiredCheck,
  DateIsRequiredCheck,
  DayOrPartOfDayIsRequiredCheck,
  DescriptionIsRequiredCheck,
  EndTimeIsRequiredCheck,
  MotiveringIsRequiredCheck,
  OrsakerIsRequiredCheck,
  StartTimeIsRequiredCheck
} from '@msfa-utils/validators/avvikelse-form-validator';
import { RequiredValidator } from '@msfa-utils/validators/required.validator';
import { BehaviorSubject, Observable } from 'rxjs';
import { first, map, switchMap } from 'rxjs/operators';
import { DeltagareAvvikelseService } from '../../services/deltagare-avvikelse.service';
import { avvikelseAlternatives, dayOrPartOfDay } from './report-alternatives';

@Component({
  selector: 'msfa-deltagare-avvikelse',
  templateUrl: './deltagare-avvikelse.component.html',
  styleUrls: ['./deltagare-avvikelse.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class DeltagareAvvikelseComponent implements OnInit {
  readonly alternativeFormControlName = 'alternative';
  readonly descriptionFormControlName = 'description'
  readonly dateFormControlName = 'date';
  readonly dayOrPartOfDayFormControlName = 'dayOrPartOfDay';
  readonly orsakerFormControlName = 'orsaker'
  readonly andraKandaOrsakerFormControlName = 'andraKandaOrsaker';
  readonly fraga1FormControlName = 'fraga1';
  readonly fraga2FormControlName = 'fraga2';
  readonly startTimeFormControlName = 'startTime';
  readonly endTimeFormControlName = 'endTime';

  private _showSuccessNotification$ = new BehaviorSubject<boolean>(false);
  private _showDangerNotification$ = new BehaviorSubject<boolean>(false);

  contactInformation$: Observable<ContactInformationCompact> = this.activatedRoute.params
    .pipe(
      switchMap(({ deltagareId }) => this.deltagareAvvikelseService.getContactInformationCompact$(deltagareId))
    )
  franvaroOrsaker$: Observable<OrsaksKoderFranvaro[]>;
  avvikelseOrsaker$: Observable<OrsaksKoderAvvikelse[]>;
  andraKandaOrsaker$: Observable<KandaAvvikelseKoder[]>;
  fragor1$: Observable<FragorForAvvikelser[]>;
  fragor2$: Observable<FragorForAvvikelser[]>;
  contactInformation: ContactInformationCompact;
  sizeTextArea: FormTextareaSize.S;
  todayDate = new Date().toISOString().slice(0, 10);
  avvikelseAlternatives: RadiobuttonModel[] = avvikelseAlternatives;
  dayOrPartOfDay: RadiobuttonModel[] = dayOrPartOfDay;
  selectedOrsaksKod: string;
  avvikelseFormGroup: FormGroup | null = null;
  totalAmountOfSteps = 2;
  currentStep = 1;
  openConfirmDialog = false;
  showSuccessNotification$ = this._showSuccessNotification$.asObservable();
  showDangerNotification$ = this._showDangerNotification$.asObservable();

  constructor(
    private deltagareAvvikelseService: DeltagareAvvikelseService,
    private router: Router,
    private activatedRoute: ActivatedRoute) { }

  ngOnInit(): void {
    this.contactInformation$
      .pipe(
        first(),
      )
      .subscribe(contactInformation => {
        this.contactInformation = contactInformation;
      });

    this.avvikelseFormGroup = new FormGroup({
      alternative: new FormControl(null, [RequiredValidator()]),
      description: new FormControl(''),
      date: new FormControl(this.todayDate),
      dayOrPartOfDay: new FormControl(null),
      orsakerFormGroup: new FormGroup({
        orsaker: new FormControl([]),
        andraKandaOrsaker: new FormControl([])
      }),
      fragorFormGroup: new FormGroup({
        fraga1: new FormControl(''),
        fraga2: new FormControl('')
      }),
      timepickerFormGroup: new FormGroup({
        startTime: new FormControl(''),
        endTime: new FormControl('')
      })
    }, {
      validators:
        [
          DescriptionIsRequiredCheck.CheckIfRequired('description', 'orsakerFormGroup', 'andraKandaOrsaker', KandaOrsakerEnum.AnnanOrsak),
          OrsakerIsRequiredCheck.CheckIfRequired('orsakerFormGroup', 'orsaker'),
          AnnanKandOrsakeIsRequiredCheck.CheckIfRequired('orsakerFormGroup', 'andraKandaOrsaker'),
          DateIsRequiredCheck.CheckIfRequired('date'),
          DayOrPartOfDayIsRequiredCheck.CheckIfRequired('dayOrPartOfDay'),
          StartTimeIsRequiredCheck.CheckIfRequired('timepickerFormGroup', 'startTime'),
          EndTimeIsRequiredCheck.CheckIfRequired('timepickerFormGroup', 'endTime'),
          MotiveringIsRequiredCheck.CheckIfRequired('fraga1')
        ]
    })
  }

  get alternativeFormControl(): AbstractControl | undefined {
    return this.avvikelseFormGroup?.get(this.alternativeFormControlName);
  }

  get descriptionFormControl(): AbstractControl | undefined {
    return this.avvikelseFormGroup?.get(this.descriptionFormControlName);
  }

  get dateFormControl(): AbstractControl | undefined {
    return this.avvikelseFormGroup?.get(this.dateFormControlName);
  }

  get dayOrPartOfDayFormControl(): AbstractControl | undefined {
    return this.avvikelseFormGroup?.get(this.dayOrPartOfDayFormControlName);
  }

  get orsakerFormControl(): AbstractControl | undefined {
    return this.avvikelseFormGroup?.get('orsakerFormGroup').get(this.orsakerFormControlName);
  }

  get andraKandaOrsakerFormControl(): AbstractControl | undefined {
    return this.avvikelseFormGroup?.get('orsakerFormGroup').get(this.andraKandaOrsakerFormControlName);
  }

  get fraga1FormControl(): AbstractControl | undefined {
    return this.avvikelseFormGroup.get('fragorFormGroup').get(this.fraga1FormControlName);
  }

  get fraga2FormControl(): AbstractControl | undefined {
    return this.avvikelseFormGroup.get('fragorFormGroup').get(this.fraga2FormControlName);
  }

  get startTimeFormControl(): AbstractControl | undefined {
    return this.avvikelseFormGroup.get('timepickerFormGroup').get(this.startTimeFormControlName);
  }

  get endTimeFormControl(): AbstractControl | undefined {
    return this.avvikelseFormGroup.get('timepickerFormGroup').get(this.endTimeFormControlName);
  }

  setConfirmDialogChanged(confirm: ConfirmDialog): void {
    this.openConfirmDialog = false;
    if (confirm === ConfirmDialog.ACCEPTED) {
      const postAvvikelse: Avvikelse = {
        datum_for_rapportering: this.todayDate,
        arbetssokande: {
          personnummer: this.contactInformation.personnummer.toString(),
          fornamn: this.contactInformation.fornamn.toString(),
          efternamn: this.contactInformation.efternamn.toString()
        },
        sokandeId: +this.activatedRoute.snapshot.params['deltagareId']
      }

      if (this.alternativeFormControl.value as string === Alternative.AVVIKELSE) {
        postAvvikelse['avvikelsealternativ'] = this.avvikelse;
      } else if (this.alternativeFormControl.value as string == Alternative.FRANVARO) {
        postAvvikelse['franvaro'] = this.franvaro;
      }

      this.deltagareAvvikelseService.createAvvikelse$(postAvvikelse, this.alternativeFormControl.value as string)
        .subscribe({
          error: () => this._showDangerNotification$.next(true),
          next: () => this._showSuccessNotification$.next(true),
          complete: () => this.avvikelseFormGroup.reset()
        });
    }
  }

  get franvaro(): FranvaroAlternativ {
    return {
      avvikelseorsakskod: this.orsakerFormControl.value as string,
      datum: this.dateFormControl.value as string,
      heldag: this.dayOrPartOfDayFormControl.value === DayOrPartOfDay.HELDAG ? true : false,
      starttid: this.startTimeFormControl.value as string || '9:00',
      sluttid: this.endTimeFormControl.value as string || '16:00',
      forvantad_narvaro: {
        starttid: '',
        sluttid: ''
      },
      alternativ_for_kanda_orsaker: {
        typ: this.andraKandaOrsakerFormControl.value as string || '',
        motivering: this.descriptionFormControl.value as string
      }
    }
  }

  get avvikelse(): AvvikelseAlternativ {
    return {
      avvikelseorsakskod: this.orsakerFormControl.value as string,
      frageformular: [
        {
          fraga: this.avvikelseFormGroup.get('orsakerFormGroup').get('orsaker').value as string + '_1',
          svar: this.fraga1FormControl.value as string
        },
        {
          fraga: this.fraga2FormControl.value as string !== '' ?
            this.avvikelseFormGroup.get('orsakerFormGroup').get('orsaker').value as string + '_2' : '',
          svar: this.fraga2FormControl.value as string
        }
      ],
      rapporteringsdatum: this.dateFormControl.value as string
    }
  }

  setAlternative(): void {
    if (this.alternativeFormControl.value as string == Alternative.FRANVARO) {
      this.franvaroOrsaker$ = this.deltagareAvvikelseService.getOrsaksKoderFranvaro$();
      this.andraKandaOrsaker$ = this.deltagareAvvikelseService.getAndraKandaOrsaker$();
    }

    if (this.alternativeFormControl.value as string == Alternative.AVVIKELSE) {
      this.avvikelseOrsaker$ = this.deltagareAvvikelseService.getOrsaksKoderAvvikelse$();
      this.fragor1$ = this.deltagareAvvikelseService.getFragorForAvvikelser$()
        .pipe(
          map((fragor: FragorForAvvikelser[]) => {
            return fragor.filter((fraga: FragorForAvvikelser) => fraga.id.includes('_1'))
          }
          )
        );

      this.fragor2$ = this.deltagareAvvikelseService.getFragorForAvvikelser$()
        .pipe(
          map((fragor: FragorForAvvikelser[]) => {
            return fragor.filter((fraga: FragorForAvvikelser) => {
              this.setIfRequiredDescription(fraga);
              return fraga.id.includes('_2')
            })
          })
        )
    }

    this.clearControlOnAlternativeChange();
  }

  private setIfRequiredDescription(fraga: FragorForAvvikelser) {
    fraga.id === '19_2' || fraga.id === '20_2' ?
      fraga.descriptionIsRequired = false :
      fraga.descriptionIsRequired = true;
  }

  setOrsakerChanged(): void {
    this.avvikelseFormGroup.markAsUntouched();
    if (this.alternativeFormControl.value as string === Alternative.AVVIKELSE) {
      this.selectedOrsaksKod = this.avvikelseFormGroup.get('orsakerFormGroup').get('orsaker').value as string;
    }

    this.avvikelseFormGroup.get('orsakerFormGroup').get('orsaker').valueChanges
      .subscribe(value => {
        if (value !== null) {
          this.avvikelseFormGroup.get('orsakerFormGroup').get('andraKandaOrsaker').reset();
        }
      });
  }

  get showDescription(): boolean {
    return this.alternativeFormControl.value as string == Alternative.FRANVARO &&
      +this.orsakerFormControl.value === FranvaroOrsaksKodEnum.AnnanKandOrsak &&
      +this.andraKandaOrsakerFormControl.value === KandaOrsakerEnum.AnnanOrsak
  }

  get showFragor(): boolean {
    return this.alternativeFormControl.value as string === Alternative.AVVIKELSE &&
      this.orsakerFormControl.value as boolean;
  }

  get showDatePicker(): boolean {
    return this.orsakerFormControl.value as boolean;
  }

  get showDayOrPartOfDayPicker(): boolean {
    return this.alternativeFormControl.value as string === Alternative.FRANVARO && this.orsakerFormControl.value as boolean;
  }

  get showTimePicker(): boolean {
    return this.alternativeFormControl.value as string === Alternative.FRANVARO &&
      this.dayOrPartOfDayFormControl.value as string === DayOrPartOfDay.DEL_AV_DAG
  }

  get nextStep(): number {
    this.avvikelseFormGroup.markAllAsTouched();
    if (this.avvikelseFormGroup.valid && this.currentStep < this.totalAmountOfSteps) {
      return this.currentStep++;
    }
  }

  previousStep(): void {
    if (this.currentStep > 1) {
      this.currentStep--;
      this._showSuccessNotification$.next(false);
      this._showDangerNotification$.next(false);
    }
  }

  backToDeltagare(): void {
    void this.router.navigate(['./deltagare', this.activatedRoute.snapshot.params['deltagareId']]);
  }

  private clearControlOnAlternativeChange(): void {
    this.descriptionFormControl.setValue('');
    this.fraga1FormControl.setValue('');
    this.fraga2FormControl.setValue('');
    this.dayOrPartOfDayFormControl.reset();
    this.avvikelseFormGroup?.get('timepickerFormGroup').reset();
  }

}
