<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;

class TransferDetectionController extends Controller
{
    /**
     * Detecta possíveis transferências entre contas
     * Critérios: mesmo valor absoluto, datas próximas, tipos opostos (debit/credit), contas diferentes
     */
    public function index(Request $request): JsonResponse
    {
        $userId = $request->user()->id;
        $toleranceDays = min(max((int) $request->input('tolerance_days', 3), 1), 30); // 1-30 dias
        
        // Buscar todas as transações não deletadas do usuário
        $debits = DB::select("
            SELECT 
                t.id,
                t.description,
                t.planned_amount,
                t.planned_date,
                t.status,
                t.account_id,
                a.name as account_name
            FROM transactions t
            LEFT JOIN accounts a ON t.account_id = a.id
            WHERE t.user_id = ?
                AND t.deleted_at IS NULL
                AND t.is_split_child = 0
                AND t.type = 'debit'
                AND t.planned_amount > 0
                AND (t.is_transfer = 0 OR t.is_transfer IS NULL)
            ORDER BY t.planned_date DESC, t.planned_amount DESC
        ", [$userId]);

        $credits = DB::select("
            SELECT 
                t.id,
                t.description,
                t.planned_amount,
                t.planned_date,
                t.status,
                t.account_id,
                a.name as account_name
            FROM transactions t
            LEFT JOIN accounts a ON t.account_id = a.id
            WHERE t.user_id = ?
                AND t.deleted_at IS NULL
                AND t.is_split_child = 0
                AND t.type = 'credit'
                AND t.planned_amount > 0
                AND (t.is_transfer = 0 OR t.is_transfer IS NULL)
            ORDER BY t.planned_date DESC, t.planned_amount DESC
        ", [$userId]);

        $potentialTransfers = [];
        $usedDebitIds = [];
        $usedCreditIds = [];

        foreach ($debits as $debit) {
            if (in_array($debit->id, $usedDebitIds)) continue;

            foreach ($credits as $credit) {
                if (in_array($credit->id, $usedCreditIds)) continue;
                
                // Deve ser em contas DIFERENTES
                if ($debit->account_id === $credit->account_id) continue;

                // Mesmo valor
                if (abs((float)$debit->planned_amount - (float)$credit->planned_amount) > 0.01) continue;

                // Data dentro da tolerância
                $debitDate = strtotime($debit->planned_date);
                $creditDate = strtotime($credit->planned_date);
                $daysDiff = abs(($creditDate - $debitDate) / 86400);
                
                if ($daysDiff > $toleranceDays) continue;

                // Calcular confiança
                $confidence = $this->calculateConfidence($debit, $credit, $daysDiff);

                $potentialTransfers[] = [
                    'debit' => [
                        'id' => $debit->id,
                        'description' => $debit->description,
                        'amount' => $debit->planned_amount,
                        'date' => $debit->planned_date,
                        'status' => $debit->status,
                        'account_id' => $debit->account_id,
                        'account_name' => $debit->account_name,
                    ],
                    'credit' => [
                        'id' => $credit->id,
                        'description' => $credit->description,
                        'amount' => $credit->planned_amount,
                        'date' => $credit->planned_date,
                        'status' => $credit->status,
                        'account_id' => $credit->account_id,
                        'account_name' => $credit->account_name,
                    ],
                    'amount' => $debit->planned_amount,
                    'days_diff' => (int)$daysDiff,
                    'confidence' => $confidence,
                ];

                $usedDebitIds[] = $debit->id;
                $usedCreditIds[] = $credit->id;
                break; // Encontrou match, passar para próximo débito
            }
        }

        // Ordenar por confiança (maior primeiro)
        usort($potentialTransfers, function($a, $b) {
            return $b['confidence']['percentage'] <=> $a['confidence']['percentage'];
        });

        return response()->json([
            'data' => $potentialTransfers,
            'total' => count($potentialTransfers),
            'tolerance_days' => $toleranceDays,
        ]);
    }

    /**
     * Calcula nível de confiança de que é uma transferência
     */
    private function calculateConfidence($debit, $credit, $daysDiff): array
    {
        $confidence = 50; // Base: mesmo valor em contas diferentes
        $reasons = ['same_amount_different_accounts'];

        // Mesma data = +30%
        if ($daysDiff == 0) {
            $confidence += 30;
            $reasons[] = 'same_date';
        } elseif ($daysDiff == 1) {
            $confidence += 20;
            $reasons[] = 'next_day';
        } elseif ($daysDiff <= 3) {
            $confidence += 10;
            $reasons[] = 'within_3_days';
        }

        // Descrição contém palavras-chave de transferência
        $transferKeywords = ['transfer', 'transferencia', 'transferência', 'traspaso', 'envio', 'recebido', 'recibido', 'deposito', 'depósito'];
        $debitDesc = strtolower($debit->description ?? '');
        $creditDesc = strtolower($credit->description ?? '');
        
        foreach ($transferKeywords as $keyword) {
            if (strpos($debitDesc, $keyword) !== false || strpos($creditDesc, $keyword) !== false) {
                $confidence += 15;
                $reasons[] = 'transfer_keyword';
                break;
            }
        }

        // Mesmo status = +5%
        if ($debit->status === $credit->status) {
            $confidence += 5;
            $reasons[] = 'same_status';
        }

        $confidence = min(100, $confidence);

        if ($confidence >= 90) {
            $level = 'high';
        } elseif ($confidence >= 70) {
            $level = 'medium';
        } else {
            $level = 'low';
        }

        return [
            'percentage' => $confidence,
            'level' => $level,
            'reasons' => $reasons,
        ];
    }

    /**
     * Busca possíveis pares para uma transação específica
     * Para converter uma transação em transferência
     */
    public function findPairs(Request $request, int $transactionId): JsonResponse
    {
        $userId = $request->user()->id;
        $toleranceDays = $request->input('tolerance_days', 7); // Tolerância maior para busca manual

        // Buscar a transação origem
        $transaction = Transaction::where('id', $transactionId)
            ->where('user_id', $userId)
            ->whereNull('deleted_at')
            ->first();

        if (!$transaction) {
            return response()->json(['error' => 'Transaction not found'], 404);
        }

        // Não pode ser uma transferência já vinculada
        if ($transaction->is_transfer) {
            return response()->json(['error' => 'Transaction is already a transfer'], 400);
        }

        // Determinar o tipo oposto
        $oppositeType = $transaction->type === 'debit' ? 'credit' : 'debit';

        // Buscar transações candidatas (tipo oposto, mesmo valor, contas diferentes, datas próximas)
        $candidates = DB::select("
            SELECT 
                t.id,
                t.description,
                t.planned_amount,
                t.amount,
                t.planned_date,
                t.effective_date,
                t.status,
                t.type,
                t.account_id,
                a.name as account_name
            FROM transactions t
            LEFT JOIN accounts a ON t.account_id = a.id
            WHERE t.user_id = ?
                AND t.deleted_at IS NULL
                AND t.is_split_child = 0
                AND t.type = ?
                AND t.account_id != ?
                AND (t.is_transfer = 0 OR t.is_transfer IS NULL)
                AND ABS(t.planned_amount - ?) < 0.01
                AND ABS(DATEDIFF(t.planned_date, ?)) <= ?
            ORDER BY ABS(DATEDIFF(t.planned_date, ?)) ASC, t.planned_date DESC
        ", [
            $userId,
            $oppositeType,
            $transaction->account_id,
            $transaction->planned_amount,
            $transaction->planned_date,
            $toleranceDays,
            $transaction->planned_date
        ]);

        $potentialPairs = [];

        foreach ($candidates as $candidate) {
            $candidateDate = strtotime($candidate->planned_date);
            $transactionDate = strtotime($transaction->planned_date);
            $daysDiff = abs(($candidateDate - $transactionDate) / 86400);

            // Usar método de confiança existente (adaptar objetos)
            $sourceObj = (object)[
                'description' => $transaction->description,
                'status' => $transaction->status,
            ];
            $candidateObj = (object)[
                'description' => $candidate->description,
                'status' => $candidate->status,
            ];
            $confidence = $this->calculateConfidence($sourceObj, $candidateObj, $daysDiff);

            $potentialPairs[] = [
                'id' => $candidate->id,
                'description' => $candidate->description,
                'amount' => $candidate->planned_amount,
                'date' => $candidate->planned_date,
                'status' => $candidate->status,
                'type' => $candidate->type,
                'account_id' => $candidate->account_id,
                'account_name' => $candidate->account_name,
                'days_diff' => (int)$daysDiff,
                'confidence' => $confidence,
            ];
        }

        // Ordenar por confiança (maior primeiro), depois por diferença de dias (menor primeiro)
        usort($potentialPairs, function($a, $b) {
            if ($b['confidence']['percentage'] !== $a['confidence']['percentage']) {
                return $b['confidence']['percentage'] <=> $a['confidence']['percentage'];
            }
            return $a['days_diff'] <=> $b['days_diff'];
        });

        return response()->json([
            'source' => [
                'id' => $transaction->id,
                'description' => $transaction->description,
                'amount' => $transaction->planned_amount,
                'date' => $transaction->planned_date,
                'status' => $transaction->status,
                'type' => $transaction->type,
                'account_id' => $transaction->account_id,
                'account_name' => $transaction->account->name ?? null,
            ],
            'pairs' => $potentialPairs,
            'total' => count($potentialPairs),
            'tolerance_days' => $toleranceDays,
        ]);
    }

    /**
     * Marca um par como transferência confirmada (vincula as duas transações)
     */
    public function confirm(Request $request): JsonResponse
    {
        $request->validate([
            'debit_id' => 'required|integer|exists:transactions,id',
            'credit_id' => 'required|integer|exists:transactions,id',
        ]);

        $userId = $request->user()->id;
        $debitId = $request->input('debit_id');
        $creditId = $request->input('credit_id');

        // Verificar se ambas transações pertencem ao usuário
        $debit = Transaction::where('id', $debitId)->where('user_id', $userId)->first();
        $credit = Transaction::where('id', $creditId)->where('user_id', $userId)->first();

        if (!$debit || !$credit) {
            return response()->json(['error' => 'Transaction not found'], 404);
        }

        // Marcar como transferência vinculada
        $debit->transfer_linked_id = $creditId;
        $debit->is_transfer = true;
        $debit->save();

        $credit->transfer_linked_id = $debitId;
        $credit->is_transfer = true;
        $credit->save();

        return response()->json([
            'success' => true,
            'message' => 'Transfer confirmed and linked',
            'debit_id' => $debitId,
            'credit_id' => $creditId,
        ]);
    }

    /**
     * Ignora um par de transferência (não sugerir novamente)
     */
    public function ignore(Request $request): JsonResponse
    {
        $request->validate([
            'debit_id' => 'required|integer|exists:transactions,id',
            'credit_id' => 'required|integer|exists:transactions,id',
        ]);

        $userId = $request->user()->id;
        
        // Salvar na tabela de pares ignorados
        DB::table('ignored_transfer_pairs')->insertOrIgnore([
            'user_id' => $userId,
            'debit_transaction_id' => $request->input('debit_id'),
            'credit_transaction_id' => $request->input('credit_id'),
            'created_at' => now(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Transfer pair ignored',
        ]);
    }

    /**
     * Deleta ambas as transações (débito e crédito) de uma transferência
     */
    public function deleteBoth(Request $request): JsonResponse
    {
        $request->validate([
            'debit_id' => 'required|integer|exists:transactions,id',
            'credit_id' => 'required|integer|exists:transactions,id',
        ]);

        $userId = $request->user()->id;
        $debitId = $request->input('debit_id');
        $creditId = $request->input('credit_id');

        $deleted = Transaction::whereIn('id', [$debitId, $creditId])
            ->where('user_id', $userId)
            ->delete();

        return response()->json([
            'success' => true,
            'message' => 'Both transactions deleted',
            'deleted_count' => $deleted,
        ]);
    }

    /**
     * Confirmar múltiplas transferências em lote
     */
    public function confirmBatch(Request $request): JsonResponse
    {
        $request->validate([
            'transfers' => 'required|array|min:1',
            'transfers.*.debit_id' => 'required|integer|exists:transactions,id',
            'transfers.*.credit_id' => 'required|integer|exists:transactions,id',
        ]);

        $userId = $request->user()->id;
        $transfers = $request->input('transfers');
        $confirmed = 0;
        $errors = [];

        foreach ($transfers as $index => $transfer) {
            $debitId = $transfer['debit_id'];
            $creditId = $transfer['credit_id'];

            // Verificar se ambas transações pertencem ao usuário
            $debit = Transaction::where('id', $debitId)->where('user_id', $userId)->first();
            $credit = Transaction::where('id', $creditId)->where('user_id', $userId)->first();

            if (!$debit || !$credit) {
                $errors[] = "Transfer {$index}: Transaction not found";
                continue;
            }

            // Marcar como transferência vinculada
            $debit->transfer_linked_id = $creditId;
            $debit->is_transfer = true;
            $debit->save();

            $credit->transfer_linked_id = $debitId;
            $credit->is_transfer = true;
            $credit->save();

            $confirmed++;
        }

        return response()->json([
            'success' => true,
            'message' => "Confirmed {$confirmed} transfers",
            'confirmed_count' => $confirmed,
            'errors' => $errors,
        ]);
    }

    /**
     * Estatísticas de transferências
     */
    public function stats(Request $request): JsonResponse
    {
        $userId = $request->user()->id;

        $confirmed = Transaction::where('user_id', $userId)
            ->where('is_transfer', true)
            ->whereNull('deleted_at')
            ->count();

        $ignored = DB::table('ignored_transfer_pairs')
            ->where('user_id', $userId)
            ->count();

        return response()->json([
            'confirmed_transfers' => $confirmed / 2, // Dividir por 2 pois cada transferência tem 2 transações
            'ignored_pairs' => $ignored,
        ]);
    }

    /**
     * Detecta possíveis reembolsos (gastos que foram devolvidos)
     * Critérios: mesmo valor, mesma conta, datas próximas, tipos opostos (debit/credit)
     */
    public function refunds(Request $request): JsonResponse
    {
        $userId = $request->user()->id;
        $toleranceDays = min(max((int) $request->input('tolerance_days', 7), 1), 30);
        
        // Buscar débitos (gastos)
        $debits = DB::select("
            SELECT 
                t.id,
                t.description,
                t.original_description,
                t.planned_amount,
                t.amount,
                t.planned_date,
                t.effective_date,
                t.status,
                t.account_id,
                a.name as account_name,
                a.currency as account_currency
            FROM transactions t
            LEFT JOIN accounts a ON t.account_id = a.id
            WHERE t.user_id = ?
                AND t.deleted_at IS NULL
                AND t.is_split_child = 0
                AND t.type = 'debit'
                AND COALESCE(t.amount, t.planned_amount) > 0
                AND (t.is_transfer = 0 OR t.is_transfer IS NULL)
                AND (t.is_refund_pair = 0 OR t.is_refund_pair IS NULL)
            ORDER BY t.planned_date DESC, t.planned_amount DESC
        ", [$userId]);

        // Buscar créditos (reembolsos potenciais)
        $credits = DB::select("
            SELECT 
                t.id,
                t.description,
                t.original_description,
                t.planned_amount,
                t.amount,
                t.planned_date,
                t.effective_date,
                t.status,
                t.account_id,
                a.name as account_name,
                a.currency as account_currency
            FROM transactions t
            LEFT JOIN accounts a ON t.account_id = a.id
            WHERE t.user_id = ?
                AND t.deleted_at IS NULL
                AND t.is_split_child = 0
                AND t.type = 'credit'
                AND COALESCE(t.amount, t.planned_amount) > 0
                AND (t.is_transfer = 0 OR t.is_transfer IS NULL)
                AND (t.is_refund_pair = 0 OR t.is_refund_pair IS NULL)
            ORDER BY t.planned_date DESC, t.planned_amount DESC
        ", [$userId]);

        $potentialRefunds = [];
        $usedDebitIds = [];
        $usedCreditIds = [];

        // Verificar pares ignorados
        $ignoredPairs = DB::table('ignored_refund_pairs')
            ->where('user_id', $userId)
            ->get()
            ->map(fn($p) => "{$p->debit_id}-{$p->credit_id}")
            ->toArray();

        foreach ($debits as $debit) {
            if (in_array($debit->id, $usedDebitIds)) continue;

            foreach ($credits as $credit) {
                if (in_array($credit->id, $usedCreditIds)) continue;
                
                // Deve ser na MESMA conta (diferente de transferência)
                if ($debit->account_id !== $credit->account_id) continue;

                // Mesmo valor (usar amount se disponível, senão planned_amount)
                $debitAmount = $debit->amount > 0 ? $debit->amount : $debit->planned_amount;
                $creditAmount = $credit->amount > 0 ? $credit->amount : $credit->planned_amount;
                
                if (abs((float)$debitAmount - (float)$creditAmount) > 0.01) continue;

                // Data dentro da tolerância
                $debitDate = strtotime($debit->effective_date ?? $debit->planned_date);
                $creditDate = strtotime($credit->effective_date ?? $credit->planned_date);
                $daysDiff = abs(($creditDate - $debitDate) / 86400);
                
                if ($daysDiff > $toleranceDays) continue;

                // Verificar se foi ignorado
                $pairKey = "{$debit->id}-{$credit->id}";
                if (in_array($pairKey, $ignoredPairs)) continue;

                // Calcular confiança e similaridade de descrição
                $confidence = $this->calculateRefundConfidence($debit, $credit, $daysDiff);

                $potentialRefunds[] = [
                    'debit' => [
                        'id' => $debit->id,
                        'description' => $debit->description,
                        'original_description' => $debit->original_description,
                        'amount' => (float) $debitAmount,
                        'date' => $debit->effective_date ?? $debit->planned_date,
                        'status' => $debit->status,
                        'account_id' => $debit->account_id,
                        'account_name' => $debit->account_name,
                    ],
                    'credit' => [
                        'id' => $credit->id,
                        'description' => $credit->description,
                        'original_description' => $credit->original_description,
                        'amount' => (float) $creditAmount,
                        'date' => $credit->effective_date ?? $credit->planned_date,
                        'status' => $credit->status,
                        'account_id' => $credit->account_id,
                        'account_name' => $credit->account_name,
                    ],
                    'amount' => (float) $debitAmount,
                    'currency' => $debit->account_currency ?? 'EUR',
                    'days_diff' => (int) $daysDiff,
                    'confidence' => $confidence,
                ];

                $usedDebitIds[] = $debit->id;
                $usedCreditIds[] = $credit->id;
                break;
            }
        }

        // Ordenar por confiança (maior primeiro)
        usort($potentialRefunds, function($a, $b) {
            return $b['confidence']['percentage'] <=> $a['confidence']['percentage'];
        });

        return response()->json([
            'data' => $potentialRefunds,
            'total' => count($potentialRefunds),
            'tolerance_days' => $toleranceDays,
        ]);
    }

    /**
     * Calcula confiança de que é um par gasto/reembolso
     */
    private function calculateRefundConfidence($debit, $credit, $daysDiff): array
    {
        $confidence = 40; // Base: mesmo valor na mesma conta
        $reasons = ['same_amount_same_account'];

        // Mesma data = +25%
        if ($daysDiff == 0) {
            $confidence += 25;
            $reasons[] = 'same_date';
        } elseif ($daysDiff == 1) {
            $confidence += 20;
            $reasons[] = 'next_day';
        } elseif ($daysDiff <= 3) {
            $confidence += 15;
            $reasons[] = 'within_3_days';
        } elseif ($daysDiff <= 7) {
            $confidence += 10;
            $reasons[] = 'within_week';
        }

        // Similaridade de descrição
        $debitDesc = strtolower($debit->original_description ?? $debit->description ?? '');
        $creditDesc = strtolower($credit->original_description ?? $credit->description ?? '');
        
        // Extrair palavras significativas (>3 caracteres)
        $debitWords = array_filter(preg_split('/\s+/', $debitDesc), fn($w) => strlen($w) > 3);
        $creditWords = array_filter(preg_split('/\s+/', $creditDesc), fn($w) => strlen($w) > 3);
        
        if (!empty($debitWords) && !empty($creditWords)) {
            $commonWords = array_intersect($debitWords, $creditWords);
            $totalWords = count(array_unique(array_merge($debitWords, $creditWords)));
            $similarity = $totalWords > 0 ? (count($commonWords) / $totalWords) * 100 : 0;
            
            if ($similarity >= 50) {
                $confidence += 25;
                $reasons[] = 'high_description_similarity';
            } elseif ($similarity >= 30) {
                $confidence += 15;
                $reasons[] = 'medium_description_similarity';
            } elseif ($similarity >= 15) {
                $confidence += 10;
                $reasons[] = 'low_description_similarity';
            }
        }

        // Keywords de reembolso
        $refundKeywords = ['bizum', 'devolucion', 'devolución', 'reembolso', 'refund', 'return', 'abono', 'favor'];
        foreach ($refundKeywords as $keyword) {
            if (strpos($debitDesc, $keyword) !== false || strpos($creditDesc, $keyword) !== false) {
                $confidence += 10;
                $reasons[] = 'refund_keyword';
                break;
            }
        }

        // Mesmo status = +5%
        if ($debit->status === $credit->status) {
            $confidence += 5;
            $reasons[] = 'same_status';
        }

        $confidence = min(100, $confidence);

        if ($confidence >= 85) {
            $level = 'high';
        } elseif ($confidence >= 65) {
            $level = 'medium';
        } else {
            $level = 'low';
        }

        return [
            'percentage' => $confidence,
            'level' => $level,
            'reasons' => $reasons,
        ];
    }

    /**
     * Confirma um par como reembolso (anula ambas transações)
     */
    public function confirmRefund(Request $request): JsonResponse
    {
        $request->validate([
            'debit_id' => 'required|integer|exists:transactions,id',
            'credit_id' => 'required|integer|exists:transactions,id',
        ]);

        $userId = $request->user()->id;
        $debitId = $request->input('debit_id');
        $creditId = $request->input('credit_id');

        $debit = Transaction::where('id', $debitId)->where('user_id', $userId)->first();
        $credit = Transaction::where('id', $creditId)->where('user_id', $userId)->first();

        if (!$debit || !$credit) {
            return response()->json(['error' => 'Transaction not found'], 404);
        }

        // Marcar ambas como par de reembolso (soft-anulação)
        $debit->is_refund_pair = true;
        $debit->refund_linked_id = $creditId;
        $debit->save();

        $credit->is_refund_pair = true;
        $credit->refund_linked_id = $debitId;
        $credit->save();

        return response()->json([
            'success' => true,
            'message' => 'Refund pair confirmed. Both transactions are now linked and excluded from calculations.',
            'debit_id' => $debitId,
            'credit_id' => $creditId,
        ]);
    }

    /**
     * Confirma múltiplos pares como reembolso
     */
    public function confirmRefundBatch(Request $request): JsonResponse
    {
        $request->validate([
            'pairs' => 'required|array|min:1',
            'pairs.*.debit_id' => 'required|integer|exists:transactions,id',
            'pairs.*.credit_id' => 'required|integer|exists:transactions,id',
        ]);

        $userId = $request->user()->id;
        $pairs = $request->input('pairs');
        $confirmed = 0;

        foreach ($pairs as $pair) {
            $debit = Transaction::where('id', $pair['debit_id'])->where('user_id', $userId)->first();
            $credit = Transaction::where('id', $pair['credit_id'])->where('user_id', $userId)->first();

            if (!$debit || !$credit) continue;

            $debit->is_refund_pair = true;
            $debit->refund_linked_id = $pair['credit_id'];
            $debit->save();

            $credit->is_refund_pair = true;
            $credit->refund_linked_id = $pair['debit_id'];
            $credit->save();

            $confirmed++;
        }

        return response()->json([
            'success' => true,
            'message' => "Confirmed {$confirmed} refund pairs",
            'confirmed_count' => $confirmed,
        ]);
    }

    /**
     * Ignorar um par de reembolso
     */
    public function ignoreRefund(Request $request): JsonResponse
    {
        $request->validate([
            'debit_id' => 'required|integer|exists:transactions,id',
            'credit_id' => 'required|integer|exists:transactions,id',
        ]);

        $userId = $request->user()->id;

        DB::table('ignored_refund_pairs')->insert([
            'user_id' => $userId,
            'debit_id' => $request->input('debit_id'),
            'credit_id' => $request->input('credit_id'),
            'created_at' => now(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Refund pair ignored',
        ]);
    }

    /**
     * Desfazer um par de reembolso confirmado
     */
    public function undoRefund(Request $request): JsonResponse
    {
        $request->validate([
            'debit_id' => 'required|integer|exists:transactions,id',
            'credit_id' => 'required|integer|exists:transactions,id',
        ]);

        $userId = $request->user()->id;

        $debit = Transaction::where('id', $request->input('debit_id'))
            ->where('user_id', $userId)
            ->first();
        $credit = Transaction::where('id', $request->input('credit_id'))
            ->where('user_id', $userId)
            ->first();

        if ($debit) {
            $debit->is_refund_pair = false;
            $debit->refund_linked_id = null;
            $debit->save();
        }

        if ($credit) {
            $credit->is_refund_pair = false;
            $credit->refund_linked_id = null;
            $credit->save();
        }

        return response()->json([
            'success' => true,
            'message' => 'Refund pair undone',
        ]);
    }
}
