/**
 * Browser/React Native-safe marketplace client for platform-service.
 *
 * Wraps platform-service /marketplace/* endpoints.
 * No Node.js dependencies — uses globalThis.fetch.
 */

import type {
  CreateListingInput,
  MarketplaceClient,
  MarketplaceClientConfig,
  MarketplaceInstallDoc,
  MarketplaceListingDoc,
  MarketplaceReviewDoc,
} from './types.js';

function generateRequestId(): string {
  return typeof globalThis.crypto?.randomUUID === 'function'
    ? globalThis.crypto.randomUUID()
    : `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
}

export function createMarketplaceClient(config: MarketplaceClientConfig): MarketplaceClient {
  const { baseUrl, productId, getAccessToken } = config;

  function headers(): Record<string, string> {
    const h: Record<string, string> = {
      'Content-Type': 'application/json',
      'x-product-id': productId,
      'x-request-id': generateRequestId(),
    };
    const token = getAccessToken();
    if (token) h['Authorization'] = `Bearer ${token}`;
    return h;
  }

  // ── Listings ──────────────────────────────────────

  async function listListings(query?: {
    templateType?: string;
    category?: string;
    tags?: string;
    pricingModel?: string;
    sortBy?: string;
    q?: string;
    limit?: number;
    offset?: number;
  }): Promise<{ listings: MarketplaceListingDoc[]; total: number }> {
    const params = new URLSearchParams();
    if (query?.templateType) params.set('templateType', query.templateType);
    if (query?.category) params.set('category', query.category);
    if (query?.tags) params.set('tags', query.tags);
    if (query?.pricingModel) params.set('pricingModel', query.pricingModel);
    if (query?.sortBy) params.set('sortBy', query.sortBy);
    if (query?.q) params.set('q', query.q);
    if (query?.limit) params.set('limit', String(query.limit));
    if (query?.offset) params.set('offset', String(query.offset));
    const qs = params.toString();
    const url = qs ? `${baseUrl}/marketplace/listings?${qs}` : `${baseUrl}/marketplace/listings`;
    const res = await globalThis.fetch(url, { headers: headers() });
    if (!res.ok) throw new Error(`listListings failed: ${res.status}`);
    return (await res.json()) as { listings: MarketplaceListingDoc[]; total: number };
  }

  async function getListing(id: string): Promise<MarketplaceListingDoc> {
    const res = await globalThis.fetch(
      `${baseUrl}/marketplace/listings/${encodeURIComponent(id)}`,
      { headers: headers() }
    );
    if (!res.ok) throw new Error(`getListing failed: ${res.status}`);
    return (await res.json()) as MarketplaceListingDoc;
  }

  async function createListing(input: CreateListingInput): Promise<MarketplaceListingDoc> {
    const res = await globalThis.fetch(`${baseUrl}/marketplace/listings`, {
      method: 'POST',
      headers: headers(),
      body: JSON.stringify(input),
    });
    if (!res.ok) throw new Error(`createListing failed: ${res.status}`);
    return (await res.json()) as MarketplaceListingDoc;
  }

  async function updateListing(
    id: string,
    updates: Partial<MarketplaceListingDoc>
  ): Promise<MarketplaceListingDoc> {
    const res = await globalThis.fetch(
      `${baseUrl}/marketplace/listings/${encodeURIComponent(id)}`,
      {
        method: 'PATCH',
        headers: headers(),
        body: JSON.stringify(updates),
      }
    );
    if (!res.ok) throw new Error(`updateListing failed: ${res.status}`);
    return (await res.json()) as MarketplaceListingDoc;
  }

  async function submitForCertification(
    id: string,
    notes?: string
  ): Promise<MarketplaceListingDoc> {
    const res = await globalThis.fetch(
      `${baseUrl}/marketplace/listings/${encodeURIComponent(id)}/submit`,
      {
        method: 'POST',
        headers: headers(),
        body: JSON.stringify({ notes }),
      }
    );
    if (!res.ok) throw new Error(`submitForCertification failed: ${res.status}`);
    return (await res.json()) as MarketplaceListingDoc;
  }

  // ── Installs ──────────────────────────────────────

  async function installListing(listingId: string): Promise<MarketplaceInstallDoc> {
    const res = await globalThis.fetch(
      `${baseUrl}/marketplace/listings/${encodeURIComponent(listingId)}/install`,
      {
        method: 'POST',
        headers: headers(),
      }
    );
    if (!res.ok) throw new Error(`installListing failed: ${res.status}`);
    return (await res.json()) as MarketplaceInstallDoc;
  }

  async function uninstallListing(listingId: string): Promise<void> {
    const res = await globalThis.fetch(
      `${baseUrl}/marketplace/listings/${encodeURIComponent(listingId)}/uninstall`,
      {
        method: 'POST',
        headers: headers(),
      }
    );
    if (!res.ok) throw new Error(`uninstallListing failed: ${res.status}`);
  }

  async function listMyInstalls(query?: {
    limit?: number;
    offset?: number;
  }): Promise<MarketplaceInstallDoc[]> {
    const params = new URLSearchParams();
    if (query?.limit) params.set('limit', String(query.limit));
    if (query?.offset) params.set('offset', String(query.offset));
    const qs = params.toString();
    const url = qs ? `${baseUrl}/marketplace/installs?${qs}` : `${baseUrl}/marketplace/installs`;
    const res = await globalThis.fetch(url, { headers: headers() });
    if (!res.ok) throw new Error(`listMyInstalls failed: ${res.status}`);
    return (await res.json()) as MarketplaceInstallDoc[];
  }

  // ── Reviews ───────────────────────────────────────

  async function listReviews(
    listingId: string,
    query?: { sortBy?: string; limit?: number }
  ): Promise<MarketplaceReviewDoc[]> {
    const params = new URLSearchParams();
    if (query?.sortBy) params.set('sortBy', query.sortBy);
    if (query?.limit) params.set('limit', String(query.limit));
    const qs = params.toString();
    const url = qs
      ? `${baseUrl}/marketplace/listings/${encodeURIComponent(listingId)}/reviews?${qs}`
      : `${baseUrl}/marketplace/listings/${encodeURIComponent(listingId)}/reviews`;
    const res = await globalThis.fetch(url, { headers: headers() });
    if (!res.ok) throw new Error(`listReviews failed: ${res.status}`);
    return (await res.json()) as MarketplaceReviewDoc[];
  }

  async function createReview(
    listingId: string,
    input: { rating: number; title: string; body: string }
  ): Promise<MarketplaceReviewDoc> {
    const res = await globalThis.fetch(
      `${baseUrl}/marketplace/listings/${encodeURIComponent(listingId)}/reviews`,
      {
        method: 'POST',
        headers: headers(),
        body: JSON.stringify(input),
      }
    );
    if (!res.ok) throw new Error(`createReview failed: ${res.status}`);
    return (await res.json()) as MarketplaceReviewDoc;
  }

  // ── Reports ───────────────────────────────────────

  async function reportListing(
    listingId: string,
    input: { reason: string; details: string }
  ): Promise<void> {
    const res = await globalThis.fetch(
      `${baseUrl}/marketplace/listings/${encodeURIComponent(listingId)}/report`,
      {
        method: 'POST',
        headers: headers(),
        body: JSON.stringify(input),
      }
    );
    if (!res.ok) throw new Error(`reportListing failed: ${res.status}`);
  }

  return {
    listListings,
    getListing,
    createListing,
    updateListing,
    submitForCertification,
    installListing,
    uninstallListing,
    listMyInstalls,
    listReviews,
    createReview,
    reportListing,
  };
}
