<?php

declare(strict_types=1);

namespace App\Modules\PublicInvitation;

use App\Core\BaseController;
use App\Core\Request;
use App\Core\Session;
use App\Core\ErrorHandler;
use App\Modules\Theme\ThemeService;

/**
 * LivePreviewController — Renders the invitation exactly as a guest would see it.
 *
 * Live Preview is intentionally a completely separate feature from Preview:
 *
 *   Preview      → Preview Shell + device simulator + dummy content
 *   Live Preview → Standalone full page + production renderer + real data
 *
 * The Live Preview page has:
 *   - No toolbar
 *   - No iframe
 *   - No device simulator
 *   - No zoom controls
 *   - The page looks identical to the future public invitation
 *
 * Route: GET /{workspace_slug}/livepreview
 *
 * Access control: Requires an authenticated Couple session with a matching
 * workspace_id. The {workspace_slug} in the URL is used to resolve the workspace
 * and verify ownership against session.active_workspace_id.
 *
 * Zero writes: This action MUST NEVER write to the database.
 *   - No recordInvitationOpen()
 *   - No RSVP persistence
 *   - No guest creation
 *   - Analytics are disabled via the $live_preview = true flag in the payload
 *
 * @package Inveetaire
 * @ref     G014
 */
class LivePreviewController extends BaseController
{
    protected string $layout = '';

    private PublicInvitationService $previewService;
    private ThemeService            $themeService;

    public function __construct()
    {
        parent::__construct();
        $this->previewService = new PublicInvitationService();
        $this->themeService   = new ThemeService();
    }

    /**
     * Render the Live Preview page.
     *
     * Route: GET /{workspace_slug}/livepreview
     *
     * This action:
     *   1. Verifies the request comes from an authenticated Couple.
     *   2. Resolves the workspace by {workspace_slug} and validates ownership
     *      against session.active_workspace_id.
     *   3. Compiles the full render payload via getRenderedPayloadForPreview().
     *   4. Renders the production theme directly — the output IS the page.
     *   5. Injects the Live Preview badge + JS read-only interceptor before </body>.
     *
     * @param Request $request
     * @return void
     */
    public function show(Request $request): void
    {
        $this->layout = '';

        // ── 1. Resolve workspace by slug from URL ─────────────────────────
        $slug      = $request->param('workspace_slug', '');
        $workspace = $this->previewService->getWorkspaceBySlug($slug);

        if ($workspace === null) {
            http_response_code(404);
            echo '<!DOCTYPE html><html><body style="font-family:sans-serif;padding:3rem;color:#64748b;text-align:center;">';
            echo '<h2>Workspace Not Found</h2>';
            echo '<p>The requested invitation workspace does not exist.</p>';
            echo '</body></html>';
            return;
        }

        $workspaceId = (int) $workspace['id'];


        // ── 3. Resolve full render payload ────────────────────────────────
        $payload = $this->previewService->getRenderedPayloadForPreview($workspaceId);

        if ($payload === null) {
            http_response_code(404);
            echo '<!DOCTYPE html><html><body style="font-family:sans-serif;padding:3rem;color:#64748b;text-align:center;">';
            echo '<h2>Invitation Not Configured</h2>';
            echo '<p>Please configure your invitation in the Builder before using Live Preview.</p>';
            echo '</body></html>';
            return;
        }

        $brideName = $payload['workspace']['bride_name'] ?? 'Bride';
        $groomName = $payload['workspace']['groom_name'] ?? 'Groom';

        // ── 4. Build render payload ────────────────────────────────────────
        $renderPayload = [
            'title'        => "{$brideName} & {$groomName}",
            'workspace'    => $payload['workspace'],
            'guest'        => $payload['guest'],
            'invitation'   => $payload['invitation'],
            'events'       => $payload['events'],
            'theme'        => $payload['theme'],
            'sections'     => $payload['sections'],
            'url'          => $payload['personal_url'],
            'qr_code'      => $payload['qr_code'],
            'rsvp'         => $payload['rsvp']  ?? null,
            'wish'         => $payload['wish']  ?? null,
            'live_preview' => true, // Received as $live_preview in theme scope — disables analytics
        ];

        // ── 5. Capture theme output and inject badge ───────────────────────
        ob_start();
        $this->themeService->renderInvitation($renderPayload);
        $html = (string) ob_get_clean();

        $badge = $this->buildLivePreviewBadge();
        if (stripos($html, '</body>') !== false) {
            $html = str_ireplace('</body>', $badge . '</body>', $html);
        } else {
            $html .= $badge;
        }

        echo $html;
    }

