<?php
/**
 * Newsletter Signup Plugin
 *
 * Modular newsletter signup section that can be included on any page.
 * Uses Listmonk's public subscription API for double opt-in.
 * Supports i18n via language files.
 *
 * Usage: Add to metadata.ini:
 *   plugins = "newsletter-signup"
 *
 * Then in your PHP content file, call the function with your custom text and theme:
 *   <?= newsletter_signup('Your custom intro text here', 'hero') ?>
 *   <?= newsletter_signup('Short text here', 'small') ?>
 *   <?= newsletter_signup('Text', 'small', ['list-uuid-here']) ?>
 *
 * Available themes:
 *   - 'hero': Full-width gradient background section (like CTA sections)
 *   - 'small': Compact inline notice with rounded border, fits between paragraphs
 */

// Start session if not already started
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

// Generate CSRF token if not exists
if (empty($_SESSION['newsletter_csrf_token'])) {
    $_SESSION['newsletter_csrf_token'] = bin2hex(random_bytes(32));
}

/**
 * Get translation for newsletter plugin
 */
function newsletterT(string $key): string {
    $ctx = $GLOBALS['ctx'] ?? null;
    if (!$ctx) {
        // Fallback values if no context
        $fallbacks = [
            'name_label' => 'Navn',
            'name_placeholder' => 'Ditt navn',
            'email_label' => 'E-post',
            'email_placeholder' => 'Din e-postadresse',
            'notice' => 'Vi sender ca. 12 e-poster i året.',
            'submit_button' => 'Meld deg på',
            'success_message' => 'Sjekk innboksen din!',
            'success_confirm' => 'Takk! Vi har sendt en e-post til deg. Åpne lenken i e-posten og bekreft for å fullføre påmeldingen.',
            'error_message' => 'Noe gikk galt!'
        ];
        return $fallbacks[$key] ?? $key;
    }

    $translations = $ctx->get('translations', []);
    $fullKey = "newsletter.{$key}";
    return $translations[$fullKey] ?? $key;
}

/**
 * Subscribe to newsletter via Listmonk public API
 */
function newsletterSubscribe(string $email, string $name, array $listUuids = []): array {
    $configPath = dirname(__DIR__, 2) . '/listmonk-config.php';
    if (!file_exists($configPath)) {
        return ['success' => false, 'error' => 'config_missing'];
    }

    $config = require $configPath;
    if (!$config['enabled']) {
        return ['success' => false, 'error' => 'disabled'];
    }

    $payload = json_encode([
        'email' => $email,
        'name' => $name,
        'list_uuids' => !empty($listUuids) ? $listUuids : $config['list_uuids']
    ]);

    $url = $config['url'] . '/api/public/subscription';
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $payload,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 10
    ]);

    $response = curl_exec($ch);
    $curlError = curl_error($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($curlError) {
        error_log("Newsletter curl error: {$curlError}");
        return ['success' => false, 'error' => 'network'];
    }

    if ($httpCode >= 200 && $httpCode < 300) {
        return ['success' => true];
    }

    error_log("Newsletter subscription failed: HTTP {$httpCode}, Response: {$response}");
    return ['success' => false, 'error' => 'api'];
}

/**
 * Rate limit check for newsletter signups
 */
function newsletterCheckRateLimit(): bool {
    $lastSubmit = $_SESSION['newsletter_last_submit'] ?? 0;
    return (time() - $lastSubmit) >= 30;
}

/**
 * Get shared form translations
 */
