<?php

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

return new class extends Migration
{
    /**
     * @return array<int, string>
     */
    private function tenantOwnedTables(): array
    {
        return [
            'policies',
            'policy_versions',
            'backup_sets',
            'backup_items',
            'restore_runs',
            'backup_schedules',
            'inventory_items',
            'inventory_links',
            'entra_groups',
            'findings',
            'entra_role_definitions',
            'managed_environment_permissions',
        ];
    }

    private function ensureWorkspaceForeignKey(string $tableName, string $constraintName): void
    {
        // Add as NOT VALID (fast) then VALIDATE (safe) — Postgres best practice.
        DB::unprepared(<<<SQL
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1
        FROM pg_constraint
        WHERE conname = '{$constraintName}'
    ) THEN
        EXECUTE format(
            'ALTER TABLE %I ADD CONSTRAINT %I FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE NOT VALID',
            '{$tableName}',
            '{$constraintName}'
        );
    END IF;

    IF EXISTS (
        SELECT 1
        FROM pg_constraint
        WHERE conname = '{$constraintName}'
          AND convalidated = false
    ) THEN
        EXECUTE format(
            'ALTER TABLE %I VALIDATE CONSTRAINT %I',
            '{$tableName}',
            '{$constraintName}'
        );
    END IF;
END
$$;
SQL);
    }

    public function up(): void
    {
        if (DB::getDriverName() !== 'pgsql') {
            return;
        }

        foreach ($this->tenantOwnedTables() as $tableName) {
            $constraintName = sprintf('%s_workspace_fk', $tableName);

            $this->ensureWorkspaceForeignKey($tableName, $constraintName);
        }
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        if (DB::getDriverName() !== 'pgsql') {
            return;
        }

        foreach ($this->tenantOwnedTables() as $tableName) {
            $constraintName = sprintf('%s_workspace_fk', $tableName);

            DB::unprepared(<<<SQL
DO $$
BEGIN
    EXECUTE format(
        'ALTER TABLE %I DROP CONSTRAINT IF EXISTS %I',
        '{$tableName}',
        '{$constraintName}'
    );
END
$$;
SQL);
        }
    }
};
