<?php

namespace App\Services;

use App\Models\Form;

/**
 * Single source of truth for turning a Form's stored block tree (see
 * FormRenderer) into the public-facing embed code. inlineHtml() is fully
 * self-contained (HTML + scoped <style> + a submit handler script) and is
 * used both as the copyable "Inline" embed snippet and, unmodified, as the
 * content injected into the popup overlay - see popupScript().
 */
class FormEmbedBuilder
{
    public static function inlineHtml(Form $form): string
    {
        $formId  = 'crmfic-form-' . $form->uuid;
        $body    = FormRenderer::bodySettings($form->fields ?? []);
        $style   = self::buildStyle($formId, $body);
        $content = FormRenderer::render($form->fields ?? []);
        $settings = $form->settings ?? [];
        $action  = $form->submitUrl();
        $viewUrl = $form->viewPingUrl();

        $settingsJson = self::jsonForScript([
            'after_submit_action' => $settings['after_submit_action'] ?? 'message',
            'redirect_url'        => $settings['redirect_url'] ?? null,
            'success_message'     => trim($settings['success_message'] ?? '') !== '' ? $settings['success_message'] : 'Thank you for subscribing!',
        ]);
        $viewUrlJson = self::jsonForScript($viewUrl);

        return <<<HTML
<div id="{$formId}" class="crmfic-embed">
<style>{$style}</style>
<form class="crmfic-form" data-action="{$action}">
{$content}
</form>
<div class="crmfic-msg crmfic-msg--error" style="display:none"></div>
<div class="crmfic-msg crmfic-msg--success" style="display:none"></div>
</div>
<script>
(function(){
  var root = document.getElementById('{$formId}');
  if (!root) return;
  var form = root.querySelector('.crmfic-form');
  var successEl = root.querySelector('.crmfic-msg--success');
  var errorEl = root.querySelector('.crmfic-msg--error');
  var settings = {$settingsJson};
  var viewUrl = {$viewUrlJson};

  if (navigator.sendBeacon) { navigator.sendBeacon(viewUrl); }

  form.addEventListener('submit', function (e) {
    e.preventDefault();
    errorEl.style.display = 'none';
    var data = new FormData(form);
    fetch(form.dataset.action, { method: 'POST', body: data, headers: { 'Accept': 'application/json' } })
      .then(function (r) { return r.json().catch(function () { return {}; }).then(function (json) { return { ok: r.ok, json: json }; }); })
      .then(function (res) {
        if (res.ok && res.json.success !== false) {
          if (settings.after_submit_action === 'redirect' && settings.redirect_url) {
            window.location.href = settings.redirect_url;
            return;
          }
          form.style.display = 'none';
          successEl.textContent = settings.success_message;
          successEl.style.display = 'block';
        } else {
          errorEl.textContent = (res.json && res.json.message) || 'Something went wrong. Please try again.';
          errorEl.style.display = 'block';
        }
      })
      .catch(function () {
        errorEl.textContent = 'Something went wrong. Please try again.';
        errorEl.style.display = 'block';
      });
  });
})();
</script>
HTML;
    }

    /**
     * The script served at Form::inlineScriptUrl() - the actual embed code
     * a user pastes for an inline form is just a placeholder <div> plus a
     * <script src="..."> tag pointing here (see FormController::embedPayload()),
     * mirroring how popupScript() already works for popups. Keeps the
     * copy-pasted snippet short instead of a large inline HTML blob.
     */
    public static function inlineScript(Form $form): string
    {
        $targetId    = $form->embedTargetId();
        $contentJson = self::jsonForScript(self::inlineHtml($form));

        return <<<JS
(function(){
  var target = document.getElementById('{$targetId}');
  if (!target) return;

  function executeScripts(container) {
    var scripts = container.querySelectorAll('script');
    for (var i = 0; i < scripts.length; i++) {
      var old = scripts[i];
      var fresh = document.createElement('script');
      fresh.textContent = old.textContent;
      old.parentNode.replaceChild(fresh, old);
    }
  }

  target.innerHTML = {$contentJson};
  executeScripts(target);
})();
JS;
    }

