import { ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core';
import { AbstractControl, FormGroup } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { DeltagareAvrop } from '@msfa-models/avrop.model';
import { addDays } from 'date-fns';
import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';
import { map, shareReplay, switchMap } from 'rxjs/operators';
import { SlutredovisningFormData } from './models/slutredovisning-form-data.model';
import { SlutredovisningStep0FormData } from './slutredovisning-form-step0/slutredovisning-form-step0.component';
import { SlutredovisningStep1FormData } from './slutredovisning-form-step1/slutredovisning-form-step1.component';
import { SlutredovisningStep2FormData } from './slutredovisning-form-step2/slutredovisning-form-step2.component';
import { SlutredovisningStep } from './slutredovisning-form.model';
import { SlutredovisningFormService } from './slutredovisning-form.service';
import { formsToSlutredovisningFormData } from './utils/form-data-to-slutredovisning.util';

interface Params {
  genomforandeReferens: string;
}

@Component({
  selector: 'msfa-slutredovisning-form',
  templateUrl: './slutredovisning-form.component.html',
  styleUrls: ['./slutredovisning-form.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [SlutredovisningFormService],
})
export class SlutredovisningFormComponent implements OnDestroy {
  totalSteps = 4;
  currentStep$ = this.slutredovisningFormService.currentStep$;
  showAvropDetails$ = this.currentStep$.pipe(map(step => step === 'step0' || step === 'step3'));

  step0FormGroup: FormGroup = new FormGroup({});
  step1FormGroup: FormGroup = new FormGroup({});
  step2FormGroup: FormGroup = new FormGroup({});

  step0FormData$: Observable<SlutredovisningStep0FormData> = this.slutredovisningFormService.step0FormData$;
  step1FormData$: Observable<SlutredovisningStep1FormData> = this.slutredovisningFormService.step1FormData$;
  step2FormData$: Observable<SlutredovisningStep2FormData> = this.slutredovisningFormService.step2FormData$;

  shouldValidate$ = new BehaviorSubject<boolean>(false);

  genomforandeReferens$: Observable<number> = this.activatedRoute.params.pipe(
    map((params: Params) => +params.genomforandeReferens)
  );

  slutredovisningFormData$: Observable<SlutredovisningFormData> = combineLatest([
    this.genomforandeReferens$,
    this.step0FormData$,
    this.step1FormData$,
    this.step2FormData$,
  ]).pipe(
    map(([genomforandereferens, step0, step1, step2]) =>
      formsToSlutredovisningFormData(genomforandereferens, step0, step1, step2)
    )
  );

  avrop$: Observable<DeltagareAvrop> = this.genomforandeReferens$.pipe(
    switchMap(genomforandeReferens => this.slutredovisningFormService.fetchAvropInformation$(genomforandeReferens)),
    shareReplay(1)
  );

  private subscriptions: Subscription[] = [];

  constructor(private slutredovisningFormService: SlutredovisningFormService, private activatedRoute: ActivatedRoute) {}

  formControlIsInvalid(formControl: AbstractControl): boolean {
    return formControl.invalid && (formControl.touched || this.shouldValidate$.value);
  }

  openConfirmDialog(): void {
    this.shouldValidate$.next(true);
  }

  private _isAfterStartDate(startDate: Date): boolean {
    return new Date() > startDate;
  }

  private _isBeforeLastPossibleReportDay(endDate: Date): boolean {
    const lastPossibleReportDay = addDays(endDate, 5); // Reporting is allowed at latest 5 days past avrop end date.
    return lastPossibleReportDay > new Date();
  }

  isAllowedToReport(avrop: DeltagareAvrop): boolean {
    return this._isAfterStartDate(avrop.startDate) && this._isBeforeLastPossibleReportDay(avrop.endDate);
  }

  notAllowedToReportWarning(avrop: DeltagareAvrop): string {
    if (!this._isBeforeLastPossibleReportDay(avrop.endDate)) {
      return 'Det går inte att göra Slutredovisning eftersom tjänsten har avslutats.';
    }
    if (!this._isAfterStartDate(avrop.startDate)) {
      return 'Det går inte att göra Slutredovisning eftersom tjänsten inte har startat ännu.';
    }
  }

  ngOnDestroy(): void {
    this.subscriptions.forEach(subscription => subscription.unsubscribe());
  }

  getStepIndex(step: SlutredovisningStep): number {
    switch (step) {
      case 'step0':
        return 0;
      case 'step1':
        return 1;
      case 'step2':
        return 2;
      case 'step3':
        return 3;
    }
  }

  backFromStep1(): void {
    this.slutredovisningFormService.setStep('step0');
  }

  backFromStep2(): void {
    this.slutredovisningFormService.setStep('step1');
  }

  backFromStep3(): void {
    this.slutredovisningFormService.setStep('step2');
  }

  processStep0Data(formData: SlutredovisningStep0FormData): void {
    this.slutredovisningFormService.processStep0Data(formData);
    window.scrollTo(0, 0);
  }

  processStep1Data(formData: SlutredovisningStep1FormData): void {
    this.slutredovisningFormService.processStep1Data(formData);
    window.scrollTo(0, 0);
  }

  processStep2Data(formData: SlutredovisningStep2FormData): void {
    this.slutredovisningFormService.processStep2Data(formData);
    window.scrollTo(0, 0);
  }
}