function newsletterGetTranslations(): array {
    return [
        'nameLabel' => htmlspecialchars(newsletterT('name_label'), ENT_QUOTES, 'UTF-8'),
        'namePlaceholder' => htmlspecialchars(newsletterT('name_placeholder'), ENT_QUOTES, 'UTF-8'),
        'emailLabel' => htmlspecialchars(newsletterT('email_label'), ENT_QUOTES, 'UTF-8'),
        'emailPlaceholder' => htmlspecialchars(newsletterT('email_placeholder'), ENT_QUOTES, 'UTF-8'),
        'notice' => htmlspecialchars(newsletterT('notice'), ENT_QUOTES, 'UTF-8'),
        'submitButton' => htmlspecialchars(newsletterT('submit_button'), ENT_QUOTES, 'UTF-8'),
        'successMessage' => htmlspecialchars(newsletterT('success_message'), ENT_QUOTES, 'UTF-8'),
        'successConfirm' => htmlspecialchars(newsletterT('success_confirm'), ENT_QUOTES, 'UTF-8'),
        'errorMessage' => htmlspecialchars(newsletterT('error_message'), ENT_QUOTES, 'UTF-8'),
    ];
}

/**
 * Get shared JavaScript (only included once per page)
 */
function newsletterGetScript(): string {
    static $scriptIncluded = false;
    if ($scriptIncluded) {
        return '';
    }
    $scriptIncluded = true;

    return <<<'SCRIPT'
<script>
(function() {
    var forms = document.querySelectorAll('[data-newsletter-form]');
    forms.forEach(function(form) {
        form.addEventListener('submit', function(e) {
            e.preventDefault();
            var btn = form.querySelector('button[type="submit"]');
            if (btn.classList.contains('is-loading') || btn.classList.contains('is-success')) return;

            btn.classList.remove('is-error');
            btn.classList.add('is-loading');
            btn.disabled = true;

            var formData = new FormData(form);
            formData.append('newsletter_submit', '1');

            fetch(window.location.href, {
                method: 'POST',
                body: formData
            })
            .then(function(r) { return r.json(); })
            .then(function(data) {
                btn.classList.remove('is-loading');
                if (data.success) {
                    var confirmMsg = form.getAttribute('data-success-confirm');
                    if (confirmMsg) {
                        var notice = document.createElement('p');
                        notice.className = 'newsletter-confirm';
                        notice.textContent = confirmMsg;
                        form.replaceWith(notice);
                    } else {
                        btn.classList.add('is-success');
                        var successTextEl = btn.querySelector('.btn-success-text');
                        var successMsg = form.getAttribute('data-success-message');
                        if (successTextEl && successMsg) successTextEl.textContent = successMsg;
                        setTimeout(function() {
                            btn.classList.remove('is-success');
                            btn.disabled = false;
                        }, 5000);
                    }
                } else {
                    btn.classList.add('is-error');
                    var errorTextEl = btn.querySelector('.btn-error-text');
                    var errorMsg = form.getAttribute('data-error-message');
                    if (errorTextEl && errorMsg) errorTextEl.textContent = errorMsg;
                    btn.disabled = false;
                    setTimeout(function() {
                        btn.classList.remove('is-error');
                    }, 5000);
                }
            })
            .catch(function() {
                btn.classList.remove('is-loading');
                btn.classList.add('is-error');
                var errorTextEl = btn.querySelector('.btn-error-text');
                var errorMsg = form.getAttribute('data-error-message');
                if (errorTextEl && errorMsg) errorTextEl.textContent = errorMsg;
                btn.disabled = false;
                setTimeout(function() {
                    btn.classList.remove('is-error');
                }, 5000);
            });
        });
    });
})();
</script>
SCRIPT;
}

/**
 * Render the "hero" theme - full-width gradient background section
 */
