/**
 * GA4 Freshness Contract
 * ──────────────────────
 * Provides stale-while-revalidate semantics for GA4 data:
 *   - Checks MetricSnapshot.updatedAt for the most recent ga4 row
 *   - If older than STALE_THRESHOLD_MS (8 hours), triggers a background sync
 *   - Rate-limited to one trigger per brand per THROTTLE_MS (30 minutes)
 */

import { prisma } from "@/lib/prisma";
import { googleAnalytics } from "@/lib/integrations/google-analytics";
import { getCredentials } from "@/lib/services/integration-credentials";

const STALE_THRESHOLD_MS = 8 * 60 * 60 * 1000; // 8 hours
const THROTTLE_MS = 30 * 60 * 1000; // 30 minutes

const lastTriggered = new Map<string, number>();

export async function triggerGa4RefreshIfStale(brandId: string): Promise<void> {
  const now = Date.now();
  const lastTime = lastTriggered.get(brandId) ?? 0;
  if (now - lastTime < THROTTLE_MS) return;

  const integration = await prisma.brandIntegration.findFirst({
    where: { brandId, integrationId: "ga4", connected: true },
    select: { id: true },
  });
  if (!integration) return;

  const latestSnapshot = await prisma.metricSnapshot.findFirst({
    where: { brandId, source: "ga4" },
    orderBy: { updatedAt: "desc" },
    select: { updatedAt: true },
  });

  if (latestSnapshot && now - latestSnapshot.updatedAt.getTime() < STALE_THRESHOLD_MS) {
    return;
  }

  lastTriggered.set(brandId, now);

  // Fire-and-forget background sync
  (async () => {
    try {
      const creds = await getCredentials(brandId, "ga4");
      if (!creds?.propertyId) return;
      const result = await googleAnalytics.sync(brandId, creds);
      console.info(`[ga4-freshness] auto-refresh for ${brandId}: ${result.message}`);
    } catch (err) {
      console.error(`[ga4-freshness] auto-refresh failed for ${brandId}:`, err instanceof Error ? err.message : String(err));
    }
  })();
}

/**
 * Get freshness status for a brand's data sources.
 * Used by admin dashboards and signal generation.
 */
export async function getSourceFreshness(brandId: string) {
  const [ga4Latest, gscLatest, siteTagLatest, dfseoLatest] = await Promise.all([
    prisma.metricSnapshot.findFirst({
      where: { brandId, source: "ga4" },
      orderBy: { updatedAt: "desc" },
      select: { date: true, updatedAt: true },
    }).catch(() => null),

    prisma.metricSnapshot.findFirst({
      where: { brandId, source: "gsc" },
      orderBy: { updatedAt: "desc" },
      select: { date: true, updatedAt: true },
    }).catch(() => null),

    // TrackedSite.lastEventAt is a maintained denormalized field that
    // mirrors max(TrackedEvent.timestamp). Using it avoids an ORDER BY
    // on the large TrackedEvent table and accurately reflects any site
    // activity (page views, clicks) rather than only conversions —
    // which previously caused false "sync stalled" alerts on sites
    // with real traffic but no overnight conversions.
    prisma.trackedSite.findUnique({
      where: { brandId },
      select: { lastEventAt: true },
    }).catch(() => null),

    prisma.keywordRanking.findFirst({
      where: { trackedKeyword: { brandId } },
      orderBy: { checkedAt: "desc" },
      select: { checkedAt: true },
    }).catch(() => null),
  ]);

  function status(lastAt: Date | null | undefined): "fresh" | "stale" | "critical" | "none" {
    if (!lastAt) return "none";
    const hoursAgo = (Date.now() - lastAt.getTime()) / 3_600_000;
    if (hoursAgo <= 12) return "fresh";
    if (hoursAgo <= 48) return "stale";
    return "critical";
  }

  return {
    ga4: {
      lastDate: ga4Latest?.date?.toISOString().split("T")[0] ?? null,
      lastUpdatedAt: ga4Latest?.updatedAt?.toISOString() ?? null,
      status: status(ga4Latest?.updatedAt),
    },
    gsc: {
      lastDate: gscLatest?.date?.toISOString().split("T")[0] ?? null,
      lastUpdatedAt: gscLatest?.updatedAt?.toISOString() ?? null,
      status: status(gscLatest?.updatedAt),
    },
    siteTag: {
      lastEventAt: siteTagLatest?.lastEventAt?.toISOString() ?? null,
      status: status(siteTagLatest?.lastEventAt),
    },
    dataforseo: {
      lastUpdatedAt: dfseoLatest?.checkedAt?.toISOString() ?? null,
      status: status(dfseoLatest?.checkedAt),
    },
  };
}
