import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { DeltagareAvrop } from '@msfa-models/avrop.model';
import { addDays } from 'date-fns';
import { combineLatest, Observable } 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/forms-to-slutredovisning-form-data';

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 {
  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$;

  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)
  );

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

  private _isAfterEndDate(date: Date): boolean {
    return new Date() > date;
  }

  private _isBeforeLastPossibleReportDay(date: Date): boolean {
    // Reporting is allowed at latest 60 days past avrop end date.
    // Because it's workdays and not calendar days we temporarily set this to much more. This date should be fetched from API in the future
    const lastPossibleReportDay = addDays(date, 100);
    return lastPossibleReportDay > new Date();
  }

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

  notAllowedToReportWarning(avrop: DeltagareAvrop): string {
    if (!this._isBeforeLastPossibleReportDay(avrop.endDate)) {
      return 'Det går inte att göra en Slutredovisning eftersom ärendet är avslutat.';
    }
    if (!this._isAfterEndDate(avrop.endDate)) {
      return 'Det går inte att göra en Slutredovisning eftersom tjänsten inte har avslutats ännu.';
    }
    if (!avrop.hasGemensamPlanering) {
      return 'Det går inte att göra en Slutredovisning eftersom en Gemensam planering inte har skickats in ännu.';
    }
  }

  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);
  }
}
