<?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
    {
        $this->ensureOrderExchangesTable();
        $this->ensureOrderExchangeItemsTable();
    }

    public function down(): void
    {
        // Intentionally non-destructive for live data safety.
    }

    private function ensureOrderExchangesTable(): void
    {
        if (! Schema::hasTable('order_exchanges')) {
            Schema::create('order_exchanges', function (Blueprint $table) {
                $table->id();
                $table->string('exchange_no', 80)->nullable()->unique();
                $table->string('idempotency_key', 120)->nullable()->unique();
                $table->unsignedBigInteger('order_id')->nullable()->index();
                $table->unsignedBigInteger('user_id')->nullable()->index();
                $table->decimal('returned_amount', 24, 8)->default(0);
                $table->decimal('replacement_amount', 24, 8)->default(0);
                $table->decimal('difference_amount', 24, 8)->default(0);
                $table->boolean('affects_collectable')->default(true);
                $table->string('exchange_status', 30)->default('posted')->index();
                $table->timestamp('exchanged_at')->nullable()->index();
                $table->text('notes')->nullable();
                $table->unsignedBigInteger('voucher_id')->nullable()->index();
                $table->unsignedBigInteger('created_by_admin_id')->nullable()->index();
                $table->unsignedBigInteger('voided_by_admin_id')->nullable()->index();
                $table->timestamp('voided_at')->nullable();
                $table->timestamps();

                $table->index(['order_id', 'exchange_status']);
            });

            return;
        }

        $this->addColumn('order_exchanges', 'exchange_no', fn (Blueprint $table) => $table->string('exchange_no', 80)->nullable()->unique());
        $this->addColumn('order_exchanges', 'idempotency_key', fn (Blueprint $table) => $table->string('idempotency_key', 120)->nullable()->unique());
        $this->addColumn('order_exchanges', 'order_id', fn (Blueprint $table) => $table->unsignedBigInteger('order_id')->nullable()->index());
        $this->addColumn('order_exchanges', 'user_id', fn (Blueprint $table) => $table->unsignedBigInteger('user_id')->nullable()->index());
        $this->addColumn('order_exchanges', 'returned_amount', fn (Blueprint $table) => $table->decimal('returned_amount', 24, 8)->default(0));
        $this->addColumn('order_exchanges', 'replacement_amount', fn (Blueprint $table) => $table->decimal('replacement_amount', 24, 8)->default(0));
        $this->addColumn('order_exchanges', 'difference_amount', fn (Blueprint $table) => $table->decimal('difference_amount', 24, 8)->default(0));
        $this->addColumn('order_exchanges', 'affects_collectable', fn (Blueprint $table) => $table->boolean('affects_collectable')->default(true));
        $this->addColumn('order_exchanges', 'exchange_status', fn (Blueprint $table) => $table->string('exchange_status', 30)->default('posted')->index());
        $this->addColumn('order_exchanges', 'exchanged_at', fn (Blueprint $table) => $table->timestamp('exchanged_at')->nullable()->index());
        $this->addColumn('order_exchanges', 'notes', fn (Blueprint $table) => $table->text('notes')->nullable());
        $this->addColumn('order_exchanges', 'voucher_id', fn (Blueprint $table) => $table->unsignedBigInteger('voucher_id')->nullable()->index());
        $this->addColumn('order_exchanges', 'created_by_admin_id', fn (Blueprint $table) => $table->unsignedBigInteger('created_by_admin_id')->nullable()->index());
        $this->addColumn('order_exchanges', 'voided_by_admin_id', fn (Blueprint $table) => $table->unsignedBigInteger('voided_by_admin_id')->nullable()->index());
        $this->addColumn('order_exchanges', 'voided_at', fn (Blueprint $table) => $table->timestamp('voided_at')->nullable());
        $this->addColumn('order_exchanges', 'created_at', fn (Blueprint $table) => $table->timestamp('created_at')->nullable());
        $this->addColumn('order_exchanges', 'updated_at', fn (Blueprint $table) => $table->timestamp('updated_at')->nullable());
    }

    private function ensureOrderExchangeItemsTable(): void
    {
        if (! Schema::hasTable('order_exchange_items')) {
            Schema::create('order_exchange_items', function (Blueprint $table) {
                $table->id();
                $table->unsignedBigInteger('order_exchange_id')->index();
                $table->string('direction', 20)->index();
                $table->unsignedBigInteger('order_detail_id')->nullable()->index();
                $table->unsignedBigInteger('item_id')->nullable()->index();
                $table->string('item_name')->nullable();
                $table->text('variation')->nullable();
                $table->unsignedInteger('quantity')->default(0);
                $table->decimal('unit_price', 24, 8)->default(0);
                $table->decimal('line_total', 24, 8)->default(0);
                $table->timestamps();

                $table->index(['order_exchange_id', 'direction']);
            });

            return;
        }

        $this->addColumn('order_exchange_items', 'order_exchange_id', fn (Blueprint $table) => $table->unsignedBigInteger('order_exchange_id')->nullable()->index());
        $this->addColumn('order_exchange_items', 'direction', fn (Blueprint $table) => $table->string('direction', 20)->nullable()->index());
        $this->addColumn('order_exchange_items', 'order_detail_id', fn (Blueprint $table) => $table->unsignedBigInteger('order_detail_id')->nullable()->index());
        $this->addColumn('order_exchange_items', 'item_id', fn (Blueprint $table) => $table->unsignedBigInteger('item_id')->nullable()->index());
        $this->addColumn('order_exchange_items', 'item_name', fn (Blueprint $table) => $table->string('item_name')->nullable());
        $this->addColumn('order_exchange_items', 'variation', fn (Blueprint $table) => $table->text('variation')->nullable());
        $this->addColumn('order_exchange_items', 'quantity', fn (Blueprint $table) => $table->unsignedInteger('quantity')->default(0));
        $this->addColumn('order_exchange_items', 'unit_price', fn (Blueprint $table) => $table->decimal('unit_price', 24, 8)->default(0));
        $this->addColumn('order_exchange_items', 'line_total', fn (Blueprint $table) => $table->decimal('line_total', 24, 8)->default(0));
        $this->addColumn('order_exchange_items', 'created_at', fn (Blueprint $table) => $table->timestamp('created_at')->nullable());
        $this->addColumn('order_exchange_items', 'updated_at', fn (Blueprint $table) => $table->timestamp('updated_at')->nullable());
    }

    private function addColumn(string $table, string $column, callable $definition): void
    {
        if (Schema::hasColumn($table, $column)) {
            return;
        }

        Schema::table($table, function (Blueprint $table) use ($definition) {
            $definition($table);
        });
    }
};
