<?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('payment_providers', function (Blueprint $table) {
            $table->id();
            $table->string('code', 50)->unique();
            $table->string('name');
            $table->string('scope', 20)->default('both');
            $table->json('capabilities')->nullable();
            $table->json('credential_schema')->nullable();
            $table->boolean('enabled')->default(true);
            $table->timestamps();
        });

        Schema::create('payment_gateway_accounts', function (Blueprint $table) {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->foreignId('payment_provider_id')->constrained()->restrictOnDelete();
            $table->foreignId('tenant_id')->nullable()->constrained()->cascadeOnDelete();
            $table->string('scope', 20);
            $table->string('name');
            $table->string('environment', 20)->default('sandbox');
            $table->text('credentials')->nullable();
            $table->text('webhook_secret')->nullable();
            $table->json('settings')->nullable();
            $table->boolean('enabled')->default(false);
            $table->boolean('is_default')->default(false);
            $table->string('last_health_status', 30)->nullable();
            $table->text('last_health_message')->nullable();
            $table->timestamp('last_health_check_at')->nullable();
            $table->timestamps();
            $table->index(['scope', 'tenant_id', 'enabled']);
        });

        Schema::create('tenant_payment_settings', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->unique()->constrained()->cascadeOnDelete();
            $table->string('payment_mode', 30)->default('disabled');
            $table->foreignId('tenant_gateway_account_id')->nullable()->constrained('payment_gateway_accounts')->nullOnDelete();
            $table->foreignId('platform_gateway_account_id')->nullable()->constrained('payment_gateway_accounts')->nullOnDelete();
            $table->string('fee_bearer', 20)->default('customer');
            $table->unsignedInteger('default_expiry_minutes')->default(1440);
            $table->json('enabled_methods')->nullable();
            $table->timestamps();
        });

        Schema::create('payment_transactions', function (Blueprint $table) {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->string('transaction_number')->unique();
            $table->foreignId('tenant_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('customer_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('invoice_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('payment_gateway_account_id')->nullable()->constrained()->nullOnDelete();
            $table->string('purpose', 30);
            $table->string('gateway_scope', 20);
            $table->string('provider_code', 50);
            $table->string('provider_reference')->nullable()->index();
            $table->string('method', 50)->nullable();
            $table->string('currency', 3)->default('IDR');
            $table->decimal('amount', 18, 2);
            $table->decimal('provider_fee', 18, 2)->default(0);
            $table->decimal('platform_fee', 18, 2)->default(0);
            $table->decimal('total_amount', 18, 2);
            $table->string('status', 30)->default('created');
            $table->string('provider_status', 50)->nullable();
            $table->string('idempotency_key')->unique();
            $table->text('checkout_url')->nullable();
            $table->text('qr_content')->nullable();
            $table->timestamp('expires_at')->nullable();
            $table->timestamp('paid_at')->nullable();
            $table->timestamp('failed_at')->nullable();
            $table->json('metadata')->nullable();
            $table->timestamps();
            $table->index(['tenant_id', 'status', 'created_at']);
            $table->index(['user_id', 'purpose', 'status']);
            $table->index(['invoice_id', 'status']);
        });

        Schema::create('payment_attempts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('payment_transaction_id')->constrained()->cascadeOnDelete();
            $table->unsignedSmallInteger('attempt_number');
            $table->string('action', 30);
            $table->string('status', 30);
            $table->json('request_payload')->nullable();
            $table->json('response_payload')->nullable();
            $table->string('error_code')->nullable();
            $table->text('error_message')->nullable();
            $table->unsignedInteger('duration_ms')->nullable();
            $table->timestamps();
            $table->unique(['payment_transaction_id', 'attempt_number', 'action'], 'payment_attempt_unique');
        });

        Schema::create('payment_webhook_logs', function (Blueprint $table) {
            $table->id();
            $table->foreignId('payment_gateway_account_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('payment_transaction_id')->nullable()->constrained()->nullOnDelete();
            $table->string('provider_code', 50);
            $table->string('provider_event_id')->nullable();
            $table->boolean('signature_valid')->default(false);
            $table->json('headers')->nullable();
            $table->json('payload');
            $table->string('status', 30)->default('received');
            $table->text('error_message')->nullable();
            $table->timestamp('processed_at')->nullable();
            $table->timestamps();
            $table->index(['provider_code', 'status', 'created_at']);
            $table->unique(['payment_gateway_account_id', 'provider_event_id']);
        });

        Schema::create('wallets', function (Blueprint $table) {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->nullableMorphs('owner');
            $table->string('wallet_type', 30);
            $table->string('currency', 3)->default('IDR');
            $table->decimal('available_balance', 18, 2)->default(0);
            $table->decimal('pending_balance', 18, 2)->default(0);
            $table->decimal('locked_balance', 18, 2)->default(0);
            $table->string('status', 20)->default('active');
            $table->unsignedBigInteger('version')->default(0);
            $table->timestamps();
            $table->unique(['owner_type', 'owner_id', 'wallet_type', 'currency'], 'wallet_owner_type_unique');
        });

        Schema::create('wallet_transactions', function (Blueprint $table) {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->string('transaction_number')->unique();
            $table->string('type', 30);
            $table->string('status', 20)->default('pending');
            $table->foreignId('payment_transaction_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('initiated_by')->nullable()->constrained('users')->nullOnDelete();
            $table->decimal('amount', 18, 2);
            $table->decimal('fee', 18, 2)->default(0);
            $table->string('currency', 3)->default('IDR');
            $table->string('idempotency_key')->unique();
            $table->text('description')->nullable();
            $table->json('metadata')->nullable();
            $table->timestamp('completed_at')->nullable();
            $table->timestamps();
            $table->index(['type', 'status', 'created_at']);
        });

        Schema::create('wallet_ledger_entries', function (Blueprint $table) {
            $table->id();
            $table->foreignId('wallet_id')->constrained()->restrictOnDelete();
            $table->foreignId('wallet_transaction_id')->constrained()->restrictOnDelete();
            $table->string('entry_type', 10);
            $table->string('balance_bucket', 20)->default('available');
            $table->decimal('amount', 18, 2);
            $table->decimal('balance_before', 18, 2);
            $table->decimal('balance_after', 18, 2);
            $table->text('description')->nullable();
            $table->timestamps();
            $table->unique(['wallet_id', 'wallet_transaction_id', 'entry_type', 'balance_bucket'], 'wallet_ledger_unique');
            $table->index(['wallet_id', 'created_at']);
        });

        Schema::create('wallet_withdrawals', function (Blueprint $table) {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->foreignId('wallet_id')->constrained()->restrictOnDelete();
            $table->foreignId('wallet_transaction_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('requested_by')->nullable()->constrained('users')->nullOnDelete();
            $table->foreignId('approved_by')->nullable()->constrained('users')->nullOnDelete();
            $table->decimal('amount', 18, 2);
            $table->decimal('fee', 18, 2)->default(0);
            $table->string('bank_code', 30);
            $table->string('account_number');
            $table->string('account_name');
            $table->string('status', 30)->default('pending_approval');
            $table->string('provider_reference')->nullable();
            $table->text('rejection_reason')->nullable();
            $table->timestamp('processed_at')->nullable();
            $table->timestamps();
            $table->index(['wallet_id', 'status', 'created_at']);
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('wallet_withdrawals');
        Schema::dropIfExists('wallet_ledger_entries');
        Schema::dropIfExists('wallet_transactions');
        Schema::dropIfExists('wallets');
        Schema::dropIfExists('payment_webhook_logs');
        Schema::dropIfExists('payment_attempts');
        Schema::dropIfExists('payment_transactions');
        Schema::dropIfExists('tenant_payment_settings');
        Schema::dropIfExists('payment_gateway_accounts');
        Schema::dropIfExists('payment_providers');
    }
};
