<?php

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('provider_bank_accounts', function (Blueprint $table) {
            $table->id();

            $table->foreignId('provider_id')->constrained('providers')->cascadeOnDelete();
            $table->foreignId('bank_id')->nullable()->constrained('banks')->nullOnDelete();

            $table->string('bank_code', 3);
            $table->string('bank_name')->nullable();

            $table->string('holder_name');
            $table->string('holder_document', 20);
            $table->string('holder_type', 20)->default('individual');

            $table->string('type', 20);
            $table->string('branch_number', 4);
            $table->string('branch_check_digit', 2)->nullable();
            $table->string('account_number', 13);
            $table->string('account_check_digit', 2);

            $table->boolean('is_primary')->default(false);
            $table->boolean('is_active')->default(true);

            $table->timestamp('gateway_synced_at')->nullable();
            $table->string('gateway_sync_hash')->nullable();
            $table->unsignedInteger('gateway_sync_count')->default(0);
            $table->json('gateway_payload')->nullable();

            $table->timestamps();
            $table->softDeletes();

            $table->index('provider_id');
        });

        DB::statement('
            CREATE UNIQUE INDEX provider_bank_accounts_primary_unique
            ON provider_bank_accounts (provider_id)
            WHERE is_primary = true AND deleted_at IS NULL
        ');

        DB::statement('
            CREATE UNIQUE INDEX provider_bank_accounts_account_unique
            ON provider_bank_accounts (provider_id, bank_code, branch_number, account_number, account_check_digit)
            WHERE deleted_at IS NULL
        ');

        $this->backfillFromProviders();
    }

    public function down(): void
    {
        Schema::dropIfExists('provider_bank_accounts');
    }

    /**
     * Migra a conta unica atual (providers.recipient_default_bank_account) para a nova tabela,
     * marcando ela como principal. A coluna json continua sendo o padrão do que esta no Pagar.me.
     * Criado apenas para evitar que o pessoal do Diária precise cadastrar as contas novamente no momento do deploy.
     */
    private function backfillFromProviders(): void
    {
        $banks = DB::table('banks')->pluck('id', 'code');

        DB::table('providers')
            ->whereNotNull('recipient_default_bank_account')
            ->orderBy('id')
            ->chunkById(100, function ($providers) use ($banks) {
                foreach ($providers as $provider) {
                    $account = json_decode($provider->recipient_default_bank_account ?? '', true);

                    if (! is_array($account) || empty(data_get($account, 'bank')) || empty(data_get($account, 'account_number'))) {
                        continue;
                    }

                    $bankCode = str_pad((string) data_get($account, 'bank'), 3, '0', STR_PAD_LEFT);

                    $attributes = [
                        'holder_name'         => data_get($account, 'holder_name') ?: '',
                        'holder_document'     => data_get($account, 'holder_document') ?: '',
                        'holder_type'         => data_get($account, 'holder_type') ?: 'individual',
                        'type'                => data_get($account, 'type') ?: 'checking',
                        'branch_number'       => data_get($account, 'branch_number') ?: '',
                        'branch_check_digit'  => data_get($account, 'branch_check_digit'),
                        'account_number'      => data_get($account, 'account_number'),
                        'account_check_digit' => data_get($account, 'account_check_digit') ?: '',
                    ];

                    $gatewayHash = sha1(json_encode([
                        'holder_name'         => $attributes['holder_name'],
                        'holder_type'         => $attributes['holder_type'],
                        'holder_document'     => $attributes['holder_document'],
                        'bank'                => $bankCode,
                        'branch_number'       => $attributes['branch_number'],
                        'branch_check_digit'  => $attributes['branch_check_digit'],
                        'account_number'      => $attributes['account_number'],
                        'account_check_digit' => $attributes['account_check_digit'],
                        'type'                => $attributes['type'],
                    ]));

                    DB::table('provider_bank_accounts')->insert([
                        'provider_id'         => $provider->id,
                        'bank_id'             => $banks[$bankCode] ?? null,
                        'bank_code'           => $bankCode,
                        'bank_name'           => null,
                        ...$attributes,
                        'is_primary'          => true,
                        'is_active'           => true,
                        'gateway_synced_at'   => $provider->recipient_id ? now() : null,
                        'gateway_sync_hash'   => $provider->recipient_id ? $gatewayHash : null,
                        'gateway_sync_count'  => $provider->recipient_id ? 1 : 0,
                        'gateway_payload'     => null,
                        'created_at'          => now(),
                        'updated_at'          => now(),
                    ]);
                }
            });
    }
};
