/**
 * Google Analytics 4 Integration
 * ---------------------------------
 * Auth: OAuth 2.0
 * API: https://analyticsdata.googleapis.com/v1beta
 */

import type { IntegrationCredentials } from "@/lib/services/integration-credentials";
import { SyncService, SyncResult, apiCall, apiCallAuthed } from "./types";
import { storeGa4Data } from "@/lib/services/ga4-sync";

const API_BASE = "https://analyticsdata.googleapis.com/v1beta";

export const googleAnalytics: SyncService = {
  id: "ga4",
  name: "Google Analytics 4",

  async connect(brandId: string, creds?: IntegrationCredentials): Promise<SyncResult> {
    if (!creds?.accessToken || !creds?.propertyId) {
      return { success: false, message: "GA4 requires an OAuth access token and a property ID." };
    }

    const res = await apiCall(`${API_BASE}/properties/${creds.propertyId}/metadata`, {
      bearerToken: creds.accessToken,
    });

    if (!res.ok) return { success: false, message: `GA4 connection failed: ${res.error}` };

    return { success: true, message: "Google Analytics 4 connected.", credentials: creds };
  },

  async disconnect(): Promise<SyncResult> {
    return { success: true, message: "Google Analytics 4 disconnected." };
  },

  async sync(brandId: string, creds?: IntegrationCredentials): Promise<SyncResult> {
    if (!creds?.propertyId) {
      return { success: false, message: "No credentials — reconnect GA4." };
    }

    // apiCallAuthed owns the token lifecycle: proactively refreshes tokens
    // expiring within 5 minutes, and force-refreshes on a 401. Only a truly
    // revoked refresh_token falls through as an auth failure.
    let res: Awaited<ReturnType<typeof apiCallAuthed>>;
    try {
      res = await apiCallAuthed(
        `${API_BASE}/properties/${creds.propertyId}:runReport`,
        {
          method: "POST",
          body: {
            dateRanges: [{ startDate: "28daysAgo", endDate: "today" }],
            dimensions: [{ name: "date" }],
            metrics: [
              { name: "sessions" },
              { name: "totalUsers" },
              { name: "screenPageViews" },
              { name: "conversions" },
            ],
          },
        },
        { brandId, integrationId: "ga4" },
      );
    } catch (err) {
      const msg = err instanceof Error ? err.message : "Reconnect GA4";
      return { success: false, message: msg };
    }

    if (!res.ok) {
      if (res.status === 401) {
        return { success: false, message: "GA4 refresh token revoked — reconnect GA4." };
      }
      return { success: false, message: `GA4 sync failed: ${res.error}` };
    }

    const data = res.data as {
      rows?: Array<{
        dimensionValues?: Array<{ value: string }>;
        metricValues?: Array<{ value: string }>;
      }>;
    };

    // Parse and store the data
    const rows = (data.rows ?? []).map(row => {
      const dims = row.dimensionValues ?? [];
      const mets = row.metricValues ?? [];
      // Format date from YYYYMMDD to YYYY-MM-DD
      const rawDate = dims[0]?.value ?? "";
      const date = rawDate.length === 8
        ? `${rawDate.slice(0, 4)}-${rawDate.slice(4, 6)}-${rawDate.slice(6, 8)}`
        : rawDate;
      return {
        date,
        sessions: parseInt(mets[0]?.value ?? "0", 10),
        users: parseInt(mets[1]?.value ?? "0", 10),
        pageViews: parseInt(mets[2]?.value ?? "0", 10),
        conversions: parseInt(mets[3]?.value ?? "0", 10),
        bounceRate: 0,
      };
    });

    const stored = await storeGa4Data(brandId, rows, "28daysAgo", "today");

    const totalSessions = rows.reduce((s, r) => s + r.sessions, 0);
    const totalUsers = rows.reduce((s, r) => s + r.users, 0);

    return {
      success: true,
      message: `Synced ${stored} days: ${totalSessions.toLocaleString()} sessions, ${totalUsers.toLocaleString()} users.`,
      data: { stored, totalSessions, totalUsers },
    };
  },
};
