import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Alternative } from '@msfa-enums/alternative.enum';
import { ErrorType } from '@msfa-enums/error-type.enum';
import { environment } from '@msfa-environment';

import {
  ContactInformationCompact,
  ContactInformationResponse,
  mapResponseToContactInformationCompact
} from '@msfa-models/api/contact-information.response.model';
import { FragorForAvvikelserResponse } from '@msfa-models/api/fragor-for-avvikelser.response';
import { KandaAvvikelseKoderResponse } from '@msfa-models/api/kanda-avvikelse-koder.response.model';
import { OrsaksKoderAvvikelseResponse } from '@msfa-models/api/orsaks-koder-avvikelse.response.model';
import { Avvikelse, AvvikelseRequestData, mapAvvikelseRequestDataToAvvikelse } from '@msfa-models/avvikelse.model';
import { errorToCustomError } from '@msfa-models/error/custom-error';
import { FragorForAvvikelser, mapResponseToFragorForAvvikelser } from '@msfa-models/fragor-for-avvikelser.model';
import { mapResponseToOrsaksKoderAvvikelse, OrsaksKoderAvvikelse } from '@msfa-models/orsaks-koder-avvikelse.model';
import {
  KandaAvvikelseKoder,
  mapResponseToAndraKandaOrsaker,
  mapResponseToOrsaksKoderFranvaro,
  OrsaksKoderFranvaro
} from '@msfa-models/orsaks-koder-franvaro.model';
import { ErrorService } from '@msfa-services/error.service';
import { Observable, of, throwError } from 'rxjs';
import { catchError, filter, map, take } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})

export class AvvikelseApiService {

  private _apiBaseUrl = `${environment.api.url}`;

  public getOrsaksKoderFranvaro$(): Observable<OrsaksKoderFranvaro[]> {
    return this.httpClient.get<{ data: OrsaksKoderAvvikelseResponse[] }>(`${this._apiBaseUrl}/orsakskoderfranvaro`).pipe(
      filter(response => !!response?.data),
      map(({ data }) => data.map(orsak => mapResponseToOrsaksKoderFranvaro(orsak)))
    )
  }

  public getOrsaksKoderAvvikelse$(): Observable<OrsaksKoderAvvikelse[]> {
    return this.httpClient.get<{ data: OrsaksKoderAvvikelseResponse[] }>(`${this._apiBaseUrl}/orsakskoderavvikelse`).pipe(
      filter(response => !!response?.data),
      map(({ data }) => data.map(avvikelse => mapResponseToOrsaksKoderAvvikelse(avvikelse)))
    )
  }

  public getAndraKandaOrsaker$(): Observable<KandaAvvikelseKoder[]> {
    return this.httpClient.get<{ data: KandaAvvikelseKoderResponse[] }>(`${this._apiBaseUrl}/kandaavvikelsekoder`).pipe(
      filter(response => !!response?.data),
      map(({ data }) => data.map(annanKandOrsak => mapResponseToAndraKandaOrsaker(annanKandOrsak)))
    )
  }

  public getFragorForAvvikelser$(): Observable<FragorForAvvikelser[]> {
    return this.httpClient.get<{ data: FragorForAvvikelserResponse[] }>(`${this._apiBaseUrl}/fragorforavvikelser`).pipe(
      filter(response => !!response?.data),
      map(({ data }) => data.map(fraga => mapResponseToFragorForAvvikelser(fraga)))
    )
  }

  public getContactInformation$(id: number): Observable<ContactInformationCompact> {
    return this.httpClient.get<{ data: ContactInformationResponse }>(`${this._apiBaseUrl}/deltagare/${id}/contact`).pipe(
      filter(response => !!response?.data),
      map(({ data }) => mapResponseToContactInformationCompact(data),
        catchError(error => {
          this.errorService.add(errorToCustomError(error));
          return of({});
        })
      )
    )
  }

  public createAvvikelse$(avvikelse: Avvikelse, alternative: string): Observable<Avvikelse> {

    return this.httpClient
      .post<{ data: AvvikelseRequestData }>(`${this._apiBaseUrl}/${this.setEndPoint(alternative)}`, avvikelse).pipe(
        filter(response => !!response?.data),
        take(1),
        map(({ data }) => mapAvvikelseRequestDataToAvvikelse(data)),
        catchError(error => throwError({ message: error as string, type: ErrorType.API }))
      )
  }

  private setEndPoint(alternative: string): string {
    let endpoint = '';

    switch (alternative) {
      case Alternative.AVVIKELSE:
        endpoint = 'avvikelse';
        break;
      case Alternative.FRANVARO:
        endpoint = 'franvaro';
        break
      default:
        break;
    }
    return endpoint;
  }

  constructor(private httpClient: HttpClient, private errorService: ErrorService) { }
}




