<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        if (! Schema::hasTable('provider_connections')) {
            return;
        }

        $driver = Schema::getConnection()->getDriverName();

        if ($driver === 'sqlite') {
            if (! Schema::hasColumn('provider_connections', 'workspace_id')) {
                Schema::table('provider_connections', function (Blueprint $table): void {
                    $table->unsignedBigInteger('workspace_id')->nullable()->after('id');
                });
            }

            DB::statement(<<<'SQL'
                UPDATE provider_connections
                SET workspace_id = (
                    SELECT managed_environments.workspace_id
                    FROM managed_environments
                    WHERE managed_environments.id = provider_connections.managed_environment_id
                )
                WHERE workspace_id IS NULL
            SQL);

            Schema::table('provider_connections', function (Blueprint $table): void {
                $table->index(['workspace_id', 'provider', 'status']);
                $table->index(['workspace_id', 'provider', 'health_status']);
            });

            return;
        }

        if (! Schema::hasColumn('provider_connections', 'workspace_id')) {
            Schema::table('provider_connections', function (Blueprint $table) use ($driver): void {
                $column = $table->foreignId('workspace_id')->nullable();

                if ($driver !== 'sqlite') {
                    $column->after('id')->constrained('workspaces')->cascadeOnDelete();
                }

                $table->index('workspace_id');
            });
        }

        $this->backfillWorkspaceId($driver);

        if ($driver === 'pgsql') {
            DB::statement('ALTER TABLE provider_connections ALTER COLUMN workspace_id SET NOT NULL');
        }

        if ($driver === 'mysql') {
            DB::statement('ALTER TABLE provider_connections MODIFY workspace_id BIGINT UNSIGNED NOT NULL');
        }

        Schema::table('provider_connections', function (Blueprint $table): void {
            $table->index(['workspace_id', 'provider', 'status']);
            $table->index(['workspace_id', 'provider', 'health_status']);
        });
    }

    public function down(): void
    {
        if (! Schema::hasTable('provider_connections')) {
            return;
        }

        $driver = Schema::getConnection()->getDriverName();

        if ($driver === 'sqlite') {
            return;
        }

        if (! Schema::hasColumn('provider_connections', 'workspace_id')) {
            return;
        }

        Schema::table('provider_connections', function (Blueprint $table): void {
            $table->dropIndex(['workspace_id']);
            $table->dropIndex(['workspace_id', 'provider', 'status']);
            $table->dropIndex(['workspace_id', 'provider', 'health_status']);
            $table->dropConstrainedForeignId('workspace_id');
        });
    }

    private function backfillWorkspaceId(string $driver): void
    {
        if ($driver === 'pgsql') {
            DB::statement(<<<'SQL'
                UPDATE provider_connections
                SET workspace_id = managed_environments.workspace_id
                FROM managed_environments
                WHERE provider_connections.workspace_id IS NULL
                  AND provider_connections.managed_environment_id = managed_environments.id
            SQL);

            return;
        }

        DB::table('provider_connections')
            ->whereNull('workspace_id')
            ->orderBy('id')
            ->chunkById(500, function ($rows): void {
                foreach ($rows as $row) {
                    $workspaceId = DB::table('managed_environments')
                        ->where('id', $row->managed_environment_id)
                        ->value('workspace_id');

                    if ($workspaceId === null) {
                        $workspaceId = DB::table('managed_environment_memberships')
                            ->join('workspace_memberships', 'workspace_memberships.user_id', '=', 'managed_environment_memberships.user_id')
                            ->where('managed_environment_memberships.managed_environment_id', (int) $row->managed_environment_id)
                            ->orderByRaw("CASE managed_environment_memberships.role WHEN 'owner' THEN 0 WHEN 'manager' THEN 1 WHEN 'operator' THEN 2 ELSE 3 END")
                            ->value('workspace_memberships.workspace_id');
                    }

                    if ($workspaceId !== null) {
                        DB::table('provider_connections')
                            ->where('id', $row->id)
                            ->update(['workspace_id' => (int) $workspaceId]);
                    }
                }
            }, 'id');
    }
};
