<?php

namespace App\Http\Controllers\Api;

use App\Constants\Status;
use App\Http\Controllers\Controller;
use App\Lib\Api\UserActionProcess;
use App\Lib\FormProcessor;
use App\Models\AdminNotification;
use App\Models\BankTransfer;
use App\Models\SetupBankTransfer;
use App\Models\Transaction;
use App\Models\TransactionCharge;
use App\Models\UserAction;
use App\Models\UserBank;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class BankTransferController extends Controller
{
    public function addBank(Request $request)
    {
        $bank = SetupBankTransfer::active()->find($request->bank_id);

        if (!$bank) {
            $notify[] = "Sorry, Bank not found";
            return responseError('validation_error', $notify);
        }

        $formData       = $bank->form->form_data;
        $formProcessor  = new FormProcessor();
        $validationRule = $formProcessor->valueValidation($formData);
        $userData       = $formProcessor->processFormData($request, $formData);

        $validator = Validator::make($request->all(), array_merge([
            'account_holder' => 'required',
            'account_number' => 'required',
        ], $validationRule));

        if ($validator->fails()) {
            return responseError('validation_error', $validator->errors());
        }

        $userBank                 = new UserBank();
        $userBank->user_id        = auth()->id();
        $userBank->bank_id        = $bank->id;
        $userBank->account_number = $request->account_number;
        $userBank->account_holder = $request->account_holder;
        $userBank->user_data      = $userData;
        $userBank->save();

        $notify[] = "Bank added successfully";
        return responseSuccess('add_bank', $notify, [
            'bank' => $userBank,
        ]);
    }

    public function bankDetails($id)
    {
        $notify[] = "My Bank Details";
        $user     = auth()->user();

        $bank = UserBank::where('user_id', $user->id)->with('bank', 'bank.form')->find($id);
        if (!$bank) {
            $notify[] = 'Sorry, Bank not found';
            return responseError('validation_error', $notify);
        }


        return responseSuccess('bank_details', $notify, [
            'bank' => $bank,
        ]);
    }

    public function updateBank(Request $request)
    {

        $bank = SetupBankTransfer::find($request->bank_id);
        if (!$bank) {
            $notify[] = "Sorry, Bank not found";
            return responseError('validation_error', $notify);
        }

        $formData       = $bank->form->form_data;
        $formProcessor  = new FormProcessor();
        $validationRule = $formProcessor->valueValidation($formData);
        $userData       = $formProcessor->processFormData($request, $formData);

        $validator = Validator::make($request->all(), array_merge([
            'id'             => 'required',
            'account_holder' => 'required',
            'account_number' => 'required',
        ], $validationRule));

        if ($validator->fails()) {
            return responseError('validation_error', $validator->errors());
        }

        $user     = auth()->user();
        $userBank = UserBank::where('user_id', $user->id)->where('bank_id', $request->bank_id)->find($request->id);
        if (!$userBank) {
            $notify[] = 'Sorry, User Bank not found';
            return responseError('validation_error', $notify);
        }

        $userBank->account_holder = $request->account_holder;
        $userBank->account_number = $request->account_number;
        $userBank->user_data      = $userData;
        $userBank->save();

        $notify[] = "Bank updated successfully";
        return responseSuccess('update_bank', $notify, [
            'bank' => $userBank,
        ]);
    }

    public function deleteBank(Request $request)
    {

        $validator = Validator::make($request->all(), [
            'user_bank_id' => 'required',
        ]);

        if ($validator->fails()) {
            return responseError('validation_error', $validator->errors());
        }

        $userBank = UserBank::where('user_id', auth()->id())->find($request->user_bank_id);
        if (!$userBank) {
            $notify[] = 'Sorry, User Bank not found';
            return responseError('validation_error', $notify);
        }

        $userBank->delete();
        $notify[] = 'Bank deleted successfully';
        return responseSuccess('delete_bank', $notify);
    }

    public function bankTransfer()
    {
        $notify[]           = "Bank Transfer";
        $user               = auth()->user();
        $bankTransferCharge = TransactionCharge::where('slug', 'bank_transfer')->first();
        $banks              = SetupBankTransfer::active()->with('form')->whereHas('form')->get();
        $myBanks            = UserBank::where('user_id', $user->id)->with('bank', 'bank.form')->get();

        return responseSuccess('bank_transfer', $notify, [
            'otp_type'             => otpType(),
            'current_balance'      => $user->balance,
            'bank_transfer_charge' => $bankTransferCharge,
            'banks'                => $banks,
            'my_added_banks'       => $myBanks,
        ]);
    }

    public function bankTransferConfirm(Request $request)
    {
        $bank          = '';
        $userData      = '';
        $user          = auth()->user();
        $accountNumber = $request->account_number;
        $accountHolder = $request->account_holder;

        if ($request->user_bank_id) {
            $userBank = UserBank::where('user_id', $user->id)->find($request->user_bank_id);
            if (!$userBank) {
                $notify[] = 'Sorry, User Bank not found';
                return responseError('validation_error', $notify);
            }
            $bank = $userBank->bank;
            if (!$bank->status) {
                $notify[] = 'Sorry, Bank not found';
                return responseError('validation_error', $notify);
            }

            $userData      = $userBank->user_data;
            $accountNumber = $userBank->account_number;
            $accountHolder = $userBank->account_holder;
        } else {
            if (!$request->bank_id) {
                $notify[] = 'Bank id is required';
                return responseError('validation_error', $notify);
            }

            $bank = SetupBankTransfer::active()->whereHas('form')->find($request->bank_id);
            if (!$bank) {
                $notify[] = 'Sorry, Bank not found';
                return responseError('validation_error', $notify);
            }

            $formData       = $bank->form->form_data;
            $formProcessor  = new FormProcessor();
            $validationRule = $formProcessor->valueValidation($formData);
            $userData       = $formProcessor->processFormData($request, $formData);

            $validator = Validator::make($request->all(), array_merge([
                'amount'         => 'required|gt:0',
                'bank_id'        => 'required',
                'otp_type'       => otpType(validation: true),
                'pin'            => 'required',
                'account_number' => 'required',
                'account_holder' => 'required',
            ], $validationRule));

            if ($validator->fails()) {
                return responseError('validation_error', $validator->errors());
            }
        }

        if (!Hash::check($request->pin, $user->password)) {
            $notify[] = 'Provided PIN does not correct';
            return responseError('validation_error', $notify);
        }

        $bankTransferCharge = TransactionCharge::where('slug', 'bank_transfer')->first();
        if (!$bankTransferCharge) {
            $notify[] = 'Sorry, Transaction charge not found';
            return responseError('validation_error', $notify);
        }

        if ($request->amount < $bankTransferCharge->min_limit || $request->amount > $bankTransferCharge->max_limit) {
            $notify[] = 'Please follow the bank transfer limit';
            return responseError('validation_error', $notify);
        }

        $fixedCharge = $bankTransferCharge->fixed_charge;
        $totalCharge = ($request->amount * $bankTransferCharge->percent_charge / 100) + $fixedCharge;
        $totalAmount = getAmount($request->amount + $totalCharge);

        if ($bankTransferCharge->daily_limit != -1 && $user->trxLimit('bank_transfer')['daily'] + $totalAmount >= $bankTransferCharge->daily_limit) {
            $notify[] = 'Daily bank transfer limit has been exceeded';
            return responseError('validation_error', $notify);
        }

        if ($totalAmount > $user->balance) {
            $notify[] = 'Sorry! Insufficient balance';
            return responseError('validation_error', $notify);
        }

        $userAction          = new UserActionProcess();
        $userAction->user_id = $user->id;
        $userAction->act     = 'bank_transfer';

        $userAction->details = [
            'user_data'      => $userData,
            'amount'         => $request->amount,
            'bank_id'        => $bank->id,
            'account_number' => $accountNumber,
            'account_holder' => $accountHolder,
            'total_amount'   => $totalAmount,
            'total_charge'   => $totalCharge,
            'done_route'     => 'api.bank.transfer.done',
        ];

        if (count(otpType())) {
            $userAction->type = $request->otp_type;
        }
        $userAction->submit();
        $actionId = $userAction->action_id;

        if ($userAction->verify_api_otp) {
            $notify[] = 'Verify otp';
            return responseSuccess('verify_otp', $notify, [
                'action_id' => $actionId,
            ]);
        }

        return callApiMethod($userAction->next_route, $actionId);
    }

    public function bankTransferDone($actionId)
    {
        $user = auth()->user();

        $userAction = UserAction::where('id', $actionId)
            ->where('user_id', $user->id)
            ->where('user_type', 'USER')
            ->where('is_api', Status::YES)
            ->where('is_used', Status::NO)
            ->first();

        if (!$userAction) {
            $notify[] = 'Sorry! Unable to process';
            return responseError('validation_error', $notify);
        }

        $details = $userAction->details;
        $bank    = SetupBankTransfer::find($details->bank_id);

        if (@$details->total_amount > $user->balance) {
            $notify[] = 'Sorry! Insufficient balance';
            return responseError('validation_error', $notify);
        }

        $userAction->is_used = Status::YES;
        $userAction->save();

        $user->balance -= $details->total_amount;
        $user->save();

        $transfer                         = new BankTransfer();
        $transfer->account_number         = $details->account_number;
        $transfer->account_holder         = $details->account_holder;
        $transfer->user_id                = $user->id;
        $transfer->setup_bank_transfer_id = $bank->id;
        $transfer->amount                 = $details->amount;
        $transfer->trx                    = getTrx();
        $transfer->user_data              =
            $details->user_data;
        $transfer->save();

        $transaction                = new Transaction();
        $transaction->user_id       = $user->id;
        $transaction->user_type     = 'USER';
        $transaction->before_charge = $details->amount;
        $transaction->amount        = $details->total_amount;
        $transaction->post_balance  = $user->balance;
        $transaction->charge        = $details->total_charge;
        $transaction->charge_type   = '+';
        $transaction->trx_type      = '-';
        $transaction->remark        = 'bank_transfer';
        $transaction->details       = 'Bank transfer';
        $transaction->receiver_id   = 0;
        $transaction->receiver_type = null;
        $transaction->trx           = $transfer->trx;
        $transaction->save();

        generatePoints($transaction, $user);

        checkUserReward($user, $transaction);

        $adminNotification            = new AdminNotification();
        $adminNotification->user_id   = $user->id;
        $adminNotification->title     = 'New bank transfer request from ' . $user->username;
        $adminNotification->click_url = urlPath('admin.bank.transfer.all');
        $adminNotification->save();

        $notify[] = 'Successfully complete the bank transfer process';
        return responseSuccess('bank_transfer_done', $notify, [
            'bank_transfer' => $transaction,
            'transaction'   => $transaction,
            'bank' => $bank
        ]);
    }

    public function bankTransferHistory()
    {
        $notify[] = "Bank Transfer History";
        $user     = auth()->user();

        return responseSuccess('bank_transfer_history', $notify, [
            'file_path'      => route('home') . '/' . getFilePath('verify'),
            'total_transfer' => BankTransfer::where('user_id', $user->id)->sum('amount'),
            'history'        => BankTransfer::where('user_id', $user->id)->with('bank', 'getTrx')->apiQuery(),
        ]);
    }
}
