import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { environment } from '@msfa-environment';
import { AvropFilterResponse } from '@msfa-models/api/avrop-filter.response.model';
import { AvropApiResponse } from '@msfa-models/api/avrop.response.model';
import { HandledareResponse } from '@msfa-models/api/handledare.response.model';
import { Params } from '@msfa-models/api/params.model';
import { AvropFilter, mapResponseToAvropFilter } from '@msfa-models/avrop-filter.model';
import { AvropCompact, AvropCompactData, mapAvropResponseToAvrop } from '@msfa-models/avrop.model';
import { Handledare, mapHandledareResponseToHandledare } from '@msfa-models/handledare.model';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { filter, map, tap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class AvropApiService {
  private _apiBaseUrl = `${environment.api.url}/avrop`;
  private _lockedAvropSnapshot$ = new BehaviorSubject<AvropCompact[]>(null);
  private _availableHandledareSnapshot$ = new BehaviorSubject<Handledare[]>(null);

  constructor(private httpClient: HttpClient) {}

  get lockedAvropValue(): AvropCompact[] {
    return this._lockedAvropSnapshot$.getValue();
  }

  fetchAvrop$(params: Params): Observable<AvropCompactData> {
    return this.httpClient
      .get<AvropApiResponse>(`${this._apiBaseUrl}`, { params })
      .pipe(map(({ data, meta }) => ({ data: data.map(avrop => mapAvropResponseToAvrop(avrop)), meta })));
  }

  fetchAvailableHandledare$(avrop: AvropCompact[]): Observable<Handledare[]> {
    const lockedAvropIsEqual = this.lockedAvropValue?.every(
      (lockedAvrop, index) => lockedAvrop.id === avrop[index]?.id
    );

    // Checking to see if we really need to make a new api-request
    if (lockedAvropIsEqual) {
      return of(this._availableHandledareSnapshot$.getValue());
    }

    this._lockedAvropSnapshot$.next(avrop);

    return this.httpClient
      .get<{ data: HandledareResponse[] }>(`${this._apiBaseUrl}/handledare`, {
        params: { avropIds: avrop.map(a => a.id) },
      })
      .pipe(
        map(({ data }) => data.map(handledare => mapHandledareResponseToHandledare(handledare))),
        tap(handledare => {
          this._availableHandledareSnapshot$.next(handledare);
        })
      );
  }

  fetchAvailableTjanster$(params: Params): Observable<AvropFilter[]> {
    return this.httpClient
      .get<{ data: AvropFilterResponse[] }>(`${this._apiBaseUrl}/tjanster`, { params })
      .pipe(
        filter(response => !!response?.data),
        map(({ data }) => data.map(tjanster => mapResponseToAvropFilter(tjanster)))
      );
  }

  fetchAvailableUtforandeVerksamheter$(params: Params): Observable<AvropFilter[]> {
    return this.httpClient
      .get<{ data: AvropFilterResponse[] }>(`${this._apiBaseUrl}/utforandeverksamheter`, { params })
      .pipe(
        filter(response => !!response?.data),
        map(({ data }) => data.map(utforandeverksamheter => mapResponseToAvropFilter(utforandeverksamheter)))
      );
  }

  fetchAvailableKommuner$(params: Params): Observable<AvropFilter[]> {
    return this.httpClient
      .get<{ data: AvropFilterResponse[] }>(`${this._apiBaseUrl}/kommuner`, { params })
      .pipe(
        filter(response => !!response?.data),
        map(({ data }) => data.map(kommun => mapResponseToAvropFilter(kommun)))
      );
  }

  async assignHandledare(avrop: AvropCompact[], handledareId: string): Promise<void> {
    const params: Params = {
      avropIds: avrop.map(deltagare => deltagare.id),
      ciamUserId: handledareId,
    };
    return this.httpClient
      .patch<void>(`${this._apiBaseUrl}/handledare/assign`, null, { params })
      .toPromise();
  }
}
