/**
 * UTM-Auto-Append: reichert `href`-URLs in HTML/Text mit Google-Analytics-UTM-Parametern an.
 *
 * Wird zur Send-Zeit im Worker aufgerufen — pro Recipient/Job, sodass `utm_content` automatisch
 * die A/B-Variante (z.B. 'A' oder 'B') mitführt. So sieht man in Google Analytics direkt welche
 * Variante besser performt hat — ohne separate Tracking-Pipeline.
 */

export interface UtmParams {
  /** utm_source — Plattform/Domain, z.B. "newsletter" oder "mailforge". */
  source?: string;
  /** utm_medium — Kanal, z.B. "email". Default: "email". */
  medium?: string;
  /** utm_campaign — Kampagnen-Identifier, z.B. "frühling-2026". */
  campaign?: string;
  /** utm_content — Variant/Kreativ-Slot. Wird zur Send-Zeit per A/B überschrieben. */
  content?: string;
  /** utm_term — Optional, klassisch für bezahlte Suche; bei Email selten gefüllt. */
  term?: string;
}

/**
 * True wenn mindestens 1 UTM-Wert gesetzt ist — sonst macht Auto-Append keinen Sinn.
 */
export function hasAnyUtm(p: UtmParams | null | undefined): boolean {
  if (!p) return false;
  return Boolean(p.source || p.medium || p.campaign || p.content || p.term);
}

/** Baut einen Query-String "utm_source=…&utm_medium=…" — leere Felder werden geskippt. */
export function buildUtmQueryString(p: UtmParams): string {
  const parts: string[] = [];
  if (p.source) parts.push(`utm_source=${encodeURIComponent(p.source)}`);
  if (p.medium) parts.push(`utm_medium=${encodeURIComponent(p.medium)}`);
  if (p.campaign) parts.push(`utm_campaign=${encodeURIComponent(p.campaign)}`);
  if (p.content) parts.push(`utm_content=${encodeURIComponent(p.content)}`);
  if (p.term) parts.push(`utm_term=${encodeURIComponent(p.term)}`);
  return parts.join('&');
}

/**
 * Heuristik: True für URLs auf die wir UTM NICHT anhängen wollen.
 * - `mailto:`, `tel:`, `sms:` — keine Web-URLs
 * - `#…` — Page-Anchor
 * - URLs die schon `utm_*`-Params tragen — Honor-User-Choice, kein Doppel-Append
 * - Unsubscribe-/List-Manage-Links — würde Tracking-Verifizierung beim ESP brechen
 */
function shouldSkipUrl(url: string): boolean {
  const u = url.trim().toLowerCase();
  if (!u) return true;
  if (u.startsWith('mailto:') || u.startsWith('tel:') || u.startsWith('sms:')) return true;
  if (u.startsWith('#')) return true;
  if (u.includes('utm_source=') || u.includes('utm_medium=') || u.includes('utm_campaign=')) return true;
  if (u.includes('/unsubscribe') || u.includes('list-unsubscribe') || u.includes('?unsub')) return true;
  return false;
}

/**
 * Hängt UTM-Parameter an eine einzelne URL an.
 * Berücksichtigt bestehende Query-Strings und Fragments korrekt:
 *  - `https://x.de/p` → `https://x.de/p?utm_source=…`
 *  - `https://x.de/p?a=1` → `https://x.de/p?a=1&utm_source=…`
 *  - `https://x.de/p#section` → `https://x.de/p?utm_source=…#section`
 */
export function appendUtmToUrl(url: string, utmQueryString: string): string {
  if (!utmQueryString) return url;
  if (shouldSkipUrl(url)) return url;

  // Fragment vom Rest separieren — UTM muss VOR dem #-Anchor stehen
  const hashIdx = url.indexOf('#');
  const base = hashIdx >= 0 ? url.slice(0, hashIdx) : url;
  const fragment = hashIdx >= 0 ? url.slice(hashIdx) : '';

  const separator = base.includes('?') ? '&' : '?';
  return `${base}${separator}${utmQueryString}${fragment}`;
}

/**
 * Reichert ALLE `href="…"`-Attribute in HTML mit UTM an.
 * Berücksichtigt sowohl `href="…"` als auch `href='…'`.
 */
