<?php

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

return new class extends Migration
{
    private const INDEX = 'uk_credit_ledger_ref_reason';

    public function up(): void
    {
        if (! Schema::hasTable('credit_ledger')) {
            return;
        }

        if (! Schema::hasColumn('credit_ledger', 'settlement_version')) {
            Schema::table('credit_ledger', function (Blueprint $table): void {
                $table->unsignedInteger('settlement_version')->default(0)->after('ref_id');
            });
        }

        $this->dropIndex();
        $this->createIndex(includeSettlementVersion: true);
    }

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

        $this->dropIndex();
        $this->createIndex(includeSettlementVersion: false);

        if (Schema::hasColumn('credit_ledger', 'settlement_version')) {
            Schema::table('credit_ledger', function (Blueprint $table): void {
                $table->dropColumn('settlement_version');
            });
        }
    }

    private function dropIndex(): void
    {
        if (! Schema::hasIndex('credit_ledger', self::INDEX)) {
            return;
        }

        $driver = Schema::getConnection()->getDriverName();
        if (in_array($driver, ['pgsql', 'sqlite'], true)) {
            DB::statement('DROP INDEX IF EXISTS '.self::INDEX);

            return;
        }

        Schema::table('credit_ledger', function (Blueprint $table): void {
            $table->dropUnique(self::INDEX);
        });
    }

    private function createIndex(bool $includeSettlementVersion): void
    {
        $columns = $includeSettlementVersion
            ? 'ref_type, ref_id, reason, settlement_version'
            : 'ref_type, ref_id, reason';
        $driver = Schema::getConnection()->getDriverName();

        if (in_array($driver, ['pgsql', 'sqlite'], true)) {
            DB::statement(
                'CREATE UNIQUE INDEX '.self::INDEX.' ON credit_ledger ('.$columns.') WHERE ref_id IS NOT NULL',
            );

            return;
        }

        Schema::table('credit_ledger', function (Blueprint $table) use ($includeSettlementVersion): void {
            $columns = ['ref_type', 'ref_id', 'reason'];
            if ($includeSettlementVersion) {
                $columns[] = 'settlement_version';
            }
            $table->unique($columns, self::INDEX);
        });
    }
};
