import { Injectable } from '@angular/core';
import { ItemDTO } from '@swagger/cat';
import { map, catchError, timeout, filter, switchMap } from 'rxjs/operators';
import { Printer } from '../models/printer.model';
import { Observable, of } from 'rxjs';
import { PrintRequestOfIEnumerableOfItemDTO, PrintRequestOfIEnumerableOfLong, ResponseArgs } from '@swagger/print';
import { HttpClient } from '@angular/common/http';
import { OMSPrintService, CheckoutPrintService, CatalogPrintService, PrintService } from '@swagger/print';

@Injectable({
  providedIn: 'root',
})
export class PrinterService {
  constructor(
    private catalogPrintService: CatalogPrintService,
    private checkoutPrintService: CheckoutPrintService,
    private oMSPrintService: OMSPrintService,
    private printService: PrintService,
    private http: HttpClient
  ) {}

  getAvailablePrinters(): Observable<Printer[] | { error: string }> {
    return this.printService.PrintPrinters().pipe(
      timeout(20000),
      catchError((error) => {
        return of({ error });
      }),
      map((response: any) => {
        if (response.error && response.error.status === 503) {
          return {
            error: response.message ? response.message : 'Das Backend ist derzeit nicht erreichbar',
          };
        }
        if (response.error && response.error.name === 'TimeoutError') {
          return { error: response.message ? response.message : 'API Timeout' };
        }
        if (response.error) {
          return {
            error: response.message ? response.message : response.error.message ? response.error.message : 'Ein Fehler ist aufgetreten',
          };
        }
        return response.result.map(
          (t) =>
            <Printer>{
              key: t.key,
              value: t.value,
              description: t.description,
              selected: t.selected,
            }
        );
      })
    );
  }

  getAvailablePrintersDev() {
    return this.http.get('http://127.0.0.1:5000/api/printers').pipe(
      timeout(20000),
      catchError((error) => {
        return of({ error });
      }),
      map((response: any) => {
        if (response.error && response.error.status === 503) {
          return {
            error: response.message ? response.message : 'Das Backend ist derzeit nicht erreichbar',
          };
        }
        if (response.error && response.error.name === 'TimeoutError') {
          return { error: response.message ? response.message : 'API Timeout' };
        }
        if (response.error) {
          return {
            error: response.message ? response.message : response.error.message ? response.error.message : 'Ein Fehler ist aufgetreten',
          };
        }
        return response.result.map(
          (t) =>
            <Printer>{
              key: t.key,
              value: t.value,
              description: t.description,
              selected: t.selected,
            }
        );
      })
    );
  }

  async printOrder(orderIds: number[], printer: string): Promise<ResponseArgs> {
    const params = <any>{
      printer: printer,
      data: orderIds,
    };
    const response = await this.oMSPrintService.OMSPrintAbholscheinById(params).pipe(timeout(20000)).toPromise();

    return response;
  }

  async printProduct(item: ItemDTO, printer: string): Promise<ResponseArgs> {
    const params = <PrintRequestOfIEnumerableOfItemDTO>{
      printer: printer,
      data: [item],
    };
    const response = await this.catalogPrintService.CatalogPrintArtikelDetail(params).pipe(timeout(20000)).toPromise();

    return response;
  }

  async printCart(cartId: number, printer: string): Promise<ResponseArgs> {
    const params = <any>{
      printer: printer,
      data: cartId,
    };
    const response = await this.checkoutPrintService.CheckoutPrintWarenkorbById(params).pipe(timeout(20000)).toPromise();

    return response;
  }

  async printGoodsInLabel(subsetItemIds: number[]): Promise<ResponseArgs> {
    const response = await this.getAvailablePrinters()
      .pipe(
        filter((data) => Array.isArray(data)),
        switchMap((printers: Printer[]) => {
          if (printers && printers.length > 0) {
            const printer = printers.find((p) => p.selected);
            if (printer) {
              const params = <PrintRequestOfIEnumerableOfLong>{
                data: subsetItemIds,
                printer: printer.key,
              };
              return this.oMSPrintService.OMSPrintAbholfachetikett(params);
            } else {
              return of(undefined);
            }
          } else {
            return of(undefined);
          }
        }),
        timeout(20000)
      )
      .toPromise();

    return response;
  }
}
