<?php

namespace Modules\ClinicSite\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Modules\ClinicSite\Entities\CsSite;
use Modules\ClinicSite\Http\Controllers\Site\SiteRenderController;

/**
 * Front-controller for the multi-tenant public website.
 *
 * Registered as GLOBAL middleware (runs before the router), so the clinic
 * website can own the root "/" of its own host without colliding with the
 * ERP's own root routes. On ERP/admin hosts — and for reserved first-segment
 * paths like /portal, /app, /api — it is a fast no-op and the request flows
 * to the normal Laravel router untouched.
 */
class ResolveTenantSite
{
    public function handle(Request $request, Closure $next)
    {
        $host = strtolower($request->getHost());

        // 1) Admin/ERP hosts are never tenant sites.
        if ($this->isAdminHost($host)) {
            return $next($request);
        }

        // 2) Reserved paths (portal, app, api, assets…) always flow to the ERP,
        //    even on a clinic host — so clinic.example.com/portal still works.
        $first = strtolower((string) $request->segment(1));
        if ($first !== '' && in_array($first, (array) config('clinicsite.reserved_paths', []), true)) {
            return $next($request);
        }

        // 3) Try to resolve a clinic site for this host.
        $site = $this->resolve($host);
        if (! $site) {
            return $next($request);
        }

        app()->instance('clinicsite.current', $site);

        // 4) Published gate — owners can preview a draft with ?preview=1.
        if (! $site->isPublished() && ! $request->boolean('preview')) {
            return response()->view('clinicSite::site.coming_soon', ['site' => $site], 200);
        }

        return app(SiteRenderController::class)->dispatch($request, $site);
    }

    protected function isAdminHost(string $host): bool
    {
        $admin = array_map('strtolower', (array) config('clinicsite.admin_hosts', []));
        $admin[] = 'localhost';
        $admin[] = '127.0.0.1';

        $appHost = parse_url((string) config('app.url'), PHP_URL_HOST);
        if ($appHost) {
            $admin[] = strtolower($appHost);
        }

        return in_array($host, array_unique(array_filter($admin)), true);
    }

    protected function resolve(string $host): ?CsSite
    {
        // (a) exact custom domain
        $site = CsSite::where('custom_domain', $host)->first();
        if ($site) {
            return $site;
        }

        // (b) wildcard subdomain under the configured base domain
        $base = strtolower((string) config('clinicsite.base_domain'));
        $label = null;

        if ($base && $host !== $base && str_ends_with($host, '.' . $base)) {
            $label = substr($host, 0, -1 * (strlen($base) + 1));
        } elseif (! $base && substr_count($host, '.') >= 1) {
            // No base configured — treat the left-most label as the slug.
            $label = explode('.', $host)[0];
        }

        if ($label && $label !== 'www') {
            return CsSite::where('subdomain_slug', $label)->first();
        }

        return null;
    }
}
