/**
 * Deterministischer MJML-Template-Renderer.
 * Wird vom Pipeline-Stub, Preserve-Mode und Edit-Re-Render verwendet.
 * Erzeugt aus Strategy + Workspace-Info ein vollständiges MJML.
 */

export interface TemplateStrategy {
  subject_variants: string[];
  preheader: string;
  hero_headline: string;
  intro: string;
  pain_point: string;
  solution: string;
  benefits: string[];
  cta_primary_text: string;
  cta_secondary_text?: string;
  ps_line: string;
}

export interface TemplateBrand {
  name: string;
  primaryColor: string;
  footerText: string;
  logoUrl?: string;
  /** Optional: Header-Telefonnummer (rechts neben Logo) */
  headerPhone?: string;
  /** Optional: Tagline unter Logo (z.B. "Ihr Versicherungsmakler") */
  headerTagline?: string;
  /** Optional: Anwaltsgeprüfter Legal-Pflicht-Block (DE) — 9pt-Block, hat Vorrang vor Legacy-Feldern */
  footerLegalText?: string;
  /** Optional: EN-Reserve-Variante des Legal-Blocks */
  footerLegalTextEn?: string;
  /** Optional: Confidentiality-/Haftungs-Block (DE) — 9pt kursiv unter dem Legal-Block */
  footerConfidentialityNotice?: string;
  /** Optional: EN-Reserve-Variante des Confidentiality-Blocks */
  footerConfidentialityNoticeEn?: string;
  /** Default true. Wenn explizit false → "Abmelden"-Link wird im Adress-Block weggelassen. */
  footerShowUnsubscribe?: boolean;
  /** Optional Legacy: Gesellschaftsdaten (Geschäftsführer, HRB, USt-ID) — nur Fallback wenn footerLegalText leer */
  footerCompanyInfo?: string;
  /** Optional Legacy: Versicherungsmakler-Compliance (§34d GewO, IHK-Reg, §59 VVG) — Fallback */
  footerLegalRegulations?: string;
  /** Optional Legacy: Beschwerdestellen (Ombudsmann, BaFin) — Fallback */
  footerComplaintBodies?: string;
  /**
   * Optional: Custom-MJML-Footer. Wenn gesetzt (nicht-leer), wird der gesamte
   * Standard-Footer-Bereich durch diesen Block ersetzt. Der User trägt die
   * Verantwortung dafür, dass System-Tags ({{BROWSER_URL}}, {{IMPRINT_URL}},
   * {{PRIVACY_URL}}, {{UNSUBSCRIBE_URL}}) enthalten sind — sie werden vom Worker
   * zur Send-Zeit ersetzt.
   */
  footerMjml?: string;
  /**
   * Standard-Signatur (DE). Wird unter der P.S.-Zeile gerendert. `\n` → `<br/>`.
   * Wenn leer/undefined → Hardcode-Fallback ("Beste Grüße,\nIhr Team").
   */
  footerDefaultSignature?: string;
  /** EN-Reserve-Variante der Standard-Signatur. */
  footerDefaultSignatureEn?: string;
}

export interface TemplateContext {
  strategy: TemplateStrategy;
  workspace: TemplateBrand;
  ctaPrimaryUrl: string;
  ctaSecondaryUrl?: string;
  heroUrl?: string;       // Wenn gesetzt → echte URL; sonst {{HERO_URL}}-Platzhalter
  heroEnabled: boolean;
  /**
   * Optional: max. Hero-Bild-Höhe in px. Wenn gesetzt:
   *  - `<mj-image>` bekommt `height="${h}px"` Attribut
   *  - Inline-CSS via `<mj-style inline="inline">` setzt `object-fit:cover` → Crop statt Stauchung
   *  - Outlook (kein object-fit-Support) fällt auf Stauchung zurück; alle anderen Clients croppen sauber
   */
  heroHeight?: number;
  /**
   * Optional: Crop-Position (object-position) für das Hero-Bild bei gesetzter heroHeight.
   * 'top' = oberer Bildteil sichtbar, 'center' = mittig (default), 'bottom' = unterer Bildteil.
   * Wirkt nur in Clients die object-fit unterstützen (Gmail/Apple/iOS Mail). Outlook ignoriert.
   */
  heroCropPosition?: 'top' | 'center' | 'bottom';
  /** Bei `preserve` mode: HTML-Body wortwörtlich übernehmen statt strukturiertes Layout */
  preserveBodyHtml?: string;
}

