/**
 * Global Privacy Control (GPC) signal detection and jurisdiction-aware
 * auto-opt-out.
 *
 * GPC is a browser-level signal (`navigator.globalPrivacyControl === true`)
 * that communicates a user's intent to opt out of the sale/sharing of their
 * personal data. Several US state laws legally require businesses to honour
 * this signal: California (CCPA/CPRA), Colorado (CPA), Connecticut (CTDPA),
 * Texas (TDPSA), and Montana (MTCDPA).
 *
 * @see https://globalprivacycontrol.github.io/gpc-spec/
 */

import type { CategorySlug } from './types';

// ── Types ────────────────────────────────────────────────────────────

declare global {
  interface Navigator {
    globalPrivacyControl?: boolean;
  }
}

/** Result of GPC detection and evaluation. */
export interface GpcResult {
  /** Whether the browser is sending the GPC signal. */
  detected: boolean;
  /** Whether GPC was honoured (auto-opt-out applied). */
  honoured: boolean;
  /** The visitor's detected region code (e.g. 'US-CA'), if available. */
  region: string | null;
}

/** GPC-related site configuration fields. */
export interface GpcConfig {
  /** Whether to detect GPC at all. */
  gpc_enabled: boolean;
  /** Region codes where GPC is legally required. */
  gpc_jurisdictions: string[];
  /** If true, honour GPC regardless of jurisdiction. */
  gpc_global_honour: boolean;
}

/** Default jurisdictions where GPC must be legally honoured. */
export const DEFAULT_GPC_JURISDICTIONS: string[] = [
  'US-CA', // California — CCPA/CPRA
  'US-CO', // Colorado — CPA
  'US-CT', // Connecticut — CTDPA
  'US-TX', // Texas — TDPSA
  'US-MT', // Montana — MTCDPA
];

// ── Detection ────────────────────────────────────────────────────────

/** Check whether the browser is sending the GPC signal. */
export function isGpcEnabled(): boolean {
  if (typeof navigator === 'undefined') return false;
  return navigator.globalPrivacyControl === true;
}

// ── Region detection ─────────────────────────────────────────────────

/**
 * Detect the visitor's region from the CMP context.
 *
 * Uses the `__cmp.visitorRegion` field, which is set by the loader
 * from GeoIP headers (e.g. Cloudflare's `CF-IPCountry` + `CF-Region`)
 * or from a GeoIP API call.
 */
export function getVisitorRegion(): string | null {
  if (typeof window === 'undefined') return null;
  return (window as { __cmp?: { visitorRegion?: string } }).__cmp?.visitorRegion ?? null;
}

// ── Jurisdiction check ───────────────────────────────────────────────

/**
 * Determine whether GPC should be honoured for the given region.
 *
 * @param region The visitor's region code (e.g. 'US-CA').
 * @param config GPC configuration from the site config.
 * @returns true if GPC should be honoured.
 */
export function shouldHonourGpc(
  region: string | null,
  config: GpcConfig,
): boolean {
  if (!config.gpc_enabled) return false;

  // Global honour overrides jurisdiction check
  if (config.gpc_global_honour) return true;

  if (!region) return false;

  const jurisdictions = config.gpc_jurisdictions.length > 0
    ? config.gpc_jurisdictions
    : DEFAULT_GPC_JURISDICTIONS;

  return jurisdictions.includes(region);
}

// ── Auto-opt-out categories ──────────────────────────────────────────

/**
 * Categories that should be rejected when GPC is honoured.
 * GPC specifically relates to sale/sharing/targeted advertising,
 * which maps to the 'marketing' and 'personalisation' categories.
 * Analytics may also be affected depending on interpretation.
 */
export const GPC_OPTOUT_CATEGORIES: CategorySlug[] = [
  'marketing',
  'personalisation',
];

/**
 * Categories that remain accepted when GPC auto-opt-out is applied.
 * 'necessary' is always accepted; 'functional' and 'analytics' are
 * not directly related to sale/sharing.
 */
export const GPC_ACCEPTED_CATEGORIES: CategorySlug[] = [
  'necessary',
  'functional',
  'analytics',
];

// ── Full evaluation ──────────────────────────────────────────────────

/**
 * Evaluate GPC signal and determine whether to apply auto-opt-out.
 *
 * @param config GPC configuration from the site config.
 * @param region The visitor's region code, or null if unknown.
 * @returns GpcResult with detection and honouring status.
 */
export function evaluateGpc(
  config: GpcConfig,
  region: string | null = null,
): GpcResult {
  const detected = isGpcEnabled();

  if (!detected || !config.gpc_enabled) {
    return { detected, honoured: false, region };
  }

  const honoured = shouldHonourGpc(region, config);

  return { detected, honoured, region };
}
