<?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
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        if (Schema::hasTable('roles') && !Schema::hasColumn('roles', 'dealer_id')) {
            Schema::table('roles', function (Blueprint $table) {
                $table->foreignId('dealer_id')->nullable()->constrained('dealers')->cascadeOnDelete();
            });
        }

        if (Schema::hasTable('model_has_roles') && !Schema::hasColumn('model_has_roles', 'dealer_id')) {
            Schema::table('model_has_roles', function (Blueprint $table) {
                $table->unsignedBigInteger('dealer_id')->nullable();
            });
        }

        if (Schema::hasTable('model_has_permissions') && !Schema::hasColumn('model_has_permissions', 'dealer_id')) {
            Schema::table('model_has_permissions', function (Blueprint $table) {
                $table->unsignedBigInteger('dealer_id')->nullable();
            });
        }

        if (Schema::hasTable('model_has_roles') && Schema::hasColumn('model_has_roles', 'dealer_id')) {
            if (!$this->columnHasIndex('model_has_roles', 'dealer_id')) {
                Schema::table('model_has_roles', function (Blueprint $table) {
                    $table->index('dealer_id');
                });
            }

            if (!$this->foreignKeyExists('model_has_roles', 'model_has_roles_dealer_id_foreign') && Schema::hasTable('dealers')) {
                Schema::table('model_has_roles', function (Blueprint $table) {
                    $table->foreign('dealer_id')->references('id')->on('dealers')->cascadeOnDelete();
                });
            }
        }

        if (Schema::hasTable('model_has_permissions') && Schema::hasColumn('model_has_permissions', 'dealer_id')) {
            if (!$this->columnHasIndex('model_has_permissions', 'dealer_id')) {
                Schema::table('model_has_permissions', function (Blueprint $table) {
                    $table->index('dealer_id');
                });
            }

            if (!$this->foreignKeyExists('model_has_permissions', 'model_has_permissions_dealer_id_foreign') && Schema::hasTable('dealers')) {
                Schema::table('model_has_permissions', function (Blueprint $table) {
                    $table->foreign('dealer_id')->references('id')->on('dealers')->cascadeOnDelete();
                });
            }
        }

        if (Schema::hasTable('roles')) {
            if ($this->indexExists('roles', 'roles_name_guard_name_unique')) {
                Schema::table('roles', function (Blueprint $table) {
                    $table->dropUnique('roles_name_guard_name_unique');
                });
            }

            if (!$this->indexExists('roles', 'roles_dealer_id_name_guard_name_unique')) {
                Schema::table('roles', function (Blueprint $table) {
                    $table->unique(['dealer_id', 'name', 'guard_name']);
                });
            }
        }
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        if (Schema::hasTable('roles')) {
            if ($this->indexExists('roles', 'roles_dealer_id_name_guard_name_unique')) {
                Schema::table('roles', function (Blueprint $table) {
                    $table->dropUnique('roles_dealer_id_name_guard_name_unique');
                });
            }

            if (!$this->indexExists('roles', 'roles_name_guard_name_unique')) {
                Schema::table('roles', function (Blueprint $table) {
                    $table->unique(['name', 'guard_name']);
                });
            }
        }

        if (Schema::hasTable('model_has_permissions') && Schema::hasColumn('model_has_permissions', 'dealer_id')) {
            Schema::table('model_has_permissions', function (Blueprint $table) {
                if ($this->foreignKeyExists('model_has_permissions', 'model_has_permissions_dealer_id_foreign')) {
                    $table->dropForeign(['dealer_id']);
                }
                $table->dropColumn('dealer_id');
            });
        }

        if (Schema::hasTable('model_has_roles') && Schema::hasColumn('model_has_roles', 'dealer_id')) {
            Schema::table('model_has_roles', function (Blueprint $table) {
                if ($this->foreignKeyExists('model_has_roles', 'model_has_roles_dealer_id_foreign')) {
                    $table->dropForeign(['dealer_id']);
                }
                $table->dropColumn('dealer_id');
            });
        }

        if (Schema::hasTable('roles') && Schema::hasColumn('roles', 'dealer_id')) {
            Schema::table('roles', function (Blueprint $table) {
                $table->dropConstrainedForeignId('dealer_id');
            });
        }
    }

    private function indexExists(string $table, string $indexName): bool
    {
        return DB::table('information_schema.statistics')
            ->where('table_schema', DB::getDatabaseName())
            ->where('table_name', $table)
            ->where('index_name', $indexName)
            ->exists();
    }

    private function foreignKeyExists(string $table, string $constraintName): bool
    {
        return DB::table('information_schema.table_constraints')
            ->where('constraint_schema', DB::getDatabaseName())
            ->where('table_name', $table)
            ->where('constraint_name', $constraintName)
            ->where('constraint_type', 'FOREIGN KEY')
            ->exists();
    }

    private function columnHasIndex(string $table, string $column): bool
    {
        return DB::table('information_schema.statistics')
            ->where('table_schema', DB::getDatabaseName())
            ->where('table_name', $table)
            ->where('column_name', $column)
            ->exists();
    }
};