export function buildMjmlFromStrategy(ctx: TemplateContext): string {
  const { strategy: s, workspace, heroEnabled, heroHeight, heroCropPosition, preserveBodyHtml } = ctx;
  // Sprach-Detection einmal pro Render-Call — auch Footer respektiert das.
  const lang = detectLanguage(s.intro);
  const heroSrc = ctx.heroUrl ?? '{{HERO_URL}}';
  // Wenn heroHeight gesetzt → height-Attribut + css-class für object-fit:cover-Crop.
  // Sonst → klassisches mj-image (natürliche Bildhöhe).
  const heroHeightAttrs = heroHeight
    ? ` height="${heroHeight}px" css-class="mf-hero-cover"`
    : '';
  const heroBlock = heroEnabled
    ? `<mj-image src="${escapeAttr(heroSrc)}" alt="${escapeAttr(s.hero_headline)}" width="600px" padding="0"${heroHeightAttrs} />`
    : '';

  const bodySection = preserveBodyHtml
    ? renderPreservedBody(preserveBodyHtml, s, workspace)
    : renderStructuredBody(s, workspace, lang);

  const secondaryCta = s.cta_secondary_text && ctx.ctaSecondaryUrl
    ? `<mj-text align="center" font-size="13px" color="#71717a" padding-top="8px"><a href="${escapeAttr(ctx.ctaSecondaryUrl)}" style="color:#71717a;text-decoration:underline">${editable('cta_secondary_text', escapeXml(s.cta_secondary_text))}</a></mj-text>`
    : '';

  // Primärer CTA — nur wenn URL gesetzt. Ohne URL kein Button (User-Wunsch: nicht mit href="#" rendern).
  // Wenn der User die URL später nachträgt, kann via Re-Render-Endpoint die Mail aktualisiert werden.
  const primaryCta = ctx.ctaPrimaryUrl
    ? `<mj-button href="${escapeAttr(ctx.ctaPrimaryUrl)}">${editable('cta_primary_text', escapeXml(s.cta_primary_text))}</mj-button>`
    : '';

  // Inline-CSS-Crop für gesetzte Hero-Höhe.
  //  - `object-fit: cover` croppt mittig statt zu stauchen — Gmail/Apple Mail/iOS Mail respektieren das
  //  - `!important` weil mj-image via inline width/height-Attributen sonst gewinnt
  //  - Outlook ignoriert object-fit → fällt auf native Stauchung zurück (kein Worse-Case als bisher)
  const heroCropStyle = heroHeight
    ? `<mj-style inline="inline">
      .mf-hero-cover img {
        height: ${heroHeight}px !important;
        object-fit: cover !important;
        object-position: ${heroCropPosition ?? 'center'} !important;
      }
    </mj-style>`
    : '';

  // Logo-Header-Section: nur rendern, wenn workspace.logoUrl gesetzt ist.
  // Wenn keine Logo-URL konfiguriert wurde, wird die Section komplett weggelassen
  // (kein Broken-Image-Fallback) — konsistent mit applyLogoUrl() im Generate-Pfad.
  const hasLogo = !!workspace.logoUrl?.trim();
  const logoSection = hasLogo
    ? `<mj-section background-color="#ffffff" padding="20px 24px 0">
      ${workspace.headerPhone
        ? `<mj-column width="65%"><mj-image src="${escapeAttr(workspace.logoUrl!)}" alt="${escapeAttr(workspace.name)}" width="120px" align="left" padding="0" /></mj-column>
           <mj-column width="35%"><mj-text font-size="13px" color="#52525b" align="right" padding="6px 0 0">📞 ${escapeXml(workspace.headerPhone)}</mj-text></mj-column>`
        : `<mj-column><mj-image src="${escapeAttr(workspace.logoUrl!)}" alt="${escapeAttr(workspace.name)}" width="120px" align="left" padding="0" /></mj-column>`}
    </mj-section>`
    // Sonderfall: Logo fehlt, aber headerPhone gesetzt → Phone alleine in einer schmalen Section behalten,
    // damit die Telefonnummer nicht stillschweigend verschwindet.
    : workspace.headerPhone
      ? `<mj-section background-color="#ffffff" padding="20px 24px 0"><mj-column><mj-text font-size="13px" color="#52525b" align="right" padding="0">📞 ${escapeXml(workspace.headerPhone)}</mj-text></mj-column></mj-section>`
      : '';

  return `<mjml>
  <mj-head>
    <mj-title>${escapeXml(s.subject_variants[0] ?? '')}</mj-title>
    <mj-preview>${escapeXml(s.preheader)}</mj-preview>
    <mj-attributes>
      <mj-all font-family="Helvetica, Arial, sans-serif" />
      <mj-text font-size="15px" line-height="1.6" color="#27272a" />
      <mj-button background-color="${escapeAttr(workspace.primaryColor)}" color="#ffffff" font-size="15px" font-weight="600" border-radius="6px" padding="12px 28px" />
    </mj-attributes>
    ${heroCropStyle}
  </mj-head>
  <mj-body width="600px" background-color="#f4f4f5">
    ${logoSection}
    ${workspace.headerTagline
      ? `<mj-section background-color="#ffffff" padding="0 24px 8px"><mj-column><mj-text font-size="13px" color="#71717a" font-style="italic" padding="0">${escapeXml(workspace.headerTagline)}</mj-text></mj-column></mj-section>`
      : ''}
    ${heroBlock ? `<mj-section background-color="#ffffff" padding="20px 24px 0"><mj-column>${heroBlock}</mj-column></mj-section>` : ''}
    ${bodySection}
    <mj-section background-color="#ffffff" padding="8px 24px 24px">
      <mj-column>
        ${primaryCta}
        ${secondaryCta}
        <mj-text font-style="italic" color="#52525b" font-size="14px" padding-top="20px">${editable('ps_line', escapeXml(s.ps_line))}</mj-text>
        <mj-text padding-top="16px">${escapeXml(resolveSignature(workspace, lang)).replace(/\n/g, '<br/>')}</mj-text>
      </mj-column>
    </mj-section>
    ${renderFooterSection(workspace, lang)}
  </mj-body>
</mjml>`;
}

