<?php

namespace App\Http\Controllers;

use App\Domain\Shared\Models\Academy;
use App\Domain\Website\Models\WebsitePage;
use App\Domain\Website\Services\WebsiteSettingService;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Renders builder pages (website_pages + website_blocks).
 *
 * Runs after every other web route so a page slug can never shadow a real
 * application route; WebsitePageService additionally refuses reserved slugs.
 */
class WebsitePageController extends Controller
{
    public function __construct(
        private readonly WebsiteSettingService $settings,
    ) {}

    /**
     * Fallback entry point. Route::fallback passes no route parameters, so the
     * slug is taken from the request path rather than a bound argument.
     */
    public function fallback(Request $request)
    {
        $slug = trim($request->path(), '/');

        if ($slug === '' || $slug === '/') {
            throw new NotFoundHttpException;
        }

        return $this->show($request, $slug);
    }

    public function show(Request $request, string $slug)
    {
        $academy = $this->academy();

        $page = WebsitePage::query()
            ->where('slug', $slug)
            ->when(! $this->canPreview($request), fn ($q) => $q->where('is_published', true))
            ->first();

        if (! $page) {
            throw new NotFoundHttpException;
        }

        return $this->renderPage($academy, $page);
    }

    /** Homepage, when the academy has promoted a builder page to be it. */
    public function home(Request $request)
    {
        $academy = $this->academy();

        $page = WebsitePage::query()
            ->where('is_homepage', true)
            ->when(! $this->canPreview($request), fn ($q) => $q->where('is_published', true))
            ->first();

        if (! $page) {
            throw new NotFoundHttpException;
        }

        return $this->renderPage($academy, $page);
    }

    /**
     * Entry point for "/". Serves a builder homepage when one exists, otherwise
     * hands off to the legacy section renderer so already-live tenants that have
     * not migrated keep their site exactly as it is.
     */
    public function homeOrLegacy(Request $request, PublicWebsiteController $legacy)
    {
        $hasBuilderHome = WebsitePage::query()
            ->where('is_homepage', true)
            ->where('is_published', true)
            ->exists();

        return $hasBuilderHome ? $this->home($request) : $legacy->home();
    }

    /** Draft preview for staff who can manage the site. */
    public function preview(Request $request, WebsitePage $page)
    {
        abort_unless($request->user()?->can('settings.manage'), 403);

        return $this->renderPage($this->academy(), $page, preview: true);
    }

    private function renderPage(Academy $academy, WebsitePage $page, bool $preview = false)
    {
        app()->instance('current_academy', $academy);

        $page->load(['blocks.childrenRecursive']);

        return view('website.page', [
            'academy' => $academy,
            'settings' => $this->settings->getOrCreate($academy),
            'page' => $page,
            'preview' => $preview,
        ]);
    }

    private function academy(): Academy
    {
        $academy = app()->bound('current_academy')
            ? app('current_academy')
            : Academy::first();

        abort_unless($academy, 404);

        return $academy;
    }

    private function canPreview(Request $request): bool
    {
        return (bool) $request->user()?->can('settings.manage');
    }
}