function newsletterRenderHero(string $introText, string $formId, array $listUuids = []): string {
    $csrfToken = $_SESSION['newsletter_csrf_token'];
    $nonce = bin2hex(random_bytes(8));
    $escapedIntro = htmlspecialchars($introText, ENT_QUOTES, 'UTF-8');
    $escapedFormId = htmlspecialchars($formId, ENT_QUOTES, 'UTF-8');
    $t = newsletterGetTranslations();
    $listUuidsField = !empty($listUuids)
        ? "\n" . '            <input type="hidden" name="newsletter_list_uuids" value="' . htmlspecialchars(implode(',', $listUuids), ENT_QUOTES, 'UTF-8') . '">'
        : '';

    $html = <<<HTML
<section class="newsletter-section newsletter-hero escape" id="{$escapedFormId}">
    <div class="newsletter-content contain">
        <p class="newsletter-intro">{$escapedIntro}</p>
        <form class="newsletter-form" method="post" data-newsletter-form data-success-message="{$t['successMessage']}" data-error-message="{$t['errorMessage']}">
            <input type="hidden" name="newsletter_csrf" value="{$csrfToken}">
            <input type="hidden" name="newsletter_form_id" value="{$escapedFormId}">{$listUuidsField}
            <div class="newsletter-fields">
                <div class="newsletter-field">
                    <label for="newsletter_name_{$nonce}" class="visually-hidden">{$t['nameLabel']}</label>
                    <input type="text" id="newsletter_name_{$nonce}" name="newsletter_name" placeholder="{$t['namePlaceholder']}" required maxlength="100">
                </div>
                <div class="newsletter-field">
                    <label for="newsletter_email_{$nonce}" class="visually-hidden">{$t['emailLabel']}</label>
                    <input type="email" id="newsletter_email_{$nonce}" name="newsletter_email" placeholder="{$t['emailPlaceholder']}" required maxlength="100">
                </div>
            </div>
            <p class="newsletter-notice">{$t['notice']}</p>
            <button type="submit" name="newsletter_submit" class="button bigger inverted">
                <span class="btn-text">{$t['submitButton']}</span>
                <span class="btn-spinner" aria-hidden="true"></span>
                <span class="btn-success" aria-hidden="true">&#10003; <span class="btn-success-text"></span></span>
                <span class="btn-error" aria-hidden="true">&#10007; <span class="btn-error-text"></span></span>
            </button>
        </form>
    </div>
</section>
HTML;

    return $html;
}

/**
 * Render the "small" theme - compact inline notice with border
 */
function newsletterRenderSmall(string $introText, string $formId, array $listUuids = []): string {
    $csrfToken = $_SESSION['newsletter_csrf_token'];
    $nonce = bin2hex(random_bytes(8));
    $escapedIntro = htmlspecialchars($introText, ENT_QUOTES, 'UTF-8');
    $escapedFormId = htmlspecialchars($formId, ENT_QUOTES, 'UTF-8');
    $t = newsletterGetTranslations();
    $listUuidsField = !empty($listUuids)
        ? "\n" . '        <input type="hidden" name="newsletter_list_uuids" value="' . htmlspecialchars(implode(',', $listUuids), ENT_QUOTES, 'UTF-8') . '">'
        : '';

    $html = <<<HTML
<aside class="newsletter-section newsletter-small" id="{$escapedFormId}">
    <p class="newsletter-intro">{$escapedIntro}</p>
    <form class="newsletter-form" method="post" data-newsletter-form data-success-message="{$t['successMessage']}" data-success-confirm="{$t['successConfirm']}" data-error-message="{$t['errorMessage']}">
        <input type="hidden" name="newsletter_csrf" value="{$csrfToken}">
        <input type="hidden" name="newsletter_form_id" value="{$escapedFormId}">{$listUuidsField}
        <div class="newsletter-fields">
            <div class="newsletter-field">
                <label for="newsletter_email_{$nonce}" class="visually-hidden">{$t['emailLabel']}</label>
                <input type="email" id="newsletter_email_{$nonce}" name="newsletter_email" placeholder="{$t['emailPlaceholder']}" required maxlength="100">
            </div>
            <div class="newsletter-field">
                <label for="newsletter_name_{$nonce}" class="visually-hidden">{$t['nameLabel']}</label>
                <input type="text" id="newsletter_name_{$nonce}" name="newsletter_name" placeholder="{$t['namePlaceholder']}" required maxlength="100">
            </div>
            <button type="submit" name="newsletter_submit" class="button">
                <span class="btn-text">{$t['submitButton']}</span>
                <span class="btn-spinner" aria-hidden="true"></span>
                <span class="btn-success" aria-hidden="true">&#10003; <span class="btn-success-text"></span></span>
                <span class="btn-error" aria-hidden="true">&#10007; <span class="btn-error-text"></span></span>
            </button>
        </div>
    </form>
</aside>
HTML;

    return $html;
}

