<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\UserTenantPreference;
use App\Services\Tenants\TenantOperabilityService;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Tenants\TenantInteractionLane;
use App\Support\Tenants\TenantOperabilityQuestion;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Schema;

final class SelectEnvironmentController
{
    public function __invoke(Request $request): RedirectResponse
    {
        $user = auth()->user();

        if (! $user instanceof User) {
            abort(403);
        }

        $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId($request);

        if ($workspaceId === null) {
            return redirect()->to('/admin/choose-workspace');
        }

        $validated = $request->validate([
            'managed_environment_id' => ['required', 'integer'],
        ]);

        $tenant = ManagedEnvironment::query()
            ->where('workspace_id', $workspaceId)
            ->whereKey($validated['managed_environment_id'])
            ->first();

        if (! $tenant instanceof ManagedEnvironment) {
            abort(404);
        }

        if (! $user->canAccessTenant($tenant)) {
            abort(404);
        }

        $outcome = app(TenantOperabilityService::class)->outcomeFor(
            tenant: $tenant,
            question: TenantOperabilityQuestion::SelectorEligibility,
            actor: $user,
            workspaceId: $workspaceId,
            lane: TenantInteractionLane::StandardActiveOperating,
        );

        if (! $outcome->allowed) {
            abort(404);
        }

        $this->persistLastTenant($user, $tenant);

        if (! app(WorkspaceContext::class)->rememberEnvironmentContext($tenant, $request)) {
            abort(404);
        }

        return redirect()->to(ManagedEnvironmentLinks::viewUrl($tenant));
    }

    private function persistLastTenant(User $user, ManagedEnvironment $tenant): void
    {
        if (Schema::hasColumn('users', 'last_tenant_id')) {
            $user->forceFill(['last_tenant_id' => $tenant->getKey()])->save();

            return;
        }

        if (! Schema::hasTable('user_managed_environment_preferences')) {
            return;
        }

        UserTenantPreference::query()->updateOrCreate(
            ['user_id' => $user->getKey(), 'managed_environment_id' => $tenant->getKey()],
            ['last_used_at' => now()]
        );
    }
}