/**
 * Wrappt Text mit einem `data-edit-key`-Span — Marker für Inline-Editing in der Preview.
 * Der Span ist semantisch transparent (kein Display-Effekt), wird von Email-Clients
 * komplett ignoriert und in unserem Preview-iframe per Script aufgegriffen.
 *
 * Bei array-Feldern (z.B. benefits) zusätzlich `data-edit-index` für deterministische Adressierung.
 */
function editable(key: string, content: string, index?: number): string {
  const idxAttr = index !== undefined ? ` data-edit-index="${index}"` : '';
  return `<span data-edit-key="${key}"${idxAttr}>${content}</span>`;
}

function resolveSignature(workspace: TemplateBrand, lang: 'de' | 'en'): string {
  if (lang === 'en') {
    return workspace.footerDefaultSignatureEn?.trim()
      || workspace.footerDefaultSignature?.trim()
      || 'Best regards,\nThe team';
  }
  return workspace.footerDefaultSignature?.trim() || 'Beste Grüße,\nIhr Team';
}

/**
 * Rendert den Footer-Bereich. Drei Pfade:
 *  - Custom-MJML (wenn `workspace.footerMjml` gesetzt + nicht-leer): User-eigener Block 1:1.
 *  - Anwaltsblock (wenn `footerLegalText` gesetzt): 9pt Legal-Block + optionaler
 *    9pt-Confidentiality-Block (kursiv). Sprach-Pick zwischen DE und EN automatisch.
 *  - Legacy (Fallback): companyInfo + legalRegulations + complaintBodies als Einzelblöcke.
 *
 * Alle Pfade enthalten Platzhalter wie `{{BROWSER_URL}}` — die Substitution passiert
 * im Worker (Send) bzw. in `applyFooterUrlsForPreview()` für die Vorschau.
 *
 * `lang` kommt aus `buildMjmlFromStrategy` (detectLanguage auf strategy.intro), wird
 * deterministisch durchgereicht damit Body und Footer dieselbe Sprache rendern.
 */
