import { Observable, of } from 'rxjs';
import { GridDataResult } from '@progress/kendo-angular-grid';
import { HttpClient } from '@angular/common/http';
import { toODataString } from '@progress/kendo-data-query';
import { map } from 'rxjs/operators';
import { convertToDates } from './util';
import { State } from '@progress/kendo-data-query';
import { inject } from '@angular/core';

interface ODataResponse<T> {
  value: T[];
  '@odata.count': string | number;
}

export class OdataGridHelper {
  http = inject(HttpClient);

  public fetch(
    odataFunction: string,
    state: State,
    extraParamsQueryStr: string,
    skipDateConversion: boolean
  ): Observable<GridDataResult> {
    extraParamsQueryStr = extraParamsQueryStr !== null ? extraParamsQueryStr : '';
    const queryStr = `${toODataString(state, { utcDates: true })}${extraParamsQueryStr}&isExport=false&exportType=none&$count=true`;
    //set the separator based on whether the odataFunction has additional parameters
    const separator: string = odataFunction.includes('?') ? '&' : '?';
    const url = `${window.location.origin}/odata/${odataFunction}${separator}${queryStr}`;

    return this.http.get<ODataResponse<GridDataResult>>(url).pipe(
      map(response => {
        const data = response.value;
        const total = parseInt(response['@odata.count'].toString(), 10);

        if (!skipDateConversion)
          convertToDates(data);

        const newResponse = ({ data: data, total: total } as GridDataResult)
        return newResponse;
      })
    );
  }

  public fetchExport(
    odataFunction: string,
    state: State,
    extraParamsQueryStr: string,
    fileNameOriginal: string
  ): Observable<{ fileBlob: Blob, fileName: string }> {
    extraParamsQueryStr = extraParamsQueryStr !== null ? extraParamsQueryStr : '';
    const newState = { ...state }; //clones state
    newState.skip = null;
    newState.take = null;
    const queryStr = `${toODataString(newState)}${extraParamsQueryStr}&isExport=true&$count=true`;
    //set the separator based on whether the odataFunction has additional parameters
    const separator: string = odataFunction.includes('?') ? '&' : '?';
    const url = `${window.location.origin}/odata/${odataFunction}${separator}${queryStr}`;

    return this.http.get(url, { observe: 'response', responseType: 'blob' }).pipe(
      map((result) => {
        const fileBlob = result.body;
        const fileName: string = result.body.type === "text/plain" ? "Error.txt" : fileNameOriginal;
        return { fileBlob, fileName };
      })
    );
  }

  public fetchEmpty(): Observable<GridDataResult> {
    const emptyGridDataResult: GridDataResult = { data: [], total: 0 };
    return of(emptyGridDataResult);
  }
}
