<?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::create('order_receipts', function (Blueprint $table) {
            $table->id();
            $table->string('voucher_no', 60)->nullable()->unique();
            $table->uuid('idempotency_key')->unique();
            $table->foreignId('order_id')->constrained()->cascadeOnDelete();
            $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();
            $table->decimal('amount', 24, 3);
            $table->string('payment_method', 100);
            $table->string('transaction_ref', 120)->nullable();
            $table->string('account_type', 80)->default('customer_advance_liability');
            $table->string('receipt_status', 30)->default('posted');
            $table->timestamp('received_at');
            $table->text('notes')->nullable();
            $table->foreignId('created_by_admin_id')->nullable()->constrained('admins')->nullOnDelete();
            $table->foreignId('voided_by_admin_id')->nullable()->constrained('admins')->nullOnDelete();
            $table->timestamp('voided_at')->nullable();
            $table->timestamps();

            $table->unique(['order_id', 'transaction_ref'], 'order_receipts_order_transaction_unique');
            $table->index(['order_id', 'receipt_status']);
        });

        Schema::table('order_payments', function (Blueprint $table) {
            $table->foreignId('order_receipt_id')
                ->nullable()
                ->after('order_id')
                ->unique()
                ->constrained('order_receipts')
                ->nullOnDelete();
        });

        Schema::create('order_exchanges', function (Blueprint $table) {
            $table->id();
            $table->string('exchange_no', 60)->nullable()->unique();
            $table->uuid('idempotency_key')->unique();
            $table->foreignId('order_id')->constrained()->cascadeOnDelete();
            $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();
            $table->decimal('returned_amount', 24, 3)->default(0);
            $table->decimal('replacement_amount', 24, 3)->default(0);
            $table->decimal('difference_amount', 24, 3)->default(0);
            $table->boolean('affects_collectable')->default(true);
            $table->string('exchange_status', 30)->default('posted');
            $table->timestamp('exchanged_at');
            $table->text('notes')->nullable();
            $table->foreignId('created_by_admin_id')->nullable()->constrained('admins')->nullOnDelete();
            $table->foreignId('voided_by_admin_id')->nullable()->constrained('admins')->nullOnDelete();
            $table->timestamp('voided_at')->nullable();
            $table->timestamps();

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

        Schema::create('order_exchange_items', function (Blueprint $table) {
            $table->id();
            $table->foreignId('order_exchange_id')->constrained('order_exchanges')->cascadeOnDelete();
            $table->string('direction', 20);
            $table->foreignId('order_detail_id')->nullable()->constrained('order_details')->nullOnDelete();
            $table->foreignId('item_id')->nullable()->constrained('items')->nullOnDelete();
            $table->string('item_name');
            $table->text('variation')->nullable();
            $table->unsignedInteger('quantity');
            $table->decimal('unit_price', 24, 3);
            $table->decimal('line_total', 24, 3);
            $table->timestamps();

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

    public function down(): void
    {
        Schema::dropIfExists('order_exchange_items');
        Schema::dropIfExists('order_exchanges');

        if (Schema::hasColumn('order_payments', 'order_receipt_id')) {
            Schema::table('order_payments', function (Blueprint $table) {
                $table->dropConstrainedForeignId('order_receipt_id');
            });
        }

        Schema::dropIfExists('order_receipts');
    }
};
