import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { catchError, map, of } from 'rxjs';
import { ApiConfigService } from '../../../../core/config/api-config.service';
import { AdminCategory, AdminCategoryListFilters } from '../models/admin-category.model';
import { AdminCategoriesGateway } from './admin-categories-gateway.interface';

/**
 * Real HTTP implementation against /backoffice/categories per
 * docs/backend/BACKEND-INTEGRATION.md §6.9 and the backend's API-REFERENCE.md §3.
 * Categories have no hard delete - only soft delete/restore.
 */
@Injectable({ providedIn: 'root' })
export class AdminCategoriesApiGateway implements AdminCategoriesGateway {
  private readonly http = inject(HttpClient);
  private readonly apiConfig = inject(ApiConfigService);

  private get baseUrl(): string {
    return `${this.apiConfig.getBaseUrl()}/backoffice/categories`;
  }

  loadCategories(filters: AdminCategoryListFilters): Observable<AdminCategory[]> {
    const params = new HttpParams()
      .set('search', filters.search)
      .set('visibility', filters.visibility)
      .set('includeDeleted', String(filters.includeDeleted));
    return this.http.get<AdminCategory[]>(this.baseUrl, { params });
  }

  loadCategory(id: string): Observable<AdminCategory | null> {
    return this.http.get<AdminCategory>(`${this.baseUrl}/${encodeURIComponent(id)}`).pipe(
      catchError(() => of(null))
    );
  }

  createCategory(category: AdminCategory): Observable<AdminCategory> {
    const { id, itemsCount, deletedAt, createdAt, updatedAt, ...body } = category;
    return this.http.post<AdminCategory>(this.baseUrl, body);
  }

  updateCategory(category: AdminCategory): Observable<AdminCategory> {
    return this.http.put<AdminCategory>(`${this.baseUrl}/${encodeURIComponent(category.id)}`, category);
  }

  deleteCategory(id: string): Observable<void> {
    return this.http.delete<void>(`${this.baseUrl}/${encodeURIComponent(id)}`);
  }

  restoreCategory(id: string): Observable<AdminCategory | null> {
    return this.http.post<AdminCategory>(`${this.baseUrl}/${encodeURIComponent(id)}/restore`, {}).pipe(
      catchError(() => of(null))
    );
  }

  isSlugTaken(slug: string, excludingId: string | null): Observable<boolean> {
    let params = new HttpParams().set('slug', slug);
    if (excludingId) {
      params = params.set('excludingId', excludingId);
    }
    return this.http.get<{ taken: boolean }>(`${this.baseUrl}/slug-taken`, { params }).pipe(
      map(response => response.taken)
    );
  }
}
