import { HttpClient, HttpParams } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { map, Observable } from 'rxjs';
import { BackendConfig, ListParams, PagedResult } from './paging';
import { normalizePage } from './normalize-page';
import { environment } from 'src/environments/environment.development';

const springDefaults: BackendConfig = {
  pageParam: 'page',
  sizeParam: 'size',
  searchParam: 'q',
  zeroBasedPageIndex: true,
  buildSort: (key, dir) => (key && dir ? ['sort', `${key},${dir}`] : null),
  mapClientSortKey: (k) => k,
};

@Injectable({ providedIn: 'root' })
export class PaginatedHttpService {
  private http = inject(HttpClient);

  // Helper method to get ngrok bypass headers
  private getNgrokHeaders(): Record<string, string> {
    const isNgrok = environment.apiBaseUrl.includes('ngrok-free.app') || environment.apiBaseUrl.includes('ngrok.io') || environment.apiBaseUrl.includes('ngrok');
    return isNgrok ? { 'ngrok-skip-browser-warning': 'true' } : {};
  }

  fetch<T>(
    url: string,
    params: ListParams,
    cfg: BackendConfig = springDefaults
  ): Observable<PagedResult<T>> {
    const {
      pageParam = 'page',
      sizeParam = 'size',
      searchParam = 'q',
      zeroBasedPageIndex = true,
      buildSort = springDefaults.buildSort!,
      mapClientSortKey = springDefaults.mapClientSortKey!,
    } = cfg;

    let httpParams = new HttpParams()
      .set(pageParam, String(zeroBasedPageIndex ? Math.max(params.page - 1, 0) : params.page))
      .set(sizeParam, String(params.size));

    if (params.search) httpParams = httpParams.set(searchParam, params.search);

    const apiSortKey = mapClientSortKey(params.sortKey);
    const sortPair = buildSort(apiSortKey, params.sortDir);
    if (sortPair) httpParams = httpParams.set(sortPair[0], sortPair[1]);

    if (params.extra) {
      for (const [k, v] of Object.entries(params.extra)) {
        if (v !== undefined && v !== null && v !== '') httpParams = httpParams.set(k, String(v));
      }
    }

    return this.http
      .get<any>(url, { params: httpParams, headers: this.getNgrokHeaders() })
      .pipe(map((raw) => normalizePage<T>(raw, params.page, params.size)));
  }
}