    /**
     * Build the Live Preview floating badge HTML + JS read-only interceptor.
     *
     * Injected before </body> of the production theme output.
     *   - Badge: fixed top-right, amber pulsing dot, "Live Preview" label.
     *   - JS:    intercepts form submit, fetch POST, XHR POST → shows modal.
     *
     * @return string
     */
    private function buildLivePreviewBadge(): string
    {
        return <<<'LPHTML'

<!-- ── G014 Live Preview Badge & Read-Only Interceptor ──────────────────── -->
<style>
#lp-badge {
    position: fixed;
    top: 16px;
    right: 16px;
    z-index: 99999;
    display: flex;
    align-items: center;
    gap: 8px;
    background: rgba(15, 23, 42, 0.92);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 12px;
    padding: 10px 16px;
    font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', sans-serif;
    font-size: 12px;
    font-weight: 600;
    color: #f1f5f9;
    box-shadow: 0 8px 32px rgba(0,0,0,0.4), 0 2px 8px rgba(0,0,0,0.3);
    cursor: default;
    user-select: none;
    letter-spacing: 0.01em;
    transition: opacity 0.3s;
}
#lp-badge:hover { opacity: 0.85; }
#lp-pulse {
    width: 8px; height: 8px;
    background: #f59e0b;
    border-radius: 50%;
    animation: lp-pulse-anim 1.8s ease-in-out infinite;
    flex-shrink: 0;
}
@keyframes lp-pulse-anim {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%       { opacity: 0.5; transform: scale(0.75); }
}
#lp-badge-text  { display: flex; flex-direction: column; gap: 2px; }
#lp-badge-title { color: #fbbf24; font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; }
#lp-badge-sub   { color: #94a3b8; font-size: 10px; font-weight: 500; }

#lp-modal-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 999999;
    background: rgba(0,0,0,0.55);
    backdrop-filter: blur(4px);
    align-items: center;
    justify-content: center;
}
#lp-modal-overlay.lp-show { display: flex; }
#lp-modal {
    background: #0f172a;
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 20px;
    padding: 32px;
    max-width: 360px;
    width: calc(100% - 48px);
    text-align: center;
    font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', sans-serif;
    box-shadow: 0 24px 64px rgba(0,0,0,0.6);
    animation: lp-modal-in 0.25s ease;
}
@keyframes lp-modal-in {
    from { opacity: 0; transform: scale(0.92) translateY(8px); }
    to   { opacity: 1; transform: scale(1)    translateY(0);   }
}
#lp-modal-icon  { font-size: 36px; margin-bottom: 12px; }
#lp-modal-title { color: #fbbf24; font-size: 14px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 8px; }
#lp-modal-body  { color: #94a3b8; font-size: 13px; line-height: 1.6; margin-bottom: 20px; }
#lp-modal-close {
    display: inline-flex; align-items: center; justify-content: center;
    background: #1e293b; border: 1px solid rgba(255,255,255,0.12);
    border-radius: 10px; color: #f1f5f9; font-size: 13px; font-weight: 600;
    padding: 10px 24px; cursor: pointer;
    transition: background 0.2s, border-color 0.2s;
}
#lp-modal-close:hover { background: #334155; border-color: rgba(255,255,255,0.25); }
</style>

<div id="lp-badge" title="Live Preview — interactions are disabled">
    <span id="lp-pulse"></span>
    <div id="lp-badge-text">
        <span id="lp-badge-title">&#128065; Live Preview</span>
        <span id="lp-badge-sub">Viewing as Couple &middot; No data saved</span>
    </div>
</div>

<div id="lp-modal-overlay" role="dialog" aria-modal="true">
    <div id="lp-modal">
        <div id="lp-modal-icon">&#128274;</div>
        <div id="lp-modal-title">Live Preview Mode</div>
        <div id="lp-modal-body">
            This action is disabled because you are previewing the invitation.<br><br>
            RSVP responses, wishes, and attendance are not recorded during Live Preview.
        </div>
        <button id="lp-modal-close" type="button">Got it</button>
    </div>
</div>

<script>
(function () {
    'use strict';
    var overlay  = document.getElementById('lp-modal-overlay');
    var closeBtn = document.getElementById('lp-modal-close');
    function showModal() { if (overlay) overlay.classList.add('lp-show'); }
    if (closeBtn) closeBtn.addEventListener('click', function () { overlay.classList.remove('lp-show'); });
    if (overlay)  overlay.addEventListener('click', function (e) { if (e.target === overlay) overlay.classList.remove('lp-show'); });
    document.addEventListener('submit', function (e) { e.preventDefault(); e.stopImmediatePropagation(); showModal(); }, true);
    var _fetch = window.fetch;
    window.fetch = function (url, opts) {
        if (opts && opts.method && opts.method.toUpperCase() === 'POST') { showModal(); return Promise.resolve(new Response('{}', { status: 200 })); }
        return _fetch.apply(this, arguments);
    };
    var _open = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function (method) { if (method && method.toUpperCase() === 'POST') this._lpBlocked = true; return _open.apply(this, arguments); };
    var _send = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function () { if (this._lpBlocked) { showModal(); return; } return _send.apply(this, arguments); };
})();
</script>
<!-- ── /G014 Live Preview Badge ─────────────────────────────────────────── -->

LPHTML;
    }
}
