import "server-only";

import {
  normalizeGoogleAnalyticsClientId,
  normalizeGoogleAnalyticsSessionId,
  toGoogleAnalyticsClientId,
} from "@/lib/google-analytics-client-id";

const EVENT_NAMES = {
  dns_record_confirmed: "dns_record_confirmed",
  dns_setup_viewed: "dns_setup_viewed",
  dns_verification_attempted: "dns_verification_attempted",
  dns_verification_failed: "dns_verification_failed",
  dns_wizard_step_viewed: "dns_wizard_step_viewed",
  domain_verified: "domain_verified",
  growth_plan_started: "growth_plan_started",
  payment_method_added: "add_payment_info",
  purchase_completed: "purchase",
  signup_failed: "signup_failed",
  signup_form_viewed: "signup_form_viewed",
  signup_recovery_sent: "signup_recovery_sent",
  signup_recovery_verified: "signup_recovery_verified",
  signup_submitted: "signup_submitted",
  signup_completed: "sign_up",
} as const;

const DNS_STEP_EVENT_NAMES: Record<string, string> = {
  provider: "dns_step_provider",
  website_connection: "dns_step_website_connection",
  website_hosting: "dns_step_website_hosting",
  dns_location: "dns_step_dns_location",
  domain_registration: "dns_step_domain_registration",
  record_mx_1: "dns_step_record_mx",
  record_spf_2: "dns_step_record_spf",
  record_dkim_3: "dns_step_record_dkim",
  record_dmarc_4: "dns_step_record_dmarc",
  verification: "dns_step_verification",
};

function getDnsRecordKind(detail: string | null | undefined) {
  return ["mx", "spf", "dkim", "dmarc"].find((kind) =>
    detail?.includes(`_${kind}_`),
  ) ?? null;
}

function getGoogleAnalyticsEventName(input: {
  eventDetail?: string | null;
  eventType: LifecycleEventName;
}) {
  if (input.eventType === "dns_wizard_step_viewed" && input.eventDetail) {
    const namedStep = DNS_STEP_EVENT_NAMES[input.eventDetail];
    if (namedStep) return namedStep;
    const recordKind = getDnsRecordKind(input.eventDetail);
    return recordKind
      ? `dns_step_record_${recordKind}`
      : EVENT_NAMES[input.eventType];
  }
  const recordKind = getDnsRecordKind(input.eventDetail);
  if (input.eventType === "dns_record_confirmed" && recordKind) {
    return `dns_record_${recordKind}_confirmed`;
  }
  if (input.eventType === "dns_verification_failed") {
    return `dns_verify_failed_${recordKind ?? "pending"}`;
  }
  return EVENT_NAMES[input.eventType];
}

type LifecycleEventName = keyof typeof EVENT_NAMES;

function getGoogleAnalyticsConfig() {
  const measurementId = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_ID?.trim() ?? "";
  const apiSecret = process.env.GOOGLE_ANALYTICS_API_SECRET?.trim() ?? "";

  if (!/^G-[A-Z0-9]+$/i.test(measurementId) || !apiSecret) {
    return null;
  }

  return { apiSecret, measurementId };
}

export async function sendGoogleAnalyticsLifecycleEvent(input: {
  eventType: LifecycleEventName;
  eventReference?: string | null;
  eventDetail?: string | null;
  gaClientId?: string | null;
  gaSessionId?: string | null;
  currency?: string | null;
  userId?: number | null;
  value?: number | null;
  visitorId?: string | null;
}) {
  const config = getGoogleAnalyticsConfig();

  if (!config) {
    return false;
  }

  const clientId =
    normalizeGoogleAnalyticsClientId(input.gaClientId) ??
    toGoogleAnalyticsClientId(input.visitorId, input.userId ?? undefined);
  const sessionId = normalizeGoogleAnalyticsSessionId(input.gaSessionId);
  const currency = /^[A-Z]{3}$/.test(input.currency?.trim().toUpperCase() ?? "")
    ? input.currency!.trim().toUpperCase()
    : null;
  const value = Number.isFinite(input.value) && Number(input.value) >= 0
    ? Number(input.value)
    : null;
  const params: Record<string, unknown> = {
    engagement_time_msec: 1,
  };
  if (sessionId) params.session_id = Number(sessionId);
  if (input.eventDetail) params.funnel_step = input.eventDetail;
  if (input.eventType === "payment_method_added") params.payment_type = "card";
  if (input.eventType === "purchase_completed") {
    params.transaction_id = input.eventReference;
    if (currency) params.currency = currency;
    if (value !== null) params.value = value;
  }
  const url = new URL("https://www.google-analytics.com/mp/collect");
  url.searchParams.set("api_secret", config.apiSecret);
  url.searchParams.set("measurement_id", config.measurementId);

  try {
    const response = await fetch(url, {
      body: JSON.stringify({
        client_id: clientId,
        events: [
          {
            name: getGoogleAnalyticsEventName(input),
            params,
          },
        ],
        ...(input.userId ? { user_id: String(input.userId) } : {}),
      }),
      headers: { "Content-Type": "application/json" },
      method: "POST",
      signal: AbortSignal.timeout(3_000),
    });

    return response.ok;
  } catch (error) {
    console.error(
      "Google Analytics lifecycle event delivery failed",
      error instanceof Error ? error.message : "unknown error",
    );
    return false;
  }
}
