<?php

declare(strict_types=1);

namespace App\Filament\Concerns;

use App\Models\Tenant;
use App\Support\OperateHub\OperateHubShell;
use Filament\Facades\Filament;
use RuntimeException;

trait ResolvesPanelTenantContext
{
    protected static function resolveTenantContextForCurrentPanel(): ?Tenant
    {
        $request = request();

        if (static::currentPanelId($request) === 'admin') {
            $tenant = app(OperateHubShell::class)->tenantOwnedPanelContext(request());

            return $tenant instanceof Tenant ? $tenant : null;
        }

        $tenant = Tenant::current();

        return $tenant instanceof Tenant ? $tenant : null;
    }

    public static function panelTenantContext(): ?Tenant
    {
        return static::resolveTenantContextForCurrentPanel();
    }

    public static function trustedPanelTenantContext(): ?Tenant
    {
        return static::panelTenantContext();
    }

    protected static function resolveTenantContextForCurrentPanelOrFail(): Tenant
    {
        $tenant = static::resolveTenantContextForCurrentPanel();

        if (! $tenant instanceof Tenant) {
            throw new RuntimeException('No tenant context selected.');
        }

        return $tenant;
    }

    protected static function resolveTrustedPanelTenantContextOrFail(): Tenant
    {
        return static::resolveTenantContextForCurrentPanelOrFail();
    }

    private static function currentPanelId(mixed $request): ?string
    {
        $panelId = Filament::getCurrentPanel()?->getId();

        if (is_string($panelId) && $panelId !== '') {
            return $panelId;
        }

        $routeName = is_object($request) && method_exists($request, 'route')
            ? $request->route()?->getName()
            : null;

        if (is_string($routeName) && $routeName !== '') {
            if (str_contains($routeName, '.tenant.')) {
                return 'tenant';
            }

            if (str_contains($routeName, '.admin.')) {
                return 'admin';
            }
        }

        $path = is_object($request) && method_exists($request, 'path')
            ? '/'.ltrim((string) $request->path(), '/')
            : null;

        if (is_string($path) && str_starts_with($path, '/admin/t/')) {
            return 'tenant';
        }

        if (is_string($path) && str_starts_with($path, '/admin/')) {
            return 'admin';
        }

        return null;
    }
}
