import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Subject, filter, takeUntil } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class HttpRequestService {
  private cancelPendingRequests = new Subject<string>();
  private ignoreUrls: string[] = [];

  constructor(
    public http: HttpClient
  ) { }

  get(url: string, params = {}) {
    params = this.cleanParams(params);

    // Cancel any pending requests for the same URL
    if (!this.ignoreUrls.includes(url)) {
      this.cancelPendingRequests.next(url);
    }

    return new Promise((resolve, reject) => {
      this.http.get(url, { params })
        .pipe(takeUntil(this.cancelPendingRequests.pipe(filter((k) => k === url))))
        .subscribe({
          next: (res) => resolve(res),
          error: (err) => reject(err),
        });
    });
  }

  post(url: string, payload: any) {
    // Cancel any pending requests for the same URL
    this.cancelPendingRequests.next(url);

    return new Promise((resolve, reject) => {
      this.http.post(url, payload)
        .pipe(takeUntil(this.cancelPendingRequests.pipe(filter((k) => k === url))))
        .subscribe({
          next: (res) => resolve(res),
          error: (err) => reject(err),
        });
    });
  }

  delete(url: string, params = {}) {
    params = this.cleanParams(params);

    // Cancel any pending requests for the same URL
    this.cancelPendingRequests.next(url);

    return new Promise((resolve, reject) => {
      this.http.delete(url, { params })
        .pipe(takeUntil(this.cancelPendingRequests.pipe(filter((k) => k === url))))
        .subscribe({
          next: (res) => resolve(res),
          error: (err) => reject(err),
        });
    });
  }

  private cleanParams<T>(params: T): T {
    Object.keys(params).forEach(key =>
      (params[key] == null || params[key] === '' || params[key] === undefined) && delete params[key]
    );
    return params;
  }
}
