import 'server-only';

export interface ProductImageDto {
  id: string;
  productId: string;
  variantId: string | null;
  url: string;
  altText: string;
  position: number;
  role: 'main' | 'gallery';
  createdAt: string;
  updatedAt: string;
}

export interface CategoryDto {
  id: string;
  parentId: string | null;
  name: string;
  slug: string;
  url: string;
  seoTitle: string | null;
  seoDescription: string | null;
  emoji?: string | null;
  color?: string | null;
  createdAt: string;
  updatedAt: string;
}

export interface CategoryTreeNodeDto extends CategoryDto {
  children: CategoryTreeNodeDto[];
}

export interface BrandDto {
  id: string;
  name: string;
  slug: string;
  url: string;
  seoTitle: string | null;
  seoDescription: string | null;
  createdAt: string;
  updatedAt: string;
}

export interface ProductSummaryDto {
  id: string;
  name: string;
  slug: string;
  url: string;
  images?: ProductImageDto[];
  description: string | null;
  state: 'draft' | 'active' | 'archived';
  seoTitle: string | null;
  seoDescription: string | null;
  categoryIds: string[];
  brandId: string | null;
  createdAt: string;
  updatedAt: string;
}

interface ProductSearchResponse {
  items: ProductSummaryDto[];
}

interface CategoryTreeResponse {
  items: CategoryTreeNodeDto[];
}

interface BrandListResponse {
  items: BrandDto[];
}

export interface SearchProductsInput {
  q?: string;
  brandSlug?: string;
  categorySlug?: string;
  limit?: number;
  offset?: number;
}

const DEFAULT_API_BASE_URL = 'http://localhost:3000';

function apiBaseUrl(): string {
  return (
    process.env.API_BASE_URL ??
    process.env.NEXT_PUBLIC_API_BASE_URL ??
    DEFAULT_API_BASE_URL
  ).replace(/\/$/, '');
}

function toQueryString(input: SearchProductsInput): string {
  const params = new URLSearchParams();
  if (input.q !== undefined && input.q.trim() !== '') params.set('q', input.q.trim());
  if (input.brandSlug !== undefined && input.brandSlug.trim() !== '') {
    params.set('brandSlug', input.brandSlug.trim());
  }
  if (input.categorySlug !== undefined && input.categorySlug.trim() !== '') {
    params.set('categorySlug', input.categorySlug.trim());
  }
  if (input.limit !== undefined) params.set('limit', String(input.limit));
  if (input.offset !== undefined) params.set('offset', String(input.offset));
  const query = params.toString();
  return query === '' ? '' : `?${query}`;
}

async function fetchJson<T>(path: string): Promise<T> {
  const response = await fetch(`${apiBaseUrl()}${path}`, {
    headers: { accept: 'application/json' },
    next: { revalidate: 60 },
  });
  if (!response.ok) {
    throw new Error(`Public API request failed with status ${response.status}`);
  }
  return (await response.json()) as T;
}

export async function searchProducts(
  input: SearchProductsInput = {},
): Promise<ProductSummaryDto[]> {
  const payload = await fetchJson<ProductSearchResponse>(`/products/search${toQueryString(input)}`);
  return payload.items;
}

export async function getProductBySlug(slug: string): Promise<ProductSummaryDto> {
  return fetchJson<ProductSummaryDto>(`/productos/${encodeURIComponent(slug)}`);
}

export async function getCategoryBySlug(slug: string): Promise<CategoryDto> {
  return fetchJson<CategoryDto>(`/categoria/${encodeURIComponent(slug)}`);
}

export async function listCategoryTree(): Promise<CategoryTreeNodeDto[]> {
  const payload = await fetchJson<CategoryTreeResponse>('/categories/tree');
  return payload.items;
}

export async function getBrandBySlug(slug: string): Promise<BrandDto> {
  return fetchJson<BrandDto>(`/marca/${encodeURIComponent(slug)}`);
}

export async function listBrands(): Promise<BrandDto[]> {
  const payload = await fetchJson<BrandListResponse>('/brands');
  return payload.items;
}
