<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('installer_states', function (Blueprint $table) {
            $table->id();
            $table->string('step')->unique();
            $table->jsonOrLongText('payload')->nullable();
            $table->timestamp('completed_at')->nullable();
            $table->timestamps();
        });

        Schema::create('ranks', function (Blueprint $table) {
            $table->id();
            $table->string('code')->unique();
            $table->string('name');
            $table->unsignedInteger('priority')->default(1)->index();
            $table->unsignedInteger('required_active_directs')->default(0);
            $table->decimal('required_weak_leg_bv', 14, 2)->default(0);
            $table->decimal('required_team_turnover', 14, 2)->default(0);
            $table->decimal('reward_amount', 14, 2)->default(0);
            $table->boolean('is_active')->default(true)->index();
            $table->timestamps();
        });

        Schema::create('user_kyc', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('pan_number', 25)->nullable()->index();
            $table->string('aadhaar_number', 20)->nullable();
            $table->string('bank_account_number', 50)->nullable()->index();
            $table->string('ifsc_code', 20)->nullable();
            $table->string('bank_name')->nullable();
            $table->string('account_holder_name')->nullable();
            $table->string('pan_document_path')->nullable();
            $table->string('cancelled_cheque_path')->nullable();
            $table->enum('status', ['pending', 'approved', 'rejected'])->default('pending')->index();
            $table->foreignId('reviewed_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamp('reviewed_at')->nullable();
            $table->text('rejection_reason')->nullable();
            $table->timestamps();
        });

        Schema::create('binary_ledger', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->foreignId('source_user_id')->nullable()->constrained('users')->nullOnDelete();
            $table->foreignId('beneficiary_user_id')->constrained('users')->cascadeOnDelete();
            $table->enum('leg', ['left', 'right'])->index();
            $table->enum('ledger_type', ['joining', 'repurchase', 'reversal_joining', 'reversal_repurchase'])->index();
            $table->enum('direction', ['credit', 'debit'])->default('credit');
            $table->decimal('units', 14, 4)->default(0);
            $table->string('reference_type', 50)->nullable();
            $table->unsignedBigInteger('reference_id')->nullable();
            $table->jsonOrLongText('meta')->nullable();
            $table->timestamp('posted_at')->useCurrent()->index();
            $table->timestamps();
            $table->index(['beneficiary_user_id', 'ledger_type', 'leg']);
            $table->index(['reference_type', 'reference_id']);
        });

        Schema::create('user_binary_carry', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->unique()->constrained()->cascadeOnDelete();
            $table->decimal('joining_left', 14, 4)->default(0);
            $table->decimal('joining_right', 14, 4)->default(0);
            $table->decimal('repurchase_left', 14, 4)->default(0);
            $table->decimal('repurchase_right', 14, 4)->default(0);
            $table->timestamp('last_processed_at')->nullable();
            $table->timestamps();
        });

        Schema::create('joining_pair_income', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->date('run_date')->index();
            $table->decimal('left_units', 14, 4)->default(0);
            $table->decimal('right_units', 14, 4)->default(0);
            $table->decimal('matched_pairs', 14, 4)->default(0);
            $table->decimal('pair_value', 14, 2)->default(0);
            $table->decimal('gross_income', 14, 2)->default(0);
            $table->decimal('capping_deduction', 14, 2)->default(0);
            $table->decimal('net_income', 14, 2)->default(0);
            $table->enum('status', ['credited', 'held', 'reversed'])->default('credited')->index();
            $table->string('reference', 100)->nullable();
            $table->timestamps();
            $table->index(['user_id', 'run_date']);
        });

        Schema::create('binary_matching_income', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->date('run_date')->index();
            $table->decimal('left_bv', 14, 4)->default(0);
            $table->decimal('right_bv', 14, 4)->default(0);
            $table->decimal('matched_bv', 14, 4)->default(0);
            $table->decimal('rate', 14, 4)->default(0);
            $table->decimal('gross_income', 14, 2)->default(0);
            $table->decimal('capping_deduction', 14, 2)->default(0);
            $table->decimal('net_income', 14, 2)->default(0);
            $table->enum('status', ['credited', 'held', 'reversed'])->default('credited')->index();
            $table->string('reference', 100)->nullable();
            $table->timestamps();
            $table->index(['user_id', 'run_date']);
        });

        Schema::create('wallet_balances', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->unique()->constrained()->cascadeOnDelete();
            $table->decimal('income_balance', 14, 2)->default(0);
            $table->decimal('repurchase_balance', 14, 2)->default(0);
            $table->decimal('withdrawable_balance', 14, 2)->default(0);
            $table->decimal('hold_balance', 14, 2)->default(0);
            $table->decimal('locked_withdrawal_balance', 14, 2)->default(0);
            $table->timestamps();
        });

        Schema::create('wallet_transactions', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->enum('wallet_type', ['income', 'repurchase', 'withdrawable', 'hold', 'locked'])->index();
            $table->enum('direction', ['credit', 'debit'])->index();
            $table->decimal('amount', 14, 2);
            $table->decimal('opening_balance', 14, 2);
            $table->decimal('closing_balance', 14, 2);
            $table->string('source_type', 100)->nullable();
            $table->unsignedBigInteger('source_id')->nullable();
            $table->string('reference', 100)->nullable();
            $table->text('narration')->nullable();
            $table->jsonOrLongText('meta')->nullable();
            $table->timestamp('transacted_at')->useCurrent()->index();
            $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamps();
            $table->index(['user_id', 'wallet_type', 'transacted_at']);
        });

        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('sku')->unique();
            $table->string('name');
            $table->string('slug')->nullable()->unique();
            $table->text('description')->nullable();
            $table->decimal('dp_price', 12, 2);
            $table->decimal('mrp', 12, 2)->nullable();
            $table->decimal('bv', 12, 2)->default(0);
            $table->decimal('gst_percent', 5, 2)->default(0);
            $table->integer('stock')->default(0);
            $table->boolean('is_active')->default(true)->index();
            $table->string('image_path')->nullable();
            $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamps();
        });

        Schema::create('franchises', function (Blueprint $table) {
            $table->id();
            $table->string('code')->unique();
            $table->string('name');
            $table->string('owner_name')->nullable();
            $table->string('mobile', 20)->nullable();
            $table->string('email')->nullable();
            $table->text('address')->nullable();
            $table->string('city')->nullable();
            $table->string('state')->nullable();
            $table->string('pincode', 12)->nullable();
            $table->string('gst_number', 20)->nullable();
            $table->decimal('wallet_balance', 14, 2)->default(0);
            $table->boolean('is_active')->default(true)->index();
            $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamps();
        });

        Schema::create('orders', function (Blueprint $table) {
            $table->id();
            $table->string('order_number')->unique();
            $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();
            $table->foreignId('franchise_id')->nullable()->constrained('franchises')->nullOnDelete();
            $table->enum('order_type', ['user', 'franchise'])->default('user')->index();
            $table->enum('status', ['pending_payment', 'paid', 'approved', 'dispatched', 'delivered', 'cancelled', 'refunded'])
                ->default('pending_payment')
                ->index();
            $table->enum('payment_status', ['unpaid', 'paid', 'failed', 'refunded'])->default('unpaid')->index();
            $table->decimal('subtotal', 14, 2)->default(0);
            $table->decimal('discount', 14, 2)->default(0);
            $table->decimal('tax', 14, 2)->default(0);
            $table->decimal('shipping', 14, 2)->default(0);
            $table->decimal('total', 14, 2)->default(0);
            $table->decimal('total_bv', 14, 4)->default(0);
            $table->string('payment_method', 50)->nullable();
            $table->text('notes')->nullable();
            $table->foreignId('approved_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamp('approved_at')->nullable();
            $table->timestamp('cancelled_at')->nullable();
            $table->timestamps();
            $table->index(['user_id', 'status']);
        });

        Schema::create('order_items', function (Blueprint $table) {
            $table->id();
            $table->foreignId('order_id')->constrained('orders')->cascadeOnDelete();
            $table->foreignId('product_id')->nullable()->constrained('products')->nullOnDelete();
            $table->string('product_name');
            $table->string('sku');
            $table->unsignedInteger('quantity');
            $table->decimal('unit_price', 14, 2);
            $table->decimal('unit_bv', 14, 4)->default(0);
            $table->decimal('gst_percent', 5, 2)->default(0);
            $table->decimal('line_total', 14, 2);
            $table->decimal('line_bv', 14, 4)->default(0);
            $table->timestamps();
        });

        Schema::create('withdrawals', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
            $table->string('request_number')->unique();
            $table->decimal('amount', 14, 2);
            $table->decimal('tds_amount', 14, 2)->default(0);
            $table->decimal('charge_amount', 14, 2)->default(0);
            $table->decimal('net_amount', 14, 2)->default(0);
            $table->date('hold_until')->nullable();
            $table->enum('status', ['pending', 'processing', 'approved', 'rejected', 'failed', 'paid'])
                ->default('pending')
                ->index();
            $table->timestamp('requested_at')->useCurrent();
            $table->timestamp('processed_at')->nullable();
            $table->foreignId('processed_by')->nullable()->constrained('users')->nullOnDelete();
            $table->text('rejection_reason')->nullable();
            $table->timestamps();
            $table->index(['user_id', 'status']);
        });

        Schema::create('payment_transactions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();
            $table->foreignId('order_id')->nullable()->constrained('orders')->nullOnDelete();
            $table->string('gateway', 50);
            $table->string('gateway_transaction_id')->nullable()->index();
            $table->string('merchant_order_ref')->nullable()->index();
            $table->decimal('amount', 14, 2);
            $table->enum('payment_for', ['joining', 'wallet_recharge', 'order', 'other'])->default('other')->index();
            $table->enum('status', ['initiated', 'pending', 'success', 'failed', 'refunded'])->default('initiated')->index();
            $table->jsonOrLongText('request_payload')->nullable();
            $table->jsonOrLongText('response_payload')->nullable();
            $table->boolean('webhook_verified')->default(false)->index();
            $table->timestamp('verified_at')->nullable();
            $table->text('failed_reason')->nullable();
            $table->timestamps();
            $table->index(['gateway', 'status']);
        });

        Schema::create('payout_transactions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('withdrawal_id')->nullable()->constrained('withdrawals')->nullOnDelete();
            $table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
            $table->string('gateway', 50);
            $table->string('gateway_payout_id')->nullable()->index();
            $table->decimal('amount', 14, 2);
            $table->enum('status', ['initiated', 'processing', 'success', 'failed', 'retry'])->default('initiated')->index();
            $table->unsignedTinyInteger('attempts')->default(0);
            $table->timestamp('last_attempt_at')->nullable();
            $table->timestamp('processed_at')->nullable();
            $table->jsonOrLongText('response_payload')->nullable();
            $table->text('failure_reason')->nullable();
            $table->timestamps();
            $table->index(['user_id', 'status']);
        });

        Schema::create('upi_transactions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
            $table->foreignId('payment_transaction_id')->nullable()->constrained('payment_transactions')->nullOnDelete();
            $table->enum('purpose', ['joining', 'wallet_recharge', 'order'])->default('wallet_recharge')->index();
            $table->string('utr', 30)->unique();
            $table->decimal('amount', 14, 2);
            $table->string('bank_name')->nullable();
            $table->string('screenshot_path')->nullable();
            $table->string('remark')->nullable();
            $table->enum('verification_status', ['pending', 'verified', 'rejected', 'duplicate', 'locked'])
                ->default('pending')
                ->index();
            $table->unsignedTinyInteger('attempts')->default(0);
            $table->foreignId('verified_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamp('verified_at')->nullable();
            $table->string('ip_address', 45)->nullable();
            $table->string('device_fingerprint', 255)->nullable();
            $table->timestamps();
            $table->index(['user_id', 'verification_status']);
        });

        Schema::create('webhook_logs', function (Blueprint $table) {
            $table->id();
            $table->string('gateway', 50)->index();
            $table->string('event_type')->nullable();
            $table->string('signature')->nullable();
            $table->string('payload_hash', 64);
            $table->longText('payload');
            $table->jsonOrLongText('headers')->nullable();
            $table->enum('status', ['received', 'verified', 'ignored', 'failed'])->default('received')->index();
            $table->timestamp('processed_at')->nullable();
            $table->text('error_message')->nullable();
            $table->timestamps();
            $table->unique(['gateway', 'payload_hash']);
        });

        Schema::create('notification_templates', function (Blueprint $table) {
            $table->id();
            $table->string('code')->unique();
            $table->enum('channel', ['sms', 'email', 'push', 'whatsapp', 'in_app'])->index();
            $table->string('title')->nullable();
            $table->text('body');
            $table->jsonOrLongText('variables')->nullable();
            $table->boolean('is_active')->default(true)->index();
            $table->timestamps();
        });

        Schema::create('otp_verifications', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();
            $table->string('mobile', 20)->nullable()->index();
            $table->string('email')->nullable()->index();
            $table->string('purpose', 100)->index();
            $table->string('otp_hash');
            $table->timestamp('expires_at');
            $table->timestamp('verified_at')->nullable();
            $table->unsignedTinyInteger('attempt_count')->default(0);
            $table->enum('status', ['pending', 'verified', 'expired', 'blocked'])->default('pending')->index();
            $table->string('ip_address', 45)->nullable();
            $table->string('device_fingerprint', 255)->nullable();
            $table->timestamps();
        });

        Schema::create('franchise_transactions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('franchise_id')->constrained('franchises')->cascadeOnDelete();
            $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();
            $table->foreignId('order_id')->nullable()->constrained('orders')->nullOnDelete();
            $table->enum('transaction_type', ['stock_in', 'stock_out', 'sale', 'bv_transfer', 'commission_credit', 'commission_debit', 'adjustment'])
                ->index();
            $table->decimal('amount', 14, 2)->default(0);
            $table->decimal('bv', 14, 4)->default(0);
            $table->unsignedInteger('quantity')->nullable();
            $table->string('reference', 100)->nullable();
            $table->text('narration')->nullable();
            $table->timestamp('transacted_at')->useCurrent()->index();
            $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamps();
            $table->index(['franchise_id', 'transaction_type']);
        });

        Schema::create('admin_activity_logs', function (Blueprint $table) {
            $table->id();
            $table->foreignId('admin_user_id')->constrained('users')->cascadeOnDelete();
            $table->string('action');
            $table->string('subject_type')->nullable();
            $table->unsignedBigInteger('subject_id')->nullable();
            $table->string('ip_address', 45)->nullable();
            $table->text('user_agent')->nullable();
            $table->jsonOrLongText('meta')->nullable();
            $table->timestamp('created_at')->useCurrent()->index();
        });

        Schema::create('identity_usage_counters', function (Blueprint $table) {
            $table->id();
            $table->enum('identity_type', ['mobile', 'email', 'pan', 'bank_account'])->index();
            $table->string('identity_value', 191);
            $table->unsignedInteger('users_count')->default(0);
            $table->unsignedInteger('max_allowed')->nullable();
            $table->timestamp('last_checked_at')->nullable();
            $table->timestamps();
            $table->unique(['identity_type', 'identity_value']);
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('identity_usage_counters');
        Schema::dropIfExists('admin_activity_logs');
        Schema::dropIfExists('franchise_transactions');
        Schema::dropIfExists('otp_verifications');
        Schema::dropIfExists('notification_templates');
        Schema::dropIfExists('webhook_logs');
        Schema::dropIfExists('upi_transactions');
        Schema::dropIfExists('payout_transactions');
        Schema::dropIfExists('payment_transactions');
        Schema::dropIfExists('withdrawals');
        Schema::dropIfExists('order_items');
        Schema::dropIfExists('orders');
        Schema::dropIfExists('franchises');
        Schema::dropIfExists('products');
        Schema::dropIfExists('wallet_transactions');
        Schema::dropIfExists('wallet_balances');
        Schema::dropIfExists('binary_matching_income');
        Schema::dropIfExists('joining_pair_income');
        Schema::dropIfExists('user_binary_carry');
        Schema::dropIfExists('binary_ledger');
        Schema::dropIfExists('user_kyc');
        Schema::dropIfExists('ranks');
        Schema::dropIfExists('installer_states');
    }
};