    public static function popupScript(Form $form): string
    {
        $uuid       = $form->uuid;
        $settings   = $form->settings ?? [];
        $trigger    = $settings['popup_trigger'] ?? 'delay';
        $triggerVal = (int) ($settings['popup_trigger_value'] ?? 5);
        $frequency  = $settings['popup_frequency'] ?? 'every_visit';
        $display    = in_array($settings['popup_display_style'] ?? 'center_modal', ['center_modal', 'corner', 'top_bar'], true)
            ? $settings['popup_display_style']
            : 'center_modal';

        $contentJson = self::jsonForScript(self::inlineHtml($form));
        $overlayCss  = self::buildPopupCss($display, FormRenderer::bodySettings($form->fields ?? []));

        return <<<JS
(function(){
  var STORAGE_KEY = 'crmfic_popup_seen_{$uuid}';
  var OVERLAY_ID = 'crmfic-popup-{$uuid}';

  if ('{$frequency}' === 'once_per_visitor' && localStorage.getItem(STORAGE_KEY)) { return; }

  function executeScripts(container) {
    var scripts = container.querySelectorAll('script');
    for (var i = 0; i < scripts.length; i++) {
      var old = scripts[i];
      var fresh = document.createElement('script');
      fresh.textContent = old.textContent;
      old.parentNode.replaceChild(fresh, old);
    }
  }

  function closePopup() {
    var el = document.getElementById(OVERLAY_ID);
    if (el) { el.remove(); }
  }

  function showPopup() {
    if (document.getElementById(OVERLAY_ID)) { return; }

    var styleTag = document.createElement('style');
    styleTag.textContent = {$overlayCss};
    document.head.appendChild(styleTag);

    var overlay = document.createElement('div');
    overlay.id = OVERLAY_ID;
    overlay.className = 'crmfic-popup-overlay crmfic-popup--{$display}';
    overlay.innerHTML = '<div class="crmfic-popup-box"><button type="button" class="crmfic-popup-close" aria-label="Close">&times;</button><div class="crmfic-popup-content">' + {$contentJson} + '</div></div>';
    document.body.appendChild(overlay);
    executeScripts(overlay);

    overlay.querySelector('.crmfic-popup-close').addEventListener('click', closePopup);
    if ('{$display}' === 'center_modal') {
      overlay.addEventListener('click', function (e) { if (e.target === overlay) { closePopup(); } });
    }
    if ('{$frequency}' === 'once_per_visitor') { localStorage.setItem(STORAGE_KEY, '1'); }
  }

  if ('{$trigger}' === 'immediate') {
    showPopup();
  } else if ('{$trigger}' === 'delay') {
    setTimeout(showPopup, {$triggerVal} * 1000);
  } else if ('{$trigger}' === 'scroll') {
    var fired = false;
    window.addEventListener('scroll', function () {
      if (fired) { return; }
      var max = document.body.scrollHeight - window.innerHeight;
      var pct = max > 0 ? (window.scrollY / max) * 100 : 100;
      if (pct >= {$triggerVal}) { fired = true; showPopup(); }
    });
  } else if ('{$trigger}' === 'exit_intent') {
    document.addEventListener('mouseout', function (e) {
      if (!e.relatedTarget && e.clientY <= 0) { showPopup(); }
    });
  }
})();
JS;
    }

