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

import type { ReferralClient, ReferralClientConfig, ReferralDoc } 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 createReferralClient(config: ReferralClientConfig): ReferralClient {
  const { baseUrl, productId, getAccessToken, defaultRewardTokens } = config;

  const defaultReferrerTokens = defaultRewardTokens?.referrer ?? 1000;
  const defaultReferredTokens = defaultRewardTokens?.referred ?? 500;

  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;
  }

  async function listMyReferrals(
    referrerId: string
  ): Promise<{ referrals: ReferralDoc[]; count: number }> {
    const res = await globalThis.fetch(
      `${baseUrl}/referrals/by-referrer/${encodeURIComponent(referrerId)}`,
      { headers: headers() }
    );
    if (!res.ok) throw new Error(`listMyReferrals failed: ${res.status}`);
    const data = (await res.json()) as { referrals: ReferralDoc[]; count: number };
    return data;
  }

  async function getReferralStats(): Promise<{
    total: number;
    completed: number;
    rewarded: number;
  }> {
    const res = await globalThis.fetch(`${baseUrl}/referrals/stats`, { headers: headers() });
    if (!res.ok) throw new Error(`getReferralStats failed: ${res.status}`);
    return (await res.json()) as { total: number; completed: number; rewarded: number };
  }

  async function createReferral(input: {
    referrerId: string;
    referrerEmail: string;
    referredEmail: string;
  }): Promise<ReferralDoc> {
    const body = {
      ...input,
      productId,
      referrerRewardTokens: defaultReferrerTokens,
      referredRewardTokens: defaultReferredTokens,
    };
    const res = await globalThis.fetch(`${baseUrl}/referrals`, {
      method: 'POST',
      headers: headers(),
      body: JSON.stringify(body),
    });
    if (!res.ok) throw new Error(`createReferral failed: ${res.status}`);
    return (await res.json()) as ReferralDoc;
  }

  async function updateReferralStatus(
    id: string,
    referrerId: string,
    status: ReferralDoc['status']
  ): Promise<ReferralDoc> {
    const res = await globalThis.fetch(`${baseUrl}/referrals/${encodeURIComponent(id)}`, {
      method: 'PUT',
      headers: headers(),
      body: JSON.stringify({ referrerId, status }),
    });
    if (!res.ok) throw new Error(`updateReferralStatus failed: ${res.status}`);
    return (await res.json()) as ReferralDoc;
  }

  async function getByEmail(email: string): Promise<ReferralDoc | null> {
    const res = await globalThis.fetch(
      `${baseUrl}/referrals/by-email/${encodeURIComponent(email)}`,
      { headers: headers() }
    );
    if (res.status === 404) return null;
    if (!res.ok) throw new Error(`getByEmail failed: ${res.status}`);
    return (await res.json()) as ReferralDoc;
  }

  function buildShareLink(code: string): string {
    return `https://bytelyst.com/refer/${encodeURIComponent(code)}?product=${encodeURIComponent(productId)}`;
  }

  function buildShareMessage(code: string, productName: string): string {
    const link = buildShareLink(code);
    return `Try ${productName}! Use my referral link to get started: ${link}`;
  }

  function calculateEarnedDays(conversions: number, daysPerReferral = 7): number {
    return Math.max(0, conversions * daysPerReferral);
  }

  return {
    listMyReferrals,
    getReferralStats,
    createReferral,
    updateReferralStatus,
    getByEmail,
    buildShareLink,
    buildShareMessage,
    calculateEarnedDays,
  };
}
