<?php

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('loan_repayment_schedules', function (Blueprint $table): void {
            if (! Schema::hasColumn('loan_repayment_schedules', 'schedule_version')) {
                $table->unsignedInteger('schedule_version')->default(1)->after('installment_no');
            }

            if (! Schema::hasColumn('loan_repayment_schedules', 'is_current')) {
                $table->boolean('is_current')->default(true)->after('schedule_version')->index();
            }

            if (! Schema::hasColumn('loan_repayment_schedules', 'archived_at')) {
                $table->timestamp('archived_at')->nullable()->after('is_current');
            }

            if (! Schema::hasColumn('loan_repayment_schedules', 'rescheduled_by')) {
                $table->foreignId('rescheduled_by')->nullable()->after('archived_at')->constrained('users')->nullOnDelete();
            }

            if (! Schema::hasColumn('loan_repayment_schedules', 'reschedule_note')) {
                $table->text('reschedule_note')->nullable()->after('rescheduled_by');
            }
        });

        if (! $this->indexExists('loan_repayment_schedules', 'loan_schedule_version_installment_unique')) {
            Schema::table('loan_repayment_schedules', function (Blueprint $table): void {
                $table->unique(['loan_id', 'schedule_version', 'installment_no'], 'loan_schedule_version_installment_unique');
            });
        }

        if ($this->indexExists('loan_repayment_schedules', 'loan_repayment_schedules_loan_id_installment_no_unique')) {
            Schema::table('loan_repayment_schedules', function (Blueprint $table): void {
                $table->dropUnique('loan_repayment_schedules_loan_id_installment_no_unique');
            });
        }

        if (! $this->indexExists('loan_repayment_schedules', 'loan_schedule_current_status_due_index')) {
            Schema::table('loan_repayment_schedules', function (Blueprint $table): void {
                $table->index(['tenant_id', 'is_current', 'status', 'due_date'], 'loan_schedule_current_status_due_index');
            });
        }
    }

    public function down(): void
    {
        if ($this->indexExists('loan_repayment_schedules', 'loan_schedule_current_status_due_index')) {
            Schema::table('loan_repayment_schedules', function (Blueprint $table): void {
                $table->dropIndex('loan_schedule_current_status_due_index');
            });
        }

        if (! $this->indexExists('loan_repayment_schedules', 'loan_repayment_schedules_loan_id_installment_no_unique')) {
            Schema::table('loan_repayment_schedules', function (Blueprint $table): void {
                $table->unique(['loan_id', 'installment_no']);
            });
        }

        if ($this->indexExists('loan_repayment_schedules', 'loan_schedule_version_installment_unique')) {
            Schema::table('loan_repayment_schedules', function (Blueprint $table): void {
                $table->dropUnique('loan_schedule_version_installment_unique');
            });
        }

        Schema::table('loan_repayment_schedules', function (Blueprint $table): void {
            foreach (['reschedule_note', 'rescheduled_by', 'archived_at', 'is_current', 'schedule_version'] as $column) {
                if (Schema::hasColumn('loan_repayment_schedules', $column)) {
                    if ($column === 'rescheduled_by') {
                        $table->dropConstrainedForeignId($column);
                    } else {
                        $table->dropColumn($column);
                    }
                }
            }
        });
    }

    private function indexExists(string $table, string $name): bool
    {
        try {
            return collect(Schema::getIndexes($table))
                ->contains(fn (array $index): bool => ($index['name'] ?? null) === $name);
        } catch (Throwable) {
            return false;
        }
    }
};
