import { analyticsEnv } from '../config/analytics.config';

const GA4_ENDPOINT = 'https://www.google-analytics.com/mp/collect';

export class GA4Service {
  private measurementId: string;
  private apiSecret: string;
  private initialized = false;

  constructor() {
    this.measurementId = analyticsEnv.GA4_MEASUREMENT_ID;
    this.apiSecret = analyticsEnv.GA4_API_SECRET || '';
  }

  async initialize(): Promise<void> {
    if (!this.measurementId || this.measurementId === 'placeholder') {
      console.warn('GA4: no measurement ID configured — events will be dropped');
      return;
    }
    if (!this.apiSecret) {
      console.warn('GA4: no API secret configured — events will be dropped');
      return;
    }
    this.initialized = true;
  }

  private async post(eventName: string, params: Record<string, unknown>): Promise<void> {
    if (!this.initialized) {
      console.log('GA4 (dry):', eventName, params);
      return;
    }

    try {
      const url = `${GA4_ENDPOINT}?measurement_id=${this.measurementId}&api_secret=${this.apiSecret}`;
      const res = await fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          client_id: params.client_id || 'system',
          events: [{ name: eventName, params }],
        }),
      });

      if (!res.ok && res.status !== 204) {
        console.error(`GA4 error: ${res.status} for event ${eventName}`);
      }
    } catch (err) {
      console.error('GA4 send failed:', err);
    }
  }

  async trackPageView(clientId: string, path: string, title?: string): Promise<void> {
    await this.post('page_view', {
      client_id: clientId,
      page_path: path,
      page_title: title || undefined,
      engagement_time_msec: 1,
    });
  }

  async trackPurchase(
    clientId: string,
    transactionId: string,
    value: number,
    currency: string,
    items: Array<{ item_id: string; item_name: string; price: number; quantity: number }>,
  ): Promise<void> {
    await this.post('purchase', {
      client_id: clientId,
      transaction_id: transactionId,
      value,
      currency,
      items,
    });
  }

  async trackWaitlistSignup(clientId: string, email?: string): Promise<void> {
    await this.post('waitlist_signup', {
      client_id: clientId,
      email_hash: email ? await this.sha256(email) : undefined,
    });
  }

  async trackConversion(
    clientId: string,
    conversionName: string,
    metadata?: Record<string, unknown>,
  ): Promise<void> {
    await this.post(conversionName, {
      client_id: clientId,
      ...metadata,
    });
  }

  async getMetrics(
    dateRange: { startDate: string; endDate: string },
    metrics: string[],
    dimensions?: string[],
  ): Promise<{ rows: unknown[]; totals: unknown[] }> {
    if (!this.measurementId || this.measurementId === 'placeholder') {
      return { rows: [], totals: [] };
    }

    const DataApi = await import('@google-analytics/data').catch(() => null);
    if (!DataApi) {
      console.warn('GA4: @google-analytics/data not installed — cannot query metrics');
      return { rows: [], totals: [] };
    }

    try {
      const client = new DataApi.BetaAnalyticsDataClient();
      const [response] = await client.runReport({
        property: `properties/${this.measurementId.replace('G-', '')}`,
        dateRanges: [dateRange],
        metrics: metrics.map(m => ({ name: m })),
        dimensions: (dimensions || []).map(d => ({ name: d })),
      });
      return {
        rows: response.rows || [],
        totals: response.totals || [],
      };
    } catch (err) {
      console.error('GA4 query failed:', err);
      return { rows: [], totals: [] };
    }
  }

  private async sha256(str: string): Promise<string> {
    const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(str.toLowerCase().trim()));
    return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');
  }
}

export const ga4Service = new GA4Service();
