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 { AvropAndMetaResponse } from '@msfa-models/api/avrop.response.model';
import { Params } from '@msfa-models/api/params.model';
import { AvropFilter, mapResponseToAvropFilter } from '@msfa-models/avrop-filter.model';
import { Avrop, AvropAndMeta, mapResponseToAvrop } from '@msfa-models/avrop.model';
import { CustomError, errorToCustomError } from '@msfa-models/error/custom-error';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { catchError, filter, map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root',
})
export class AvropApiService {
  private _apiBaseUrl = `${environment.api.url}/avrop`;
  private _lockedAvropSnapshot$ = new BehaviorSubject<Avrop[]>(null);
  private _showUnauthorizedError$ = new BehaviorSubject<boolean>(false);
  public showUnauthorizedError$: Observable<boolean> = this._showUnauthorizedError$.asObservable();

  constructor(private httpClient: HttpClient) {}

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

  fetchAvrop$(params: Params): Observable<AvropAndMeta | null> {
    return this.httpClient
      .get<AvropAndMetaResponse>(`${this._apiBaseUrl}`, { params })
      .pipe(
        map(({ data, meta }) => ({ data: data.map(avrop => mapResponseToAvrop(avrop)), meta })),
        catchError((error: Error & { status: number }) => {
          if (error.status === 403) {
            this._showUnauthorizedError$.next(true);
            return of(null as null);
          } else {
            throw new CustomError(
              errorToCustomError({ ...error, message: `Kunde inte hämta nya deltagare.\n\n${error.message}` })
            );
          }
        })
      );
  }

  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: Avrop[], 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();
  }
}
