<?php

declare(strict_types=1);

namespace App\Modules\PublicInvitation;

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

/**
 * PublicInvitationController — HTTP Handler for public-facing guest invitation links.
 *
 * Scoped only to URL-token mapping, error redirection, and view delegation.
 * Thin design with no SQL queries or business logic.
 *
 * RC-009: Rendering is fully delegated to ThemeService.
 * The controller has no knowledge of theme paths or file structure.
 *
 * @package Inveetaire
 * @ref     PILOT-003, RC-009
 */
class PublicInvitationController extends BaseController
{
    // The public guest invitation template doesn't share couple/admin dashboard layouts.
    protected string $layout = '';
    private PublicInvitationService $service;
    private ThemeService $themeService;

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

    /**
     * Show the guest's personalized landing page.
     * Route: GET /{workspace_slug}/i/{guest_token}
     *
     * @param Request $request
     * @return void
     */
    public function show(Request $request): void
    {
        $slug = (string) $request->param('workspace_slug');
        $token = (string) $request->param('guest_token');

        if ($slug === '' || $token === '') {
            ErrorHandler::renderNotFound();
            return;
        }

        // Resolve structured guest identity parameters
        $payload = $this->service->getRenderedPayload($slug, $token);

        if ($payload === null) {
            // Return 404 for invalid tokens or slugs
            ErrorHandler::renderNotFound();
            return;
        }

        $brideName = $payload['workspace']['bride_name'] ?? 'Bride';
        $groomName = $payload['workspace']['groom_name'] ?? 'Groom';
        $titleText = "{$brideName} & {$groomName} — Wedding Invitation";

        // Build the render payload (no layout wrapping — theme handles its own HTML)
        $renderPayload = [
            'title'      => $titleText,
            '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,
            'gift_settings' => $payload['gift_settings'] ?? null,
            'gift_accounts' => $payload['gift_accounts'] ?? [],
        ];

        // Delegate rendering to the Theme Engine.
        // The controller does not know theme paths or file structure.
        $this->themeService->renderInvitation($renderPayload);
    }

    /**
     * Public QR Code validation endpoint.
     * Route: GET /i/validation/{guest_token}
     *
     * @param Request $request
     * @return void
     */
    public function validateQr(Request $request): void
    {
        $token = trim((string) $request->param('guest_token'));

        if ($token === '') {
            $this->json([
                'validation_result' => 'invalid'
            ], 400, 'Token parameter is required.');
            return;
        }

        // Query the database via the model to validate the token
        $publicModel = new PublicInvitationModel();
        $data = $publicModel->getValidationData($token);

        if ($data === null) {
            $this->json([
                'validation_result' => 'invalid'
            ], 404, 'Invitation QR code not recognized.');
            return;
        }

        // Verify active workspace + published invitation
        $isWorkspaceActive   = ($data['workspace_status'] ?? '') === 'active';
        $isInvitationPublished = ($data['invitation_status'] ?? '') === 'published';

        if (!$isWorkspaceActive || !$isInvitationPublished) {
            $this->json([
                'validation_result' => 'invalid'
            ], 403, 'Invitation is currently inactive or unpublished.');
            return;
        }

        // Prepare secure validation payload response
        $this->json([
            'validation_result' => 'valid',
            'guest_name'        => $data['full_name'],
            'honorific'         => $data['honorific'],
            'guest_group'       => $data['guest_group'],
            'invited_pax'       => (int) ($data['invited_pax'] ?? 1),
            'workspace_slug'    => $data['workspace_slug'],
            'couple_names'      => trim(($data['groom_display_name'] ?? '') . ' & ' . ($data['bride_display_name'] ?? ''))
        ], 200, 'Invitation is valid.');
    }
}
