/**
 * Backend Analytics Client
 *
 * Fire-and-forget event tracking for server-side environments.
 * Does not block on event delivery.
 */

import type { EventMetadata } from '../types';
import { BatchQueue, type BatchQueueConfig } from './BatchQueue';
import { collectServerMetadata } from './metadata';

/** Simplified tracking event for backend SDK */
interface TrackingEvent {
  eventType: string;
  timestamp: string;
  sessionId?: string;
  userId?: string;
  properties: Record<string, unknown>;
  metadata: EventMetadata;
  [key: string]: unknown;
}

export interface BackendClientConfig {
  /** Analytics collector endpoint URL */
  endpoint: string;
  /** Service name for attribution */
  serviceName: string;
  /** Batch configuration */
  batch?: Partial<BatchQueueConfig>;
  /** Custom headers to include in requests */
  headers?: Record<string, string>;
  /** Enable debug logging */
  debug?: boolean;
}

export class BackendAnalyticsClient {
  private readonly endpoint: string;
  private readonly serviceName: string;
  private readonly queue: BatchQueue;
  private readonly headers: Record<string, string>;
  private readonly debug: boolean;

  constructor(config: BackendClientConfig) {
    this.endpoint = config.endpoint;
    this.serviceName = config.serviceName;
    this.headers = config.headers ?? {};
    this.debug = config.debug ?? false;

    this.queue = new BatchQueue({
      maxSize: config.batch?.maxSize ?? 50,
      maxWait: config.batch?.maxWait ?? 10000,
      onFlush: (events) => this.sendEvents(events as TrackingEvent[]),
    });
  }

  /**
   * Track an event (fire-and-forget)
   */
  track(
    eventType: string,
    properties?: Record<string, unknown>,
    context?: { userId?: string; sessionId?: string },
  ): void {
    const event: TrackingEvent = {
      eventType,
      timestamp: new Date().toISOString(),
      sessionId: context?.sessionId,
      userId: context?.userId,
      properties: {
        ...properties,
        $service: this.serviceName,
      },
      metadata: collectServerMetadata(),
    };

    if (this.debug) {
      console.log('[Analytics Backend] Track:', event);
    }

    this.queue.add(event);
  }

  /**
   * Flush pending events immediately
   */
  async flush(): Promise<void> {
    await this.queue.flush();
  }

  /**
   * Graceful shutdown - flush remaining events
   */
  async shutdown(): Promise<void> {
    await this.flush();
  }

  private async sendEvents(events: TrackingEvent[]): Promise<void> {
    if (events.length === 0) return;

    try {
      const response = await fetch(`${this.endpoint}/collect`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          ...this.headers,
        },
        body: JSON.stringify({ events }),
      });

      if (!response.ok) {
        throw new Error(`Analytics request failed: ${response.status}`);
      }

      if (this.debug) {
        console.log(`[Analytics Backend] Sent ${events.length} events`);
      }
    } catch (error) {
      // Fire-and-forget: log but don't throw
      console.error('[Analytics Backend] Failed to send events:', error);
    }
  }
}
