import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { map, Observable } from 'rxjs';

import { environment } from '../../environments/environment';
import { ApiCollectionResponse } from '../models/api-response.model';
import { CatalogHttpMethod } from '../models/catalog-crud.model';
import { extractCollectionData } from '../utils/api-response.util';

@Injectable({
  providedIn: 'root'
})
export class CatalogCrudService {
  constructor(private http: HttpClient) {}

  list<T>(endpoint: string): Observable<T[]> {
    return this.http
      .get<T[] | ApiCollectionResponse<T>>(this.buildUrl(endpoint))
      .pipe(map(response => extractCollectionData(response)));
  }

  getById<T>(endpoint: string, id: number): Observable<T> {
    return this.http.get<T>(`${this.buildUrl(endpoint)}/${id}`);
  }

  create<T>(endpoint: string, payload: Record<string, unknown>): Observable<T> {
    return this.http.post<T>(this.buildUrl(endpoint), payload);
  }

  update<T>(
    endpoint: string,
    id: number,
    payload: Record<string, unknown>,
    method: CatalogHttpMethod = 'PUT'
  ): Observable<T> {
    const url = `${this.buildUrl(endpoint)}/${id}`;
    return method === 'PATCH'
      ? this.http.patch<T>(url, payload)
      : this.http.put<T>(url, payload);
  }

  delete(endpoint: string, id: number): Observable<void> {
    return this.http.delete<void>(`${this.buildUrl(endpoint)}/${id}`);
  }

  private buildUrl(endpoint: string): string {
    return `${environment.apiBaseUrl}${endpoint}`;
  }
}
