<?php

declare(strict_types=1);

use App\Models\Credit;
use App\Services\Payments\PaymentMaterializer;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;

/**
 * Limpieza de datos: reversals corruptos.
 *
 * La versión anterior de PaymentReverser clonaba los pivotes del pago original
 * al pago de reversión (voided=0) con `applied_amount` POSITIVO. Como
 * PaymentMaterializer y PaymentDistributor suman pivotes filtrando solo
 * `payments.voided=0`, esos pivotes del reversal se contaban como dinero
 * aplicado → doble conteo del saldo (cuotas re-infladas, pagos posteriores
 * desviados a extra_amount).
 *
 * Esta migración desprende los pivotes de todo pago `reversal` y re-materializa
 * los créditos afectados para que `amount_paid`/`applied_amount` reflejen solo
 * los pagos reales. Idempotente: si no hay pivotes en reversals, no hace nada.
 */
return new class extends Migration
{
    public function up(): void
    {
        $reversalIds = DB::table('payments as p')
            ->join('payment_installment as pi', 'pi.payment_id', '=', 'p.id')
            ->where('p.payment_method', 'reversal')
            ->distinct()
            ->pluck('p.id');

        if ($reversalIds->isEmpty()) {
            return;
        }

        $creditIds = DB::table('payments')
            ->whereIn('id', $reversalIds)
            ->whereNotNull('credit_id')
            ->distinct()
            ->pluck('credit_id');

        DB::transaction(function () use ($reversalIds, $creditIds) {
            // 1) Desprender los pivotes de los reversals (la causa del doble conteo).
            DB::table('payment_installment')
                ->whereIn('payment_id', $reversalIds)
                ->delete();

            // 2) Re-materializar cada crédito afectado: recalcula amount_paid de las
            //    cuotas y applied_amount de los pagos desde los pivotes válidos.
            $materializer = app(PaymentMaterializer::class);

            foreach ($creditIds as $creditId) {
                $credit = Credit::withoutGlobalScopes()->find($creditId);

                if ($credit) {
                    $materializer->materializeCredit($credit);
                }
            }
        });
    }

    public function down(): void
    {
        // No reversible: no recreamos pivotes corruptos a propósito.
    }
};