/**
 * Get CSS for all themes (only included once per page)
 */
function newsletterGetStyles(): string {
    static $stylesIncluded = false;
    if ($stylesIncluded) {
        return '';
    }
    $stylesIncluded = true;

    return <<<'STYLES'
<style>
/* Shared styles */
.newsletter-form {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}
.newsletter-form .btn-spinner,
.newsletter-form .btn-success,
.newsletter-form .btn-error {
    display: none;
}
.newsletter-form .button {
    position: relative;
}
.newsletter-form .button.is-loading .btn-text { visibility: hidden; }
.newsletter-form .button.is-loading .btn-spinner {
    display: block;
    position: absolute;
    inset: 0;
    margin: auto;
    width: 1.2rem;
    height: 1.2rem;
    border: 2px solid transparent;
    border-top-color: currentColor;
    border-radius: 50%;
    animation: newsletter-spin 0.8s linear infinite;
}
.newsletter-form .button.is-success .btn-text { display: none; }
.newsletter-form .button.is-success .btn-success { display: inline; }
.newsletter-form .button.is-error .btn-text { display: none; }
.newsletter-form .button.is-error .btn-error { display: inline; }
@keyframes newsletter-spin {
    to { transform: rotate(360deg); }
}
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Hero theme */
.newsletter-hero {
    background: linear-gradient(135deg, var(--color-green), var(--color-blue));
    color: white;
    padding: 1rem 1rem 2rem 1rem;
    margin-top: 3rem;
}
.newsletter-hero .newsletter-content {
    text-align: center;
}
.newsletter-hero .newsletter-intro {
    font-size: clamp(1.1rem, 3vw, 1.3rem);
    line-height: 1.5;
}
.newsletter-hero .newsletter-fields {
    display: flex;
    gap: 0.8rem;
    width: 100%;
    max-width: 32rem;
    flex-direction: row;
    flex-wrap: wrap;
}
.newsletter-hero .newsletter-field {
    flex: 1 1 clamp(45%, (20rem - 100vw) * 999, 100%);
    min-width: 0;
}
.newsletter-hero .newsletter-field input {
    width: 100%;
    padding: 0.7rem 1rem;
    border: none;
    border-radius: 2rem;
    font-family: inherit;
    font-size: 1rem;
    box-sizing: border-box;
}
.newsletter-hero .newsletter-field input:focus {
    outline: 2px solid white;
    outline-offset: 2px;
}
.newsletter-hero .newsletter-notice {
    font-size: 0.85rem;
    opacity: 0.9;
    margin: 0;
}
.newsletter-hero .button {
    min-width: 10rem;
}
.newsletter-hero .button.is-success { background-color: white; color: var(--color-green); }
.newsletter-hero .button.is-error { background-color: oklch(0.55 0.2 25); color: white; outline: none; }

/* Small theme */
.newsletter-small {
    border: 2px solid var(--color-green);
    border-radius: 0.5rem;
    padding: 0.6rem 0.8rem;
    margin-top: 2em;
}
.newsletter-small .newsletter-intro {
    margin-top: 0;
    margin-bottom: 0.5rem;
    font-weight: 600;
    // text-align: center;
    font-size: 1.2rem;
}
.newsletter-small .newsletter-form {
    align-items: stretch;
    gap: 0;
    margin-top:0;
}
.newsletter-small .newsletter-fields {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    align-items: center;
}
.newsletter-small .newsletter-field {
    flex: 1 1 clamp(30%, (28rem - 100%) * 999, 100%);
    min-width: 0;
}
.newsletter-small .newsletter-field input {
    width: 100%;
    padding: 0.4rem 0.7rem;
    border: 1px solid oklch(0.8 0 0);
    border-radius: 0.25rem;
    font-family: inherit;
    font-size: 0.9rem;
    box-sizing: border-box;
}
.newsletter-small .newsletter-field input:focus {
    outline: none;
    border-color: var(--color-green);
    box-shadow: 0 0 0 0.15rem oklch(0.618 0.1176 173.93 / 0.25);
}
.newsletter-small .button {
    flex-shrink: 0;
    padding: 0.2rem 0.8rem;
    font-size: 0.9rem;
    margin-top:0;
}
.newsletter-small .newsletter-confirm {
    margin: 0.3rem 0 0;
    font-size: 0.95rem;
    color: var(--color-green);
    font-weight: 600;
}
.newsletter-small .button.is-success { background-color: var(--color-green); color: white; }
.newsletter-small .button.is-error { background-color: oklch(0.55 0.2 25); color: white; outline: none; }
</style>
STYLES;
}