export function renderFooterSection(workspace: TemplateBrand, lang: 'de' | 'en' = 'de'): string {
  const customMjml = workspace.footerMjml?.trim();
  if (customMjml) return customMjml;

  const showUnsub = workspace.footerShowUnsubscribe !== false;
  const unsubLinkLabel = lang === 'en' ? 'Unsubscribe' : 'Abmelden';
  const browserLinkLabel = lang === 'en' ? 'View in browser' : 'Im Browser ansehen';
  const imprintLinkLabel = lang === 'en' ? 'Imprint' : 'Impressum';
  const privacyLinkLabel = lang === 'en' ? 'Privacy' : 'Datenschutz';

  // System-Links pro Workspace zusammenstellen — Abmelde-Link wird bei Info-Workspaces weggelassen.
  const linkParts = [
    `<a href="{{BROWSER_URL}}" style="color:#a1a1aa">${browserLinkLabel}</a>`,
    `<a href="{{IMPRINT_URL}}" style="color:#a1a1aa">${imprintLinkLabel}</a>`,
    `<a href="{{PRIVACY_URL}}" style="color:#a1a1aa">${privacyLinkLabel}</a>`,
  ];
  if (showUnsub) {
    linkParts.push(`<a href="{{UNSUBSCRIBE_URL}}" style="color:#a1a1aa">${unsubLinkLabel}</a>`);
  }
  const systemLinks = linkParts.join(' · ');

  // Sprach-gepickter Legal-Block — EN-Reserve hat Vorrang wenn Mail-Sprache 'en' UND EN-Text gesetzt.
  const legalText = lang === 'en' && workspace.footerLegalTextEn?.trim()
    ? workspace.footerLegalTextEn
    : workspace.footerLegalText?.trim();
  const confText = lang === 'en' && workspace.footerConfidentialityNoticeEn?.trim()
    ? workspace.footerConfidentialityNoticeEn
    : workspace.footerConfidentialityNotice?.trim();

  const hasAnwaltsblock = !!legalText;

  const anwaltLegalBlock = legalText
    ? `<mj-text font-size="12px" color="#71717a" align="center" line-height="1.55" padding-top="12px">${escapeXml(legalText).replace(/\n/g, '<br/>')}</mj-text>`
    : '';
  const anwaltConfBlock = confText
    ? `<mj-text font-size="12px" color="#71717a" align="center" line-height="1.55" font-style="italic" padding-top="10px">${escapeXml(confText).replace(/\n/g, '<br/>')}</mj-text>`
    : '';

  // Legacy-Pfad nur wenn KEIN Anwaltsblock gesetzt ist — alte Workspaces sollen sich nicht verändern.
  const legacyCompanyInfoBlock = !hasAnwaltsblock && workspace.footerCompanyInfo
    ? `<mj-text font-size="10px" color="#a1a1aa" align="center" line-height="1.6" padding-top="10px">${escapeXml(workspace.footerCompanyInfo).replace(/\n/g, '<br/>')}</mj-text>`
    : '';
  const legacyRegulationsBlock = !hasAnwaltsblock && workspace.footerLegalRegulations
    ? `<mj-text font-size="10px" color="#a1a1aa" align="center" line-height="1.6" padding-top="8px"><strong style="color:#71717a">${lang === 'en' ? 'Legal' : 'Rechtliches'}:</strong><br/>${escapeXml(workspace.footerLegalRegulations).replace(/\n/g, '<br/>')}</mj-text>`
    : '';
  const legacyComplaintsBlock = !hasAnwaltsblock && workspace.footerComplaintBodies
    ? `<mj-text font-size="10px" color="#a1a1aa" align="center" line-height="1.6" padding-top="8px"><strong style="color:#71717a">${lang === 'en' ? 'Complaint bodies' : 'Beschwerdestellen'}:</strong><br/>${escapeXml(workspace.footerComplaintBodies).replace(/\n/g, '<br/>')}</mj-text>`
    : '';

  return `<mj-section background-color="#f4f4f5" padding="16px 24px">
      <mj-column>
        <mj-text font-size="11px" color="#a1a1aa" align="center" line-height="1.6">
          ${escapeXml(workspace.footerText)}<br/>
          ${systemLinks}
        </mj-text>
        ${anwaltLegalBlock}
        ${anwaltConfBlock}
        ${legacyCompanyInfoBlock}
        ${legacyRegulationsBlock}
        ${legacyComplaintsBlock}
      </mj-column>
    </mj-section>`;
}

