// Google Analytics (GA4) service — ESM conversion of google-server/services/analytics.service.js.
// Phase 4: accepts injected ioredis client (was self-constructing node-redis v4 before).
// node-redis v4 set syntax `{ EX: 300 }` is translated to ioredis `setex(key, 300, val)`.

import { BetaAnalyticsDataClient } from '@google-analytics/data';

const CACHE_DURATIONS = {
  REALTIME_BASIC: 60,
  REALTIME_DETAILED: 300,
  BASIC_METRICS: 3600,
  USER_BEHAVIOR: 3600,
};

export class AnalyticsService {
  constructor(redis) {
    if (!redis) {
      throw new Error('AnalyticsService requires an ioredis client (Phase 4: injected)');
    }
    this.redis = redis;

    const credentials = process.env.GOOGLE_APPLICATION_CREDENTIALS_JSON;
    this.analyticsClient = new BetaAnalyticsDataClient({
      credentials: typeof credentials === 'string' ? JSON.parse(credentials) : credentials,
    });
    this.propertyId = process.env.GA_PROPERTY_ID;
  }

  get _redisReady() {
    return this.redis.status === 'ready' || this.redis.status === 'connect';
  }

  async _cacheGet(key) {
    if (!this._redisReady) return null;
    try {
      const raw = await this.redis.get(key);
      return raw ? JSON.parse(raw) : null;
    } catch (err) {
      console.warn('[AnalyticsService] cache get failed:', err.message);
      return null;
    }
  }

  async _cacheSet(key, value, ttlSec) {
    if (!this._redisReady) return;
    try {
      await this.redis.setex(key, ttlSec, JSON.stringify(value));
    } catch (err) {
      console.warn('[AnalyticsService] cache set failed:', err.message);
    }
  }

  async getBasicMetrics(startDate = '7daysAgo') {
    const cacheKey = `analytics:basic_metrics:${startDate}`;
    const cached = await this._cacheGet(cacheKey);
    if (cached) return cached;

    const [response] = await this.analyticsClient.runReport({
      property: `properties/${this.propertyId}`,
      dateRanges: [{ startDate, endDate: 'today' }],
      dimensions: [{ name: 'date' }],
      metrics: [
        { name: 'activeUsers' },
        { name: 'newUsers' },
        { name: 'averageSessionDuration' },
        { name: 'screenPageViews' },
        { name: 'bounceRate' },
        { name: 'conversions' },
      ],
      returnPropertyQuota: true,
    });

    await this._cacheSet(cacheKey, response, CACHE_DURATIONS.BASIC_METRICS);
    return response;
  }

  async getRealTimeBasicData() {
    const cacheKey = 'analytics:realtime:basic';
    const cached = await this._cacheGet(cacheKey);
    if (cached) return cached;

    const [userResponse] = await this.analyticsClient.runRealtimeReport({
      property: `properties/${this.propertyId}`,
      metrics: [{ name: 'activeUsers' }],
      returnPropertyQuota: true,
    });

    const [fiveMinResponse] = await this.analyticsClient.runRealtimeReport({
      property: `properties/${this.propertyId}`,
      metrics: [{ name: 'activeUsers' }],
      minuteRanges: [{ startMinutesAgo: 5, endMinutesAgo: 0 }],
    });

    const [timeSeriesResponse] = await this.analyticsClient.runRealtimeReport({
      property: `properties/${this.propertyId}`,
      dimensions: [{ name: 'minutesAgo' }],
      metrics: [{ name: 'activeUsers' }],
    });

    const response = {
      userResponse,
      fiveMinResponse,
      timeSeriesResponse,
      quotaInfo: {
        projectHourly: userResponse.propertyQuota.tokensPerProjectPerHour,
        daily: userResponse.propertyQuota.tokensPerDay,
        serverErrors: userResponse.propertyQuota.serverErrorsPerProjectPerHour,
        thresholdedRequests: userResponse.propertyQuota.potentiallyThresholdedRequestsPerHour,
      },
    };

    await this._cacheSet(cacheKey, response, CACHE_DURATIONS.REALTIME_BASIC);
    return response;
  }

  async getRealTimeDetailedData() {
    const cacheKey = 'analytics:realtime:detailed';
    const cached = await this._cacheGet(cacheKey);
    if (cached) return cached;

    const [pageResponse] = await this.analyticsClient.runRealtimeReport({
      property: `properties/${this.propertyId}`,
      dimensions: [{ name: 'unifiedScreenName' }],
      metrics: [{ name: 'screenPageViews' }],
      orderBy: [{ metric: { metricName: 'screenPageViews' }, desc: true }],
      limit: 25,
    });

    const [eventResponse] = await this.analyticsClient.runRealtimeReport({
      property: `properties/${this.propertyId}`,
      dimensions: [{ name: 'eventName' }],
      metrics: [{ name: 'eventCount' }],
      orderBy: [{ metric: { metricName: 'eventCount' }, desc: true }],
      limit: 25,
    });

    const [deviceResponse] = await this.analyticsClient.runRealtimeReport({
      property: `properties/${this.propertyId}`,
      dimensions: [{ name: 'deviceCategory' }],
      metrics: [{ name: 'activeUsers' }],
      orderBy: [{ metric: { metricName: 'activeUsers' }, desc: true }],
      limit: 10,
      returnPropertyQuota: true,
    });

    const response = {
      pageResponse,
      eventResponse,
      sourceResponse: deviceResponse,
    };

    await this._cacheSet(cacheKey, response, CACHE_DURATIONS.REALTIME_DETAILED);
    return response;
  }

  async getUserBehavior(timeRange = '30') {
    const cacheKey = `analytics:user_behavior:${timeRange}`;
    const cached = await this._cacheGet(cacheKey);
    if (cached) return cached;

    const [pageResponse] = await this.analyticsClient.runReport({
      property: `properties/${this.propertyId}`,
      dateRanges: [{ startDate: `${timeRange}daysAgo`, endDate: 'today' }],
      dimensions: [{ name: 'pagePath' }],
      metrics: [
        { name: 'screenPageViews' },
        { name: 'averageSessionDuration' },
        { name: 'bounceRate' },
        { name: 'sessions' },
      ],
      orderBy: [{ metric: { metricName: 'screenPageViews' }, desc: true }],
      limit: 25,
    });

    const [deviceResponse] = await this.analyticsClient.runReport({
      property: `properties/${this.propertyId}`,
      dateRanges: [{ startDate: `${timeRange}daysAgo`, endDate: 'today' }],
      dimensions: [{ name: 'deviceCategory' }],
      metrics: [{ name: 'screenPageViews' }, { name: 'sessions' }],
    });

    const [sourceResponse] = await this.analyticsClient.runReport({
      property: `properties/${this.propertyId}`,
      dateRanges: [{ startDate: `${timeRange}daysAgo`, endDate: 'today' }],
      dimensions: [{ name: 'sessionSource' }],
      metrics: [{ name: 'sessions' }, { name: 'conversions' }],
      orderBy: [{ metric: { metricName: 'sessions' }, desc: true }],
      limit: 25,
      returnPropertyQuota: true,
    });

    const response = { pageResponse, deviceResponse, sourceResponse };
    await this._cacheSet(cacheKey, response, CACHE_DURATIONS.USER_BEHAVIOR);
    return response;
  }
}