export function applyUtmToHtml(html: string, params: UtmParams): string {
  if (!hasAnyUtm(params)) return html;
  const qs = buildUtmQueryString(params);
  if (!qs) return html;

  // Match href="..." oder href='...' — capture quote + URL separat
  return html.replace(/href=(["'])([^"']+)\1/gi, (_match, quote: string, url: string) => {
    return `href=${quote}${appendUtmToUrl(url, qs)}${quote}`;
  });
}

/**
 * Reichert URLs in Plain-Text an. Heuristik: Match auf `http://…` und `https://…` bis zum
 * nächsten Whitespace oder String-Ende. Lässt Punktuation am Ende (`. , ; )`) unangetastet.
 */
export function applyUtmToText(text: string, params: UtmParams): string {
  if (!hasAnyUtm(params)) return text;
  const qs = buildUtmQueryString(params);
  if (!qs) return text;

  return text.replace(/(https?:\/\/[^\s<>"]+?)([.,;:!?)\]]?(?:\s|$))/g, (_m, url: string, tail: string) => {
    return `${appendUtmToUrl(url, qs)}${tail}`;
  });
}

/**
 * Slug-Helper für UTM-Defaults: lowercase, Diakritika strippen, alles außer
 * `[a-z0-9-]` zu `-`, Mehrfach-Dashes kollabieren, Trim. Trunkiert auf 50 Zeichen,
 * damit die Werte in GA-Reports nicht abgeschnitten werden.
 *
 * Beispiele:
 *  - "ITS GmbH B2B Partnership Outreach" → "its-gmbh-b2b-partnership-outreach"
 *  - "Frühling Aktion 2026!" → "fruhling-aktion-2026"
 */
export function slugify(input: string): string {
  return input
    .normalize('NFD')
    // Combining Diacritical Marks (U+0300–U+036F) entfernen, damit "Frühling" → "Fruhling"
    .replace(/[̀-ͯ]/g, '')
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '')
    .slice(0, 50);
}

/**
 * Briefing-Sub-Shape den `prefillUtm` zur Ableitung von Defaults braucht.
 * Bewusst lose getypt, damit das Modul ohne Zirkular-Import aus `BriefingPanel.tsx`
 * leben kann — Frontend reicht einfach `{ workspaceSlug, campaignName }` rein.
 */
export interface UtmPrefillInput {
  workspaceSlug?: string;
  campaignName?: string;
}

/**
 * Liefert deterministische UTM-Defaults aus einem Briefing-State.
 * `medium` ist immer "email" (Channel-Konvention). Werte werden slugifiziert
 * und mit Jahr-Monat-Suffix versehen, damit die Kampagne in GA-Reports zeitlich
 * eindeutig ist (zwei "Q2 Reaktivierung"-Sends in zwei Monaten sind getrennt).
 *
 * Felder mit nicht ableitbarem Input fehlen im Output (undefined) — das
 * `existing`-Merge im UI entscheidet, ob sie überschrieben werden.
 */
export function prefillUtm(input: UtmPrefillInput, now: Date = new Date()): UtmParams {
  const yyyyMM = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
  const out: UtmParams = { medium: 'email' };
  if (input.workspaceSlug) out.source = slugify(input.workspaceSlug);
  if (input.campaignName && input.campaignName.trim().length > 0) {
    const base = slugify(input.campaignName);
    if (base) out.campaign = `${base}-${yyyyMM}`.slice(0, 80);
  }
  return out;
}

/**
 * Merged neue UTM-Defaults non-destruktiv in einen bestehenden State. Bereits
 * gefüllte Felder bleiben unangetastet — der User soll seine manuellen Werte
 * nicht durch einen Toggle-Reflex verlieren.
 */
export function mergeUtmDefaults(existing: UtmParams | undefined, defaults: UtmParams): UtmParams {
  const base: UtmParams = existing ?? {};
  const out: UtmParams = { ...base };
  for (const k of ['source', 'medium', 'campaign', 'content', 'term'] as const) {
    if (!out[k] && defaults[k]) out[k] = defaults[k];
  }
  return out;
}