function renderStructuredBody(s: TemplateStrategy, _brand: TemplateBrand, lang: 'de' | 'en'): string {
  // Per-Bullet Remove-Marker und Add-Marker am Ende. Inline-Style display:none versteckt sie
  // in Email-Clients (Gmail/Apple/Outlook); der Inline-Editor unhided sie nur im Preview-iframe.
  const benefits = s.benefits.map((b, i) =>
    `<li style="margin-bottom:6px">${editable('benefits', escapeXml(b), i)}<span data-mf-action="remove-benefit" data-edit-index="${i}" class="mf-benefit-remove" style="display:none;mso-hide:all" aria-label="Vorteil entfernen">✖</span></li>`
  ).join('');
  const addBenefitMarker = `<li data-mf-action="add-benefit" class="mf-benefit-add" style="display:none;mso-hide:all">${lang === 'en' ? '+ Add benefit' : '+ Vorteil hinzufügen'}</li>`;
  return `<mj-section background-color="#ffffff" padding="24px 24px 0">
  <mj-column>
    <mj-text font-size="24px" font-weight="700" color="#18181b" line-height="1.25">${editable('hero_headline', escapeXml(s.hero_headline))}</mj-text>
    <mj-text>${editable('intro', escapeXml(s.intro))}</mj-text>
    <mj-text>${editable('pain_point', escapeXml(s.pain_point))}</mj-text>
    <mj-text>${editable('solution', escapeXml(s.solution))}</mj-text>
    <mj-text font-weight="600" padding-top="8px">${lang === 'en' ? 'Your benefits at a glance:' : 'Ihre Vorteile auf einen Blick:'}</mj-text>
    <mj-text><ul style="padding-left:18px;margin:0">${benefits}${addBenefitMarker}</ul></mj-text>
  </mj-column>
</mj-section>`;
}

function renderPreservedBody(html: string, s: TemplateStrategy, _brand: TemplateBrand): string {
  // Trim und sanitize — nur sicheres HTML zulassen (Tiptap-Output ist bereits clean)
  const clean = html.trim();
  return `<mj-section background-color="#ffffff" padding="24px 24px 0">
  <mj-column>
    <mj-text font-size="24px" font-weight="700" color="#18181b" line-height="1.25">${editable('hero_headline', escapeXml(s.hero_headline))}</mj-text>
    <mj-raw><div style="font-family:Helvetica,Arial,sans-serif;font-size:15px;line-height:1.6;color:#27272a;padding:0">${clean}</div></mj-raw>
  </mj-column>
</mj-section>`;
}

export function detectLanguage(s: string): 'de' | 'en' {
  const lower = s.toLowerCase();
  // Sehr einfache Heuristik — DE-typische Stoppwörter
  if (/\b(sie|wir|der|die|das|mit|und|für|ihre|haben|sind)\b/.test(lower)) return 'de';
  return 'en';
}

function escapeXml(s: string): string {
  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

function escapeAttr(s: string): string {
  return s.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;');
}
