<?php

declare(strict_types=1);

namespace App\Filament\Concerns;

use App\Models\ManagedEnvironment;
use App\Models\Workspace;
use Filament\Facades\Filament;
use Filament\Panel;
use Illuminate\Database\Eloquent\Model;

trait WorkspaceScopedEnvironmentRoutes
{
    public static function getSlug(?Panel $panel = null): string
    {
        return static::workspaceScopedSlug(parent::getSlug($panel), $panel);
    }

    /**
     * @param  array<string, mixed>  $parameters
     */
    public static function getUrl(?string $name = null, array $parameters = [], bool $isAbsolute = true, ?string $panel = null, ?Model $tenant = null, bool $shouldGuessMissingParameters = false): string
    {
        $panelId = $panel ?? Filament::getCurrentOrDefaultPanel()?->getId() ?? 'admin';

        if ($panelId !== 'admin') {
            return parent::getUrl($name, $parameters, $isAbsolute, $panelId, $tenant, $shouldGuessMissingParameters);
        }

        $resolvedTenant = static::resolveWorkspaceScopedEnvironment($parameters, $tenant);

        if (! $resolvedTenant instanceof ManagedEnvironment) {
            return url('/admin');
        }

        $workspace = static::resolveWorkspaceScopedWorkspace($resolvedTenant, $parameters);

        if (! $workspace instanceof Workspace && ! is_string($workspace) && ! is_int($workspace)) {
            return url('/admin');
        }

        $parameters['environment'] ??= $resolvedTenant;
        $parameters['workspace'] ??= $workspace;
        unset($parameters['tenant']);

        return parent::getUrl($name, $parameters, $isAbsolute, $panelId, null, $shouldGuessMissingParameters);
    }

    protected static function workspaceScopedSlug(string $slug, ?Panel $panel = null): string
    {
        if (! static::shouldUseWorkspaceScopedEnvironmentRoutes($panel)) {
            return $slug;
        }

        $prefix = 'workspaces/{workspace}/environments/{environment}/';

        return str_starts_with($slug, $prefix)
            ? $slug
            : $prefix.ltrim($slug, '/');
    }

    protected static function shouldUseWorkspaceScopedEnvironmentRoutes(?Panel $panel = null): bool
    {
        $panelId = $panel?->getId() ?? Filament::getCurrentOrDefaultPanel()?->getId() ?? 'admin';

        return $panelId === 'admin';
    }

    /**
     * @param  array<string, mixed>  $parameters
     */
    protected static function resolveWorkspaceScopedEnvironment(array $parameters, ?Model $tenant = null): ?ManagedEnvironment
    {
        $parameterTenant = $parameters['tenant'] ?? $parameters['environment'] ?? null;

        if ($parameterTenant instanceof ManagedEnvironment) {
            return $parameterTenant;
        }

        if ($tenant instanceof ManagedEnvironment) {
            return $tenant;
        }

        $record = $parameters['record'] ?? null;

        if ($record instanceof Model) {
            $relationshipName = static::workspaceScopedEnvironmentRelationshipName();

            if (method_exists($record, $relationshipName)) {
                $recordTenant = $record->getRelationValue($relationshipName);

                if (! $recordTenant instanceof ManagedEnvironment) {
                    $recordTenant = $record->{$relationshipName}()->first();
                }

                if ($recordTenant instanceof ManagedEnvironment) {
                    return $recordTenant;
                }
            }
        }

        if (method_exists(static::class, 'resolveTenantContextForCurrentPanel')) {
            $resolvedTenant = static::resolveTenantContextForCurrentPanel();

            if ($resolvedTenant instanceof ManagedEnvironment) {
                return $resolvedTenant;
            }
        }

        if (method_exists(static::class, 'panelTenantContext')) {
            $resolvedTenant = static::panelTenantContext();

            if ($resolvedTenant instanceof ManagedEnvironment) {
                return $resolvedTenant;
            }
        }

        return null;
    }

    /**
     * @param  array<string, mixed>  $parameters
     */
    protected static function resolveWorkspaceScopedWorkspace(ManagedEnvironment $tenant, array $parameters): Workspace|string|int|null
    {
        $workspace = $parameters['workspace'] ?? null;

        if ($workspace instanceof Workspace || is_string($workspace) || is_int($workspace)) {
            return $workspace;
        }

        $tenantWorkspace = $tenant->workspace;

        if ($tenantWorkspace instanceof Workspace) {
            return $tenantWorkspace;
        }

        return $tenant->workspace()->first();
    }

    protected static function workspaceScopedEnvironmentRelationshipName(): string
    {
        $relationshipName = property_exists(static::class, 'tenantOwnershipRelationshipName')
            ? static::$tenantOwnershipRelationshipName
            : null;

        return is_string($relationshipName) && $relationshipName !== ''
            ? $relationshipName
            : 'tenant';
    }
}
