/**
 * Browser/React Native-safe feature flag client for platform-service.
 *
 * Polls GET /api/flags/poll on a configurable interval and caches results.
 * No Node.js dependencies — uses globalThis.fetch.
 *
 * @example
 * ```ts
 * import { createFeatureFlagClient } from '@bytelyst/feature-flag-client';
 *
 * const flags = createFeatureFlagClient({
 *   baseUrl: 'http://localhost:4003/api',
 *   productId: 'nomgap',
 *   platform: 'mobile',
 * });
 *
 * await flags.init({ userId: 'user-123' });
 * if (flags.isEnabled('premium_body_viz')) { ... }
 * ```
 */

import type { FeatureFlagClient, FeatureFlagClientConfig } from './types.js';

export function createFeatureFlagClient(config: FeatureFlagClientConfig): FeatureFlagClient {
  const {
    baseUrl,
    productId,
    platform,
    pollIntervalMs = 5 * 60 * 1000,
    storage,
    storagePrefix,
  } = config;

  const prefix = storagePrefix ?? productId;
  const STORAGE_KEY = `${prefix}-feature-flags`;

  let flags: Record<string, boolean> = {};
  let initialized = false;
  let intervalId: ReturnType<typeof setInterval> | null = null;
  let userId: string | undefined;

  // Restore from storage on creation
  if (storage) {
    try {
      const cached = storage.getItem(STORAGE_KEY);
      if (cached) flags = JSON.parse(cached);
    } catch {
      // Ignore parse errors
    }
  }

  async function fetchFlags(): Promise<void> {
    try {
      const parts = [`platform=${encodeURIComponent(platform)}`];
      if (userId) parts.push(`userId=${encodeURIComponent(userId)}`);

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

      const res = await globalThis.fetch(`${baseUrl}/flags/poll?${parts.join('&')}`, {
        headers: { 'x-product-id': productId, 'x-request-id': requestId },
      });

      if (!res.ok) return;

      const data = (await res.json()) as { flags?: Record<string, boolean> };
      flags = data.flags ?? {};

      // Persist to storage
      if (storage) {
        try {
          storage.setItem(STORAGE_KEY, JSON.stringify(flags));
        } catch {
          // Storage write failure — non-fatal
        }
      }
    } catch {
      // Keep existing flags on network error
    }
  }

  async function init(params?: { userId?: string }): Promise<void> {
    if (initialized) return;
    initialized = true;
    userId = params?.userId;
    await fetchFlags();
    intervalId = setInterval(() => {
      void fetchFlags();
    }, pollIntervalMs);
  }

  function isEnabled(key: string): boolean {
    return flags[key] === true;
  }

  function getAllFlags(): Readonly<Record<string, boolean>> {
    return flags;
  }

  async function refresh(): Promise<void> {
    await fetchFlags();
  }

  function stop(): void {
    if (intervalId) clearInterval(intervalId);
    intervalId = null;
    flags = {};
    initialized = false;
    userId = undefined;
  }

  return { init, isEnabled, getAllFlags, refresh, stop };
}
