<?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
    {
        if (Schema::hasTable('webhook_deliveries')) {
            Schema::table('webhook_deliveries', function (Blueprint $table) {
                if (! Schema::hasColumn('webhook_deliveries', 'raw_payload')) $table->longText('raw_payload')->nullable()->after('payload');
                if (! Schema::hasColumn('webhook_deliveries', 'delivered_at')) $table->timestampTz('delivered_at')->nullable();
                if (! Schema::hasColumn('webhook_deliveries', 'exhausted_at')) $table->timestampTz('exhausted_at')->nullable();
            });
        }

        if (! Schema::hasTable('webhook_delivery_attempts')) {
            Schema::create('webhook_delivery_attempts', function (Blueprint $table) {
                $table->id();
                $table->foreignId('delivery_id')->constrained('webhook_deliveries')->cascadeOnDelete();
                $table->unsignedSmallInteger('attempt_number');
                $table->string('timestamp', 20);
                $table->string('signature', 80);
                $table->longText('request_body');
                $table->unsignedSmallInteger('response_code')->nullable();
                $table->longText('response_body')->nullable();
                $table->text('error')->nullable();
                $table->unsignedInteger('duration_ms')->nullable();
                $table->timestampTz('attempted_at')->nullable();
                $table->unique(['delivery_id', 'attempt_number'], 'webhook_attempt_delivery_number_unique');
            });
        }

        if (Schema::hasTable('payouts')) {
            Schema::table('payouts', function (Blueprint $table) {
                if (! Schema::hasColumn('payouts', 'two_factor_confirmed_at')) $table->timestampTz('two_factor_confirmed_at')->nullable();
                if (! Schema::hasColumn('payouts', 'screening_status')) $table->string('screening_status', 30)->nullable();
                if (! Schema::hasColumn('payouts', 'screening_result')) $table->json('screening_result')->nullable();
                if (! Schema::hasColumn('payouts', 'approved_at')) $table->timestampTz('approved_at')->nullable();
                if (! Schema::hasColumn('payouts', 'approved_by')) $table->unsignedBigInteger('approved_by')->nullable();
                if (! Schema::hasColumn('payouts', 'provider_idempotency_key')) $table->string('provider_idempotency_key')->nullable()->unique('payouts_provider_idem_unique');
                if (! Schema::hasColumn('payouts', 'broadcast_started_at')) $table->timestampTz('broadcast_started_at')->nullable();
                if (! Schema::hasColumn('payouts', 'broadcast_at')) $table->timestampTz('broadcast_at')->nullable();
                if (! Schema::hasColumn('payouts', 'completed_at')) $table->timestampTz('completed_at')->nullable();
                if (! Schema::hasColumn('payouts', 'failed_at')) $table->timestampTz('failed_at')->nullable();
                if (! Schema::hasColumn('payouts', 'failure_reason')) $table->text('failure_reason')->nullable();
                if (! Schema::hasColumn('payouts', 'reservation_ledger_transaction_id')) $table->foreignId('reservation_ledger_transaction_id')->nullable()->constrained('ledger_transactions');
                if (! Schema::hasColumn('payouts', 'settlement_ledger_transaction_id')) $table->foreignId('settlement_ledger_transaction_id')->nullable()->constrained('ledger_transactions');
                if (! Schema::hasColumn('payouts', 'release_ledger_transaction_id')) $table->foreignId('release_ledger_transaction_id')->nullable()->constrained('ledger_transactions');
            });
        }

        if (! Schema::hasTable('payout_address_allowlists')) {
            Schema::create('payout_address_allowlists', function (Blueprint $table) {
                $table->id();
                $table->foreignId('merchant_id')->constrained()->cascadeOnDelete();
                $table->foreignId('asset_id')->constrained();
                $table->string('environment', 16);
                $table->string('address');
                $table->string('label')->nullable();
                $table->string('status', 20)->default('cooling');
                $table->timestampTz('available_at')->nullable();
                $table->timestampTz('verified_at')->nullable();
                $table->timestampsTz();
                $table->unique(['merchant_id', 'asset_id', 'environment', 'address'], 'payout_allowlist_scope_address_unique');
            });
        }

        if (! Schema::hasTable('payout_kill_switches')) {
            Schema::create('payout_kill_switches', function (Blueprint $table) {
                $table->id();
                $table->string('scope_type', 20);
                $table->string('scope_id')->nullable();
                $table->string('environment', 16)->nullable();
                $table->boolean('enabled')->default(true);
                $table->text('reason');
                $table->unsignedBigInteger('activated_by')->nullable();
                $table->timestampTz('activated_at')->nullable();
                $table->timestampTz('deactivated_at')->nullable();
                $table->timestampsTz();
                $table->index(['scope_type', 'scope_id', 'environment', 'enabled'], 'payout_kill_switch_scope_idx');
            });
        }

        if (! Schema::hasTable('merchant_balance_snapshots')) {
            Schema::create('merchant_balance_snapshots', function (Blueprint $table) {
                $table->id();
                $table->foreignId('merchant_id')->constrained()->cascadeOnDelete();
                $table->foreignId('asset_id')->constrained();
                $table->string('environment', 16);
                $table->date('statement_date');
                $table->decimal('pending_atomic', 65, 0)->default(0);
                $table->decimal('available_atomic', 65, 0)->default(0);
                $table->decimal('reserved_atomic', 65, 0)->default(0);
                $table->timestampsTz();
                $table->unique(['merchant_id', 'asset_id', 'environment', 'statement_date'], 'merchant_balance_snapshot_unique');
            });
        }

        if (! Schema::hasTable('operations_alerts')) {
            Schema::create('operations_alerts', function (Blueprint $table) {
                $table->id();
                $table->string('severity', 20)->index();
                $table->string('code', 80)->index();
                $table->string('subject_type')->nullable();
                $table->string('subject_id')->nullable();
                $table->text('message');
                $table->json('context')->nullable();
                $table->timestampTz('acknowledged_at')->nullable();
                $table->timestampsTz();
            });
        }
    }

    public function down(): void
    {
        Schema::dropIfExists('operations_alerts');
        Schema::dropIfExists('merchant_balance_snapshots');
        Schema::dropIfExists('payout_kill_switches');
        Schema::dropIfExists('payout_address_allowlists');
        Schema::dropIfExists('webhook_delivery_attempts');
    }
};
