<?php

declare(strict_types=1);

namespace App\Support\Workspaces;

use App\Filament\Pages\ChooseWorkspace;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Tenants\TenantOperabilityService;
use App\Support\ManagedEnvironmentLinks;

/**
 * Resolves the explicit post-selection destination after a workspace is set.
 *
 * ManagedEnvironment-count branching stays available for chooser-driven flows:
 *  - 0 tenants  → Managed Tenants index
 *  - 1 tenant   → ManagedEnvironment Dashboard directly
 *  - >1 tenants → Choose ManagedEnvironment page
 */
final class WorkspaceRedirectResolver
{
    public function __construct(
        private TenantOperabilityService $tenantOperabilityService,
    ) {}

    /**
     * Resolve the redirect URL for the given workspace + user.
     *
     * Returns a fully qualified URL string.
     */
    public function resolve(Workspace $workspace, User $user, ?string $intendedUrl = null): string
    {
        if (is_string($intendedUrl)) {
            $resolvedIntendedUrl = $this->resolveSafeIntendedUrl($intendedUrl, $workspace, $user);

            if (is_string($resolvedIntendedUrl)) {
                return $resolvedIntendedUrl;
            }
        }

        $selectableTenants = $this->tenantOperabilityService->filterSelectable($user->accessibleManagedEnvironmentsQuery((int) $workspace->getKey())
            ->orderBy('name')
            ->get());

        $tenantCount = (int) $selectableTenants->count();

        if ($tenantCount === 0) {
            return $this->environmentChooserUrl($workspace);
        }

        if ($tenantCount === 1) {
            $tenant = $selectableTenants->first();

            if ($tenant !== null) {
                return ManagedEnvironmentLinks::viewUrl($tenant);
            }
        }

        return $this->environmentChooserUrl($workspace);
    }

    /**
     * Resolve the redirect URL using a workspace ID.
     *
     * Falls back to the chooser page if the workspace cannot be resolved.
     */
    public function resolveFromId(int $workspaceId, User $user): string
    {
        $workspace = Workspace::query()->whereKey($workspaceId)->first();

        if (! $workspace instanceof Workspace) {
            return ChooseWorkspace::getUrl();
        }

        return $this->resolve($workspace, $user);
    }

    private function resolveSafeIntendedUrl(string $intendedUrl, Workspace $workspace, User $user): ?string
    {
        $scheme = parse_url($intendedUrl, PHP_URL_SCHEME);
        $host = parse_url($intendedUrl, PHP_URL_HOST);

        if (str_starts_with($intendedUrl, '//')) {
            return null;
        }

        if ((is_string($scheme) || is_string($host)) && ! $this->isSameOriginUrl($intendedUrl)) {
            return null;
        }

        $path = '/'.ltrim((string) (parse_url($intendedUrl, PHP_URL_PATH) ?? ''), '/');

        if (! str_starts_with($path, '/admin')) {
            return null;
        }

        if ($this->isRetiredTenantPath($path)) {
            return null;
        }

        parse_str((string) (parse_url($intendedUrl, PHP_URL_QUERY) ?? ''), $query);

        if ($path === '/admin/operations') {
            return ManagedEnvironmentLinks::operationsUrl($workspace, $query);
        }

        if (str_starts_with($path, '/admin/operations/')) {
            return null;
        }

        $tenantIdentifier = $query['environment_id'] ?? $query['tenant'] ?? $query['managed_environment_id'] ?? null;

        if ($tenantIdentifier !== null && ! $this->tenantIdentifierMatchesWorkspace((string) $tenantIdentifier, $workspace, $user)) {
            return null;
        }

        return $intendedUrl;
    }

    private function tenantIdentifierMatchesWorkspace(string $identifier, Workspace $workspace, User $user): bool
    {
        $tenant = ManagedEnvironment::query()
            ->withTrashed()
            ->where(static function ($query) use ($identifier): void {
                $query->where('slug', $identifier);

                if (ctype_digit($identifier)) {
                    $query->orWhere((new ManagedEnvironment)->getQualifiedKeyName(), (int) $identifier);
                }
            })
            ->first();

        return $tenant instanceof ManagedEnvironment
            && (int) $tenant->workspace_id === (int) $workspace->getKey()
            && $user->canAccessTenant($tenant);
    }

    private function environmentChooserUrl(Workspace $workspace): string
    {
        return ManagedEnvironmentLinks::indexUrl($workspace);
    }

    private function isRetiredTenantPath(string $path): bool
    {
        return preg_match('#^/admin/(?:t|tenants)(?:/|$)#', $path) === 1;
    }

    private function isSameOriginUrl(string $url): bool
    {
        $urlHost = parse_url($url, PHP_URL_HOST);

        if (! is_string($urlHost) || $urlHost === '') {
            return true;
        }

        $appUrl = url('/');
        $appHost = parse_url($appUrl, PHP_URL_HOST);

        if (! is_string($appHost) || ! hash_equals($appHost, $urlHost)) {
            return false;
        }

        $urlScheme = parse_url($url, PHP_URL_SCHEME);
        $appScheme = parse_url($appUrl, PHP_URL_SCHEME);

        return ! is_string($urlScheme)
            || ! is_string($appScheme)
            || hash_equals($appScheme, $urlScheme);
    }
}