/**
 * Render the newsletter signup section HTML
 * This is the main function to call from content files.
 *
 * @param string $introText Custom intro text to display above the form
 * @param string $theme Theme to use: 'hero' (default) or 'small'
 * @param array $listUuids Optional Listmonk list UUIDs for this form (default: uses global config)
 * @param string $formId Optional form ID for the section (default: 'newsletter')
 * @return string The complete HTML for the newsletter signup section
 */
function newsletter_signup(string $introText, string $theme = 'hero', array $listUuids = [], string $formId = 'newsletter'): string {
    $html = newsletterGetStyles();

    switch ($theme) {
        case 'small':
            $html .= newsletterRenderSmall($introText, $formId, $listUuids);
            break;
        case 'hero':
        default:
            $html .= newsletterRenderHero($introText, $formId, $listUuids);
            break;
    }

    $html .= newsletterGetScript();

    return $html;
}

/**
 * Handle AJAX form submission
 */
function newsletterHandleSubmission(): void {
    if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['newsletter_submit'])) {
        return;
    }

    header('Content-Type: application/json');

    // CSRF validation
    if (!isset($_POST['newsletter_csrf']) ||
        !hash_equals($_SESSION['newsletter_csrf_token'] ?? '', $_POST['newsletter_csrf'])) {
        echo json_encode(['success' => false, 'error' => 'csrf']);
        exit;
    }

    // Rate limit
    if (!newsletterCheckRateLimit()) {
        echo json_encode(['success' => false, 'error' => 'rate_limit']);
        exit;
    }

    // Validate input
    $name = trim($_POST['newsletter_name'] ?? '');
    $email = strtolower(trim($_POST['newsletter_email'] ?? ''));

    if (empty($name) || strlen($name) < 2 || strlen($name) > 100) {
        echo json_encode(['success' => false, 'error' => 'invalid_name']);
        exit;
    }

    if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > 100) {
        echo json_encode(['success' => false, 'error' => 'invalid_email']);
        exit;
    }

    // Parse per-form list UUIDs (if provided)
    $listUuids = [];
    if (!empty($_POST['newsletter_list_uuids'])) {
        $raw = explode(',', $_POST['newsletter_list_uuids']);
        foreach ($raw as $uuid) {
            $uuid = trim($uuid);
            if (preg_match('/^[0-9a-f\-]{36}$/i', $uuid)) {
                $listUuids[] = $uuid;
            }
        }
    }

    // Subscribe
    $result = newsletterSubscribe($email, $name, $listUuids);

    if ($result['success']) {
        $_SESSION['newsletter_last_submit'] = time();
    }

    echo json_encode($result);
    exit;
}

// Handle form submission early (before any output)
newsletterHandleSubmission();
