export interface MarketplaceClientOptions {
  baseUrl: string;
  productId: string;
  getAccessToken: () => string;
}

export interface MarketplaceListing {
  id: string;
  title: string;
  description: string;
  category: string;
  author: string;
  downloads: number;
}

function joinUrl(base: string, path: string): string {
  const b = base.replace(/\/$/, "");
  const p = path.startsWith("/") ? path : `/${path}`;
  return `${b}${p}`;
}

function headers(opts: MarketplaceClientOptions): HeadersInit {
  return {
    Authorization: `Bearer ${opts.getAccessToken()}`,
    "X-Product-Id": opts.productId,
    Accept: "application/json",
    "Content-Type": "application/json",
  };
}

async function parseJson<T>(res: Response): Promise<T> {
  if (!res.ok) {
    const text = await res.text();
    throw new Error(`HTTP ${res.status}: ${text || res.statusText}`);
  }
  return res.json() as Promise<T>;
}

export function createMarketplaceClient(opts: MarketplaceClientOptions) {
  const { baseUrl } = opts;

  return {
    async listListings(listOpts?: {
      category?: string;
    }): Promise<MarketplaceListing[]> {
      const q = new URLSearchParams();
      if (listOpts?.category !== undefined && listOpts.category !== "") {
        q.set("category", listOpts.category);
      }
      const query = q.toString();
      const path =
        query.length > 0
          ? `/marketplace/listings?${query}`
          : "/marketplace/listings";
      const res = await fetch(joinUrl(baseUrl, path), {
        method: "GET",
        headers: headers(opts),
      });
      return parseJson<MarketplaceListing[]>(res);
    },

    async installListing(
      listingId: string
    ): Promise<{ success: boolean }> {
      const res = await fetch(
        joinUrl(
          baseUrl,
          `/marketplace/listings/${encodeURIComponent(listingId)}/install`
        ),
        { method: "POST", headers: headers(opts), body: "{}" }
      );
      return parseJson<{ success: boolean }>(res);
    },
  };
}
