<?php

namespace App\Http\Controllers;

use App\Models\ProviderConnection;
use App\Models\ManagedEnvironment;
use App\Services\Intune\AuditLogger;
use App\Services\Providers\AdminConsentUrlFactory;
use App\Support\Providers\ProviderConnectionType;
use App\Support\Providers\ProviderConsentStatus;
use App\Support\Providers\ProviderReasonCodes;
use App\Support\Providers\ProviderVerificationStatus;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;

class ManagedEnvironmentOnboardingController extends Controller
{
    public function __invoke(
        Request $request,
        AdminConsentUrlFactory $consentUrlFactory,
        AuditLogger $auditLogger,
    ): RedirectResponse {
        $tenantIdentifier = $request->string('tenant')->toString();
        abort_if($tenantIdentifier === '', ResponseAlias::HTTP_NOT_FOUND);

        $state = Str::uuid()->toString();
        $request->session()->put('environment_onboard_state', $state);

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

        if ($workspaceId !== null) {
            $request->session()->put('environment_onboard_workspace_id', (int) $workspaceId);
        }

        $tenant = $this->resolveTenant($tenantIdentifier, is_numeric($workspaceId) ? (int) $workspaceId : null);
        $connection = $this->upsertPlatformConnection($tenant);
        $url = $consentUrlFactory->make($connection, $state);

        $auditLogger->log(
            tenant: $tenant,
            action: 'provider_connection.consent_started',
            context: [
                'metadata' => [
                    'source' => 'admin.consent.start',
                    'workspace_id' => (int) $connection->workspace_id,
                    'provider_connection_id' => (int) $connection->getKey(),
                    'provider' => (string) $connection->provider,
                    'entra_tenant_id' => (string) $connection->entra_tenant_id,
                    'connection_type' => $connection->connection_type->value,
                    'effective_client_id' => trim((string) config('graph.client_id')),
                    'state' => $state,
                ],
            ],
            actorId: auth()->id(),
            actorEmail: auth()->user()?->email,
            actorName: auth()->user()?->name,
            resourceType: 'provider_connection',
            resourceId: (string) $connection->getKey(),
            status: 'success',
        );

        return redirect()->away($url);
    }

    private function resolveTenant(string $tenantIdentifier, ?int $workspaceId): ManagedEnvironment
    {
        $tenant = ManagedEnvironment::query()
            ->where(function ($query) use ($tenantIdentifier): void {
                $query->where('slug', $tenantIdentifier);
            })
            ->first();

        if ($tenant instanceof ManagedEnvironment) {
            if ($tenant->workspace_id === null && $workspaceId !== null) {
                $tenant->forceFill(['workspace_id' => $workspaceId])->save();
            }

            return $tenant;
        }

        abort_if($workspaceId === null, ResponseAlias::HTTP_FORBIDDEN, 'Missing workspace context');

        return ManagedEnvironment::create([
            'slug' => $tenantIdentifier,
            'name' => 'New ManagedEnvironment',
            'workspace_id' => $workspaceId,
        ]);
    }

    private function upsertPlatformConnection(ManagedEnvironment $tenant): ProviderConnection
    {
        $hasDefault = ProviderConnection::query()
            ->where('managed_environment_id', (int) $tenant->getKey())
            ->where('provider', 'microsoft')
            ->where('is_default', true)
            ->exists();

        $connection = ProviderConnection::query()->updateOrCreate(
            [
                'managed_environment_id' => (int) $tenant->getKey(),
                'provider' => 'microsoft',
                'entra_tenant_id' => (string) ($tenant->graphTenantId() ?? $tenant->managed_environment_id ?? $tenant->external_id),
            ],
            [
                'workspace_id' => (int) $tenant->workspace_id,
                'display_name' => (string) ($tenant->name ?? 'Microsoft Connection'),
                'is_enabled' => true,
                'connection_type' => ProviderConnectionType::Platform->value,
                'consent_status' => ProviderConsentStatus::Required->value,
                'consent_granted_at' => null,
                'consent_last_checked_at' => null,
                'consent_error_code' => null,
                'consent_error_message' => null,
                'verification_status' => ProviderVerificationStatus::Unknown->value,
                'migration_review_required' => false,
                'migration_reviewed_at' => null,
                'last_error_reason_code' => ProviderReasonCodes::ProviderConsentMissing,
                'last_error_message' => null,
                'is_default' => $hasDefault ? false : true,
            ],
        );

        $connection->credential()->delete();

        if (! $hasDefault && ! $connection->is_default) {
            $connection->makeDefault();
        }

        return $connection->fresh();
    }
}
