import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { AdminProduct, AdminProductCategoryOption, AdminProductListFilters, AdminProductsListResult } from '../models/admin-product.model';
import { AdminProductsGateway } from './admin-products-gateway.interface';

/**
 * Contract: docs/backend/PHASE-3-CATALOG-OFFER-FULFILLMENT-CONTRACT.md §7
 * (list/get/create/update on /api/admin/v2/products). duplicate/archive/
 * restore aren't individually specified - inferred as sub-resource actions,
 * consistent with the offers/{id}/publish pattern in the same contract.
 */
@Injectable({ providedIn: 'root' })
export class AdminProductsApiGateway implements AdminProductsGateway {
  private readonly http = inject(HttpClient);

  loadProducts(filters: AdminProductListFilters): Observable<AdminProductsListResult> {
    let params = new HttpParams();
    for (const [key, value] of Object.entries(filters ?? {})) {
      if (value !== undefined && value !== null && value !== '') {
        params = params.set(key, String(value));
      }
    }
    return this.http.get<AdminProductsListResult>('/api/admin/v2/products', { params });
  }

  loadProduct(id: string): Observable<AdminProduct | null> {
    return this.http.get<AdminProduct | null>(`/api/admin/v2/products/${encodeURIComponent(id)}`);
  }

  loadCategories(): Observable<AdminProductCategoryOption[]> {
    return this.http.get<AdminProductCategoryOption[]>('/api/admin/v2/products/categories');
  }

  createProduct(product: AdminProduct): Observable<AdminProduct> {
    return this.http.post<AdminProduct>('/api/admin/v2/products', product);
  }

  updateProduct(product: AdminProduct): Observable<AdminProduct> {
    return this.http.patch<AdminProduct>(`/api/admin/v2/products/${encodeURIComponent(product.id)}`, product);
  }

  deleteProduct(id: string): Observable<void> {
    return this.http.delete(`/api/admin/v2/products/${encodeURIComponent(id)}`).pipe(map(() => undefined));
  }

  duplicateProduct(id: string): Observable<AdminProduct | null> {
    return this.http.post<AdminProduct | null>(`/api/admin/v2/products/${encodeURIComponent(id)}/duplicate`, {});
  }

  archiveProduct(id: string): Observable<void> {
    return this.http
      .post(`/api/admin/v2/products/${encodeURIComponent(id)}/archive`, {})
      .pipe(map(() => undefined));
  }

  restoreProduct(id: string): Observable<AdminProduct | null> {
    return this.http.post<AdminProduct | null>(`/api/admin/v2/products/${encodeURIComponent(id)}/restore`, {});
  }
}
