<?php

namespace App\Jobs;

use App\Models\Transfer;
use App\Models\User;
use App\Models\UserTransaction;
use App\Services\TransferService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class TransferToBank implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * Create a new job instance.
     */
    public function __construct(public $account, public User $user,)
    {
        //
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {

        try {
            $transferService = new TransferService();

            $transferReference = $transferService->initaiteDotTransfer(
                $this->account['bank_code'],
                $this->account['account_number'],
                $this->account['account_name'],
                $this->account['amount'],
                $this->account['reference'],
                $this->account['description'],
                $this->account['bank_name'],
                $this->user
            );

            Log::channel('transfer-logs')->info("Transfer reference: " . json_encode($transferReference));


            if ($transferReference['state'] == 'FAILED') {
                throw new \Exception($transferReference['message']);
            }

            $tranferRecord = Transfer::firstWhere('reference', $this->account['reference']);

            if (!$tranferRecord) {
                throw new \Exception("Transfer record not found for reference: {$this->account['reference']}");
            }

            $tranferRecord->update([
                'reference' => $transferReference['receiptNumber'],
                'status' => $transferReference['state'],
                'transfer_id' => $transferReference['requestId'],
            ]);
        } catch (\Exception $e) {
            // Your existing exception handling
            $this->handleFailedTransfer($e);

            Log::channel('transfer-logs')->error("Transfer job failed: " . $e->getMessage());

            throw new \Exception("Transfer failed: " . $e->getMessage());
        }
    }

    private function handleFailedTransfer(\Exception $e)
    {
        DB::beginTransaction();

        $tranferRecord = Transfer::firstWhere('reference', $this->account['reference']);

        if ($tranferRecord) {
            $tranferRecord->update([
                'status' => Transfer::STATUS_FAILED
            ]);

            $user = $tranferRecord->user;
            $total = $this->account['amount'] + $this->account['swiftpay_fee'];

            $user->increment('wallet_balance', $total);

            UserTransaction::create([
                'user_id' => $user->id,
                'type' => UserTransaction::TYPE_CREDIT,
                'amount' => $total,
                'source' => UserTransaction::SOURCE_BANK_TRANSFER,
                'status' => UserTransaction::STATUS_SUCCESSFUL,
                'message' => "Refunded N{$total} to your account due to failed multiple transfers"
            ]);
        }

        DB::commit();
    }
}