    private static function buildStyle(string $formId, array $body): string
    {
        $background = preg_match('/^#[0-9a-fA-F]{3,8}$/', $body['bgColor'] ?? '') ? $body['bgColor'] : '#ffffff';
        $radius     = is_numeric($body['borderRadius'] ?? null) ? (int) $body['borderRadius'] : 12;
        $font       = e($body['fontFamily'] ?? 'Inter');

        return <<<CSS
#{$formId} {
  font-family: '{$font}', Helvetica, Arial, sans-serif;
  background: {$background};
  padding: 24px;
  border-radius: {$radius}px;
  box-sizing: border-box;
}
#{$formId} .crmfic-required { color: #dc2626; }
#{$formId} .crmfic-label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; }
#{$formId} .crmfic-input {
  width: 100%; box-sizing: border-box; padding: 9px 12px; font-size: 14px;
  border: 1px solid rgba(120,120,120,.35); font-family: inherit; background: rgba(255,255,255,.9); color: #111827;
}
#{$formId} textarea.crmfic-input { min-height: 90px; resize: vertical; }
#{$formId} .crmfic-name-row { display: flex; gap: 8px; }
#{$formId} .crmfic-help { font-size: 12px; opacity: .65; margin-top: 4px; }
#{$formId} .crmfic-msg--success { color: #16a34a; font-size: 14px; padding: 8px 0; }
#{$formId} .crmfic-msg--error { color: #dc2626; font-size: 13px; margin-bottom: 10px; }
#{$formId} .crmfic-radio-group, #{$formId} .crmfic-checkbox-group { display: flex; flex-direction: column; gap: 6px; }
#{$formId} .crmfic-choice { font-size: 14px; font-weight: 400; display: flex; align-items: center; gap: 6px; }
#{$formId} .crmfic-consent { font-size: 13px; display: flex; align-items: flex-start; gap: 6px; font-weight: 400; }
#{$formId} .crmfic-rating { display: flex; flex-direction: row-reverse; justify-content: flex-end; gap: 2px; }
#{$formId} .crmfic-rating input { position: absolute; opacity: 0; width: 1px; height: 1px; }
#{$formId} .crmfic-rating label { font-size: 22px; color: #d1d5db; cursor: pointer; }
#{$formId} .crmfic-rating input:checked ~ label, #{$formId} .crmfic-rating label:hover, #{$formId} .crmfic-rating label:hover ~ label { color: #f59e0b; }
#{$formId} .crmfic-choice-buttons { display: flex; flex-direction: column; gap: 8px; }
#{$formId} .crmfic-choice-btn { position: relative; display: block; cursor: pointer; }
#{$formId} .crmfic-choice-btn input { position: absolute; opacity: 0; }
#{$formId} .crmfic-choice-btn span { display: block; padding: 14px 20px; border-radius: inherit; color: #fff; text-align: center; font-weight: 600; font-size: 14px; }
#{$formId} .crmfic-choice-btn input:checked ~ span { outline: 3px solid rgba(0,0,0,.15); }
CSS;
    }

    private static function buildPopupCss(string $display, array $body): string
    {
        $radius     = is_numeric($body['borderRadius'] ?? null) ? (int) $body['borderRadius'] : 14;
        $background = preg_match('/^#[0-9a-fA-F]{3,8}$/', $body['bgColor'] ?? '') ? $body['bgColor'] : '#ffffff';
        $closeColor = self::isDarkColor($background) ? '#f9fafb' : '#374151';

        $positional = match ($display) {
            'corner'  => '.crmfic-popup--corner { align-items: flex-end; justify-content: flex-end; background: transparent; padding: 20px; } .crmfic-popup--corner .crmfic-popup-box { max-width: 340px; }',
            'top_bar' => '.crmfic-popup--top_bar { align-items: flex-start; justify-content: center; background: transparent; } .crmfic-popup--top_bar .crmfic-popup-box { max-width: 100%; width: 100%; border-radius: 0; }',
            default   => '.crmfic-popup--center_modal { align-items: center; justify-content: center; background: rgba(17,24,39,.6); }',
        };

        $css = <<<CSS
.crmfic-popup-overlay { position: fixed; inset: 0; z-index: 999999; display: flex; }
.crmfic-popup-box { position: relative; background: {$background}; border-radius: {$radius}px; padding: 6px; max-width: 440px; width: calc(100% - 40px); box-shadow: 0 20px 50px rgba(0,0,0,.25); }
.crmfic-popup-close { position: absolute; top: 10px; right: 12px; background: none; border: none; font-size: 22px; line-height: 1; cursor: pointer; color: {$closeColor}; opacity: .7; }
.crmfic-popup-close:hover { opacity: 1; }
{$positional}
CSS;

        return self::jsonForScript($css);
    }

    private static function isDarkColor(string $hex): bool
    {
        $hex = ltrim($hex, '#');
        if (strlen($hex) === 3) {
            $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
        }
        if (strlen($hex) < 6) {
            return false;
        }
        $r = hexdec(substr($hex, 0, 2));
        $g = hexdec(substr($hex, 2, 2));
        $b = hexdec(substr($hex, 4, 2));
        $luminance = (0.299 * $r + 0.587 * $g + 0.114 * $b) / 255;

        return $luminance < 0.5;
    }

    private static function jsonForScript(mixed $value): string
    {
        return json_encode($value, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP) ?: 'null';
    }
}
