import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { DeltagareExportRequest } from '@msfa-models/api/deltagare-export.request.model';
import { CustomError } from '@msfa-models/error/custom-error';
import { Export } from '@msfa-models/export.model';
import { formatDate } from '@msfa-shared/utils/format-to-date.util';
import { saveAs } from 'file-saver';
import { BehaviorSubject } from 'rxjs';
import { take } from 'rxjs/operators';
import { DeltagareExportFormData, DeltagareExportFormErrors } from './deltagare-export.model';
import { DeltagareExportService } from './deltagare-export.service';
import { DeltagareExportValidator } from './deltagare-export.validator';

@Component({
  selector: 'msfa-deltagare-export',
  templateUrl: './deltagare-export.component.html',
  styleUrls: ['./deltagare-export.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DeltagareExportComponent {
  maxDate = new Date();
  shouldValidate$ = new BehaviorSubject<boolean>(false);
  fetchIsLoading$ = new BehaviorSubject<boolean>(false);
  fetchError$ = new BehaviorSubject<CustomError>(null);
  exportIsEmpty$ = new BehaviorSubject<boolean>(false);
  formGroup = new FormGroup(
    {
      startDate: new FormControl(null),
      endDate: new FormControl(null),
      includeExportedDeltagare: new FormControl(false),
      isExcel: new FormControl(false),
    },
    [DeltagareExportValidator.isDeltagareExportValid()]
  );
  constructor(private deltagareExportService: DeltagareExportService) {
    this.formGroup.valueChanges.subscribe(() => {
      this._removeAlerts();
    });
  }

  get startDateFormControl(): FormControl {
    return this.formGroup.get('startDate') as FormControl;
  }
  get endDateFormControl(): FormControl {
    return this.formGroup.get('endDate') as FormControl;
  }
  get includeExportedDeltagareFormControl(): FormControl {
    return this.formGroup.get('includeExportedDeltagare') as FormControl;
  }
  get isExcelFormControl(): FormControl {
    return this.formGroup.get('isExcel') as FormControl;
  }

  get deltagagareExportFormData(): DeltagareExportFormData {
    return this.formGroup.value as DeltagareExportFormData;
  }

  get formErrors(): DeltagareExportFormErrors {
    return this.formGroup.errors as DeltagareExportFormErrors;
  }

  get showPeriodError(): boolean {
    return this.formErrors?.datesMismatch && this.shouldValidate$.getValue();
  }

  private _removeAlerts(): void {
    this.fetchError$.next(null);
    this.exportIsEmpty$.next(false);
  }

  fetchExportFile(): void {
    this._removeAlerts();
    if (this.formGroup.invalid) {
      this.shouldValidate$.next(true);
      return;
    }

    this.fetchIsLoading$.next(true);
    this.deltagareExportService
      .fetchExportFile$(this._formDataToRequestData)
      .pipe(take(1))
      .subscribe({
        next: ({ empty, blob }: Export) => {
          if (empty) {
            this.exportIsEmpty$.next(true);
          } else {
            const isExcel = this._formDataToRequestData.exportToExcel;
            saveAs(blob, this._getFileName(isExcel));
            this.formGroup.reset();
          }
          this.fetchIsLoading$.next(false);
        },
        error: (customError: CustomError) => {
          this.fetchError$.next({ ...customError, message: customError.error.message });
          this.fetchIsLoading$.next(false);
          throw { ...customError, avoidToast: true };
        },
      });
  }

  private _getFileName(isExcel: boolean): string {
    const baseFileName = 'deltagare-export';
    const extension = isExcel ? 'xlsx' : 'csv';

    return `${baseFileName}-${formatDate(new Date())}.${extension}`;
  }

  private _getFileType(isExcel: boolean): string {
    return isExcel ? 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' : 'text/csv';
  }

  private get _formDataToRequestData(): DeltagareExportRequest {
    const { startDate, endDate, includeExportedDeltagare, isExcel } = this.deltagagareExportFormData;
    const requestData: DeltagareExportRequest = {
      includeExportedDeltagare: !!includeExportedDeltagare,
      exportToExcel: !!isExcel,
    };
    if (startDate) {
      requestData.startDate = startDate;
    }
    if (endDate) {
      requestData.endDate = endDate;
    }
    return requestData;
  }
}
