<?php

use App\Models\Dealer;
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('dealers') || !Schema::hasColumn('dealers', 'domain')) {
            return;
        }

        // Backfill null/empty domains to safe placeholders before enforcing constraints.
        Dealer::query()
            ->whereNull('domain')
            ->orWhere('domain', '')
            ->orderBy('id')
            ->chunkById(100, function ($dealers): void {
                /** @var \App\Models\Dealer $dealer */
                foreach ($dealers as $dealer) {
                    if ($dealer->is_default) {
                        $dealer->domain = 'megatheron.co.za';
                    } else {
                        $dealer->domain = sprintf('dealer-%d.example.invalid', $dealer->id);
                    }

                    $dealer->save();
                }
            });

        // Normalize all existing domains to lowercase/trimmed to avoid uniqueness surprises.
        Dealer::query()->orderBy('id')->chunkById(100, function ($dealers): void {
            /** @var \App\Models\Dealer $dealer */
            foreach ($dealers as $dealer) {
                $normalized = strtolower(trim((string) $dealer->domain));
                if ($normalized === '') {
                    $normalized = sprintf('dealer-%d.example.invalid', $dealer->id);
                }

                if ($dealer->domain !== $normalized) {
                    $dealer->domain = $normalized;
                    $dealer->save();
                }
            }
        });

        // Add unique index on domain if it does not exist yet (MySQL-safe, no Doctrine DBAL).
        if (! $this->indexExists('dealers', 'dealers_domain_unique')) {
            Schema::table('dealers', function (Blueprint $table): void {
                $table->unique('domain', 'dealers_domain_unique');
            });
        }

        // Enforce NOT NULL at database level where supported.
        $connection = config('database.default');
        $driver = config("database.connections.$connection.driver");

        if ($driver === 'mysql') {
            DB::statement('ALTER TABLE dealers MODIFY domain VARCHAR(255) NOT NULL');
        }
    }

    public function down(): void
    {
        if (!Schema::hasTable('dealers') || !Schema::hasColumn('dealers', 'domain')) {
            return;
        }

        // Drop unique index if present.
        if ($this->indexExists('dealers', 'dealers_domain_unique')) {
            Schema::table('dealers', function (Blueprint $table): void {
                $table->dropUnique('dealers_domain_unique');
            });
        }

        $connection = config('database.default');
        $driver = config("database.connections.$connection.driver");

        if ($driver === 'mysql') {
            DB::statement('ALTER TABLE dealers MODIFY domain VARCHAR(255) NULL');
        }
    }

    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();
    }
};

