<?php

namespace App\Http\Controllers\Frontend;

use App\Http\Controllers\Controller;
use App\Jobs\SendEmailJob;
use App\Mail\WithdrawalEmail;
use App\Models\ApiSettings;
use Illuminate\Http\Request;
use App\Models\Currency;
use App\Models\Guideline;
use App\Models\CSRNow\User as CsrNowUser;
use App\Models\DepositOption;
use App\Models\Member;
use App\Models\User;
use App\Models\UserTeamsiteLicense;
use Illuminate\Support\Facades\Auth;
use App\Models\Wallet;
use App\Models\Withdrawal;
use App\Models\WithdrawalWhitelist;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Session;
use Symfony\Component\HttpFoundation\Response;

class WithdrawalController extends Controller
{
    public function index(Request $request)
    {
        $withdrawalCurrency = Currency::where('status',1)->whereIn('wizard', ['Withdraw', 'All'])->get();
        $currency = Currency::where('status',1)->whereIn('wizard', ['Withdraw', 'All'])->pluck('abbreviation');
        return view('frontend.withdrawal.withdrawal-list',compact('currency','withdrawalCurrency'));
    }

    public function create(Request $request)
    {
        $data = Http::withToken('Bearer '.Session::get('api_login_token'))->withHeaders(getCsrNowApiHeader())->get(config('csrnow.api.live_endpoint').'auth/profile');
        $userDetails = $data->object()->data ?? null;
        $currency = Currency::whereIn('wizard', ['Withdraw', 'All'])->where('status',1)->get();
        $walletBalance = Wallet::where('user_id' , Auth::id())->where('wallet_list_id', 1)->first();
        $user = Auth::user();
        $apiSetting = ApiSettings::where('domain_holder', '=', 'tron_api')->first();
        $teamsiteLicenses = UserTeamsiteLicense::where('user_id', Auth::id())->where('start', '<=',Carbon::now())->where('end', '>=',Carbon::now())->count();
        $kycStatus = Member::where('user_id', Auth::id())->first();
        $withdrawalSetting = json_decode(getSiteSettings('active_withdrawal_button'), true);
        $showWithdrawal = true;
        $withdrawalMessages = [];
        if (!empty($withdrawalSetting)) {
            if(in_array('business_licenses',$withdrawalSetting) && $teamsiteLicenses == 0){
                $withdrawalMessages[] = "An active business license is required.";
                $showWithdrawal = false;
            }
            if(in_array('kyc_completed',$withdrawalSetting) && (empty($kycStatus) || $kycStatus->kyc_status !== "active")){
                $withdrawalMessages[] = "KYC verification must be completed.";
                $showWithdrawal = false;
            }
            if(in_array('enable_google_account_2fa',$withdrawalSetting) && (empty(Auth::user()->setting->fa_setting) || !in_array('withdrawal', Auth::user()->setting->fa_setting))){
                $withdrawalMessages[] = "Google 2FA for withdrawals must be enabled.";
                $showWithdrawal = false;
            }
        }

        return view('frontend.withdrawal.index', compact('userDetails','currency','walletBalance','user','apiSetting','showWithdrawal','withdrawalMessages'));
    }

    public function getCurrency($currency_id)
    {
        $currency = Currency::find($currency_id);
        return response()->json($currency);
    }

    public function currencyGuideLine($currency_id)
    {
        $guidelines = Guideline::where('currency_id', $currency_id)->where('type', 'withdrawal')->first();
        return response()->json($guidelines);
    }

    public function getBlockchain($currency_id)
    {
        $blockchain = DepositOption::where('deposit_currency', $currency_id)->where('status', 1)->get();
        return response()->json($blockchain);
    }

    public function store(Request $request)
    {
        if(in_array('withdrawal', Auth::user()->setting->fa_setting) || in_array('withdrawal', Auth::user()->setting->fa3_setting)) {
            if(!Session::has('withdrawal2faVerification') || (Session::has('withdrawal2faVerification') && Session::get('withdrawal2faVerification') !== true)) {
                return response()->json(['status' => false, 'msg' => 'Can`t submit form without authentication code '], Response::HTTP_UNPROCESSABLE_ENTITY);
            } else {
                Session::forget('withdrawal2faVerification');
            }
        }
        try {
            $data = $request->validate([
                'currency_id' => 'required',
                'amount' => 'required|numeric',
                'withdrawal_wallet_id' => 'sometimes',
                'exchange_amount' => 'nullable|numeric',
                'blockchain' => 'sometimes',
                'blockchain_address' => 'sometimes',
                'exchange_rate' => 'nullable|numeric',
                'account_type' => 'nullable|string',
                'withdrawal_fee' => 'nullable|numeric',
                'received_amount' => 'nullable|numeric',
                'primary_account_first_name' => 'required_if:account_type,joint_account',
                'primary_account_last_name' => 'required_if:account_type,joint_account',
                'joint_account_first_name' => 'required_if:account_type,joint_account',
                'joint_account_last_name' => 'required_if:account_type,joint_account',
                'business_name' => 'required_if:account_type,business_account',
                'account_holder'=> 'sometimes',
                'bank_name'=> 'sometimes',
                'iban_number'=> 'sometimes',
                'bank_branch_name'=> 'sometimes',
                'bic_swift_number'=> 'sometimes',
                'bank_address'=> 'sometimes'
            ]);
            if(!isset($data['account_type']) || (isset($data['account_type']) && $data['account_type'] != "joint_account")){
                $data['primary_account_first_name'] = null;
                $data['primary_account_last_name'] = null;
            }
            $currency = Currency::find($data['currency_id']);

            // received_amount calculation
            $withdrawalFee = getSiteSettings('withdrawal_fee');
            $data['withdrawal_fee'] = $withdrawalFee;
            $data['received_amount'] = $data['amount'] - $withdrawalFee;
            // exchange_amount calculation
            if($currency->abbreviation != 'EUR'){
                $to = $currency->abbreviation;
                $exchangeRate = convertCurrency('EUR',$to);
                $exchangeRate = floor($exchangeRate * 100) / 100;
                $data['exchange_rate'] = number_format($exchangeRate, 2, '.', '');
                $exchange_amount = $data['received_amount'] * $data['exchange_rate'];
                $data['exchange_amount'] = $exchange_amount;
            }
            $walletBalance = Wallet::where('user_id' , Auth::id())->where('wallet_list_id', 1)->first();
            $data['withdrawal_wallet_id'] = $walletBalance->id;
            $availableBalance = getOCACurrentBalance();
            if($data['amount'] >= $availableBalance) {
                return response()->json(['success' => false,'msg' => 'You have insufficient balance for withdrawal.'], 422);
            }

            /* store data in withdrawal table */
            $data['user_id'] = Auth::id();
            $randomRefNo = wordwrap(generateRandomCode(12), 4, "-", true);
            $referenceNo = "WIT-$randomRefNo";
            $data['reference_no'] = $referenceNo;
            $data['wallet_id'] = $data['withdrawal_wallet_id'];
            $dayOfToday = Carbon::now()->format('l');
            $data['due_date'] = $dayOfToday == "Saturday" ? Carbon::now()->addDays(7) : ($dayOfToday == "Sunday" ? Carbon::now()->addDays(6) : Carbon::now()->addDays(5));

            // Condition for under review status
            if(isset($data['blockchain_address'])){
                $whitelistUser = WithdrawalWhitelist::where(['user_id' => Auth::user()->id,'blockchain_address' => $request->blockchain_address])->exists();
                if(!$whitelistUser){
                    $newWithdrawal = Withdrawal::where('blockchain_address', $request->blockchain_address)->count();
                    $multipleUserWithdrawal = Withdrawal::where('blockchain_address',$request->blockchain_address)->WhereNot('user_id',Auth::user()->id)->count();
                    $csrWithdrawalApi = Http::withToken('Bearer '.Session::get('api_login_token'))->withHeaders(getCsrNowApiHeader())->get(config('csrnow.api.live_endpoint').'auth/get-withdrawal-data/'.$request->blockchain_address);
                    $responseData = $csrWithdrawalApi->object();

                    if($newWithdrawal == 0 || $multipleUserWithdrawal > 0 || (isset($responseData->status) && $responseData->status == true && !empty($responseData->withdrawData))){
                        $data['status'] = 4;
                    }
                }
            }
            $withdrawal = Withdrawal::create($data);

            /* find account details based on account type */
            $account_details = '';
            switch ($request->account_type) {
                case 'personal':
                    $account_details = 'Account holder name: ' .Auth::user()->details->first_name . ' ' . Auth::user()->details->last_name;
                    break;
                case 'joint_account':
                    $account_details = 'Primary account holder name: ' .$withdrawal->primary_account_first_name . ' ' . $withdrawal->primary_account_last_name.'<br>';
                    $account_details .= 'Secondary account holder name: ' .$withdrawal->joint_account_first_name . ' ' . $withdrawal->joint_account_last_name;
                    break;
                case 'business_account':
                    $account_details = 'Business name: ' .$withdrawal->business_name;
                    break;
                default:
                    break;
            }

            if($withdrawal->currency->abbreviation == "EUR" || $withdrawal->currency->abbreviation == "CAD"){
                $log = 'Withdrawal created successfully. <br><br>
                        Funds sent to:<br>
                        Username: ' . Auth::user()->details->username . ' <br>
                        Members Name: ' . Auth::user()->details->first_name . ' ' . Auth::user()->details->last_name . ' <br>
                        Account Holder: ' . $data['account_holder'] .'<br>
                        Bank Name: ' . $data['bank_name'] .'<br>
                        IBAN Number: ' . $data['iban_number'] .'<br>
                        Bank Branch Name: ' . $data['bank_branch_name'] .'<br>
                        BIC/SWIFT: ' . $data['bic_swift_number'] .'<br>
                        Bank Address: ' . $data['bank_address'] .'<br><br>
                        Date: ' . $withdrawal->created_at . '<br>
                        Withdrawal Amount: ' . formatDisplayNumber($data['amount']) . ' EUR <br>';
                if($withdrawalFee != 0){
                    $log .= 'Withdrawal Fee: ' . formatDisplayNumber($withdrawal->withdrawal_fee) . ' EUR <br>';
                }
                 $log .= 'Received Amount: ' . formatDisplayNumber($withdrawal->received_amount) . ' EUR <br>';
                if($withdrawal->currency->abbreviation != "EUR"){
                    $log .= 'Exchange Amount: ' . formatDisplayNumber($data['exchange_amount']) . ' '. $withdrawal->currency->abbreviation .' <br>';
                }
                $log .= 'Reference No: ' . $withdrawal->reference_no . '<br><br>
                        Account holder details:<br>'. $account_details.'<br>';
            } else{
                $log = 'Withdrawal created successfully. <br><br>
                        Funds sent to:<br>
                        Username: ' . Auth::user()->details->username . ' <br>
                        Members Name: ' . Auth::user()->details->first_name . ' ' . Auth::user()->details->last_name . ' <br>
                        Blockchain: ' . $data['blockchain'] .'<br>
                        Blockchain Address: ' . $data['blockchain_address'] .'<br>
                        Date: ' . $withdrawal->created_at . '<br>
                        Withdrawal Amount: ' . formatDisplayNumber($data['amount']) . ' EUR <br>';
                if($withdrawalFee != 0){
                     $log .= 'Withdrawal Fee: ' . formatDisplayNumber($withdrawal->withdrawal_fee) . ' EUR <br>';
                }
                $log .= 'Received Amount: ' . formatDisplayNumber($withdrawal->received_amount) . ' EUR <br>
                        Exchange Amount: ' . formatDisplayNumber($data['exchange_amount']) . ' '. $withdrawal->currency->descabbreviationription .' <br>
                        Reference No: ' . $withdrawal->reference_no . '<br>';
            }

            saveLog($log, Auth::user(), ['logType' => 'withdrawal'], 'withdrawal');

            $body = 'Reference No: ' . $withdrawal->reference_no . '<br>';
            $inputs['name'] = Auth::user()->details->username;
            $inputs['email'] = Auth::user()->details->email;
            $inputs['body'] = $body;
            $emailSwitch = getEmailSettings('withdrawal');
            if($emailSwitch == 'on'){
                $emailClassRef = new WithdrawalEmail($inputs);
                SendEmailJob::dispatch($inputs['email'], $emailClassRef);
            }
            return response()->json(['success' => true, 'msg' => 'Withdrawal created successfully', 'data' => $withdrawal]);
        } catch (Exception $e) {
            $log = 'Withdrawal create failed. <br>
                    Username: ' . Auth::user()->details->first_name . ' ' . Auth::user()->details->last_name . ' <br>
                    Date: ' . Carbon::now() . '<br>
                    Withdrawal: ' . formatDisplayNumber($request->amount) . ' <br>';
            saveLog($log, Auth::user(), ['logType' => 'withdrawal failed'], 'withdrawal failed');
            reportLog($e);
            return response()->json(['status' => false, 'msg' => 'Error: ' . $e->getMessage()], Response::HTTP_UNPROCESSABLE_ENTITY);
        }
    }

    function generateTicketDescription( $withdrawal, $account_details)
    {
        if($withdrawal->currency->abbreviation == "EUR" || $withdrawal->currency->abbreviation == "CAD"){
            $description = 'Dear Support,<br><br>
                            This ticket was raised by the withdrawal wizard on AAC.<br><br>
                            Funds sent to:<br>
                            Username: ' . Auth::user()->details->username . ' <br>
                            Members Name: ' . Auth::user()->details->first_name . ' ' . Auth::user()->details->last_name . ' <br>
                            Account Holder: ' . $withdrawal->account_holder .'<br>
                            Bank Name: ' . $withdrawal->bank_name .'<br>
                            IBAN Number: ' . $withdrawal->iban_number .'<br>
                            Bank Branch Name: ' . $withdrawal->bank_branch_name .'<br>
                            BIC/SWIFT: ' . $withdrawal->bic_swift_number .'<br>
                            Bank Address: ' . $withdrawal->bank_address .'<br><br>
                            Date: ' . $withdrawal->created_at . '<br>
                            Withdrawal Amount: ' . formatDisplayNumber($withdrawal->amount) . ' EUR <br>
                            Withdrawal Fee: ' . formatDisplayNumber($withdrawal->withdrawal_fee) . ' EUR <br>
                            Received Amount: ' . formatDisplayNumber($withdrawal->received_amount) . ' EUR <br>';
            if($withdrawal->currency->abbreviation != "EUR"){
                $description .= 'Exchange Amount: ' . formatDisplayNumber($withdrawal->exchange_amount) . ' '. $withdrawal->currency->abbreviation .' <br>';
            }
            $description .= 'Reference: ' . $withdrawal->reference_no . '<br>'.
                             $account_details .'<br><br>
                            Once your withdrawal request has been reviewed and approved, the funds will be processed accordingly.<br><br>
                            Thank you!';
        } else {
            $description = 'Dear Support,<br><br>
                            This ticket was raised by the withdrawal wizard on AAC.<br><br>
                            Funds sent to:<br>
                            Username: ' . Auth::user()->details->username . ' <br>
                            Members Name: ' . Auth::user()->details->first_name . ' ' . Auth::user()->details->last_name . ' <br>
                            Blockchain: ' . $withdrawal->blockchain .'<br>
                            Blockchain Address: ' . $withdrawal->blockchain_address .'<br>
                            Date: ' . $withdrawal->created_at . '<br>
                            Withdrawal Amount: ' . formatDisplayNumber($withdrawal->amount) . ' EUR <br>
                            Withdrawal Fee: ' . formatDisplayNumber($withdrawal->withdrawal_fee) . ' EUR <br>
                            Received Amount: ' . formatDisplayNumber($withdrawal->received_amount) . ' EUR <br>
                            Exchange Amount: ' . formatDisplayNumber($withdrawal->exchange_amount) . ' '. $withdrawal->currency->abbreviation .' <br>
                            Reference: ' . $withdrawal->reference_no . '<br><br>
                            Once your withdrawal request has been reviewed and approved, the funds will be processed accordingly.<br><br>
                            Thank you!';
        }
        return $description;
    }

    public function allWithdrawal(Request $request)
    {
        $search = $request->filter;
        $filter = (array) json_decode($search);
        $sort = $request->sort ?: 'id';
        $order = $request->order ?: 'desc';
        $offset = $request->offset;
        $limit = $request->limit;

        $query = Withdrawal::with('user','currency','wallet','preApprovedBy','approvedBy');
        if (isset($request->currency_id)){
            $query->where('currency_id',$request->currency_id);
        }
        $query->when($search, function ($q) use ($filter) {
                foreach ($filter as $key => $item) {
                    if ($key == 'created_at') {
                        $dates = explode(' - ', $item);
                        $startDate = createFromFormatCustom($dates[0]);
                        $endDate = createFromFormatCustom($dates[1]);
                        $q->whereDate('created_at', '>=', $startDate)->whereDate('created_at', '<=', $endDate);
                    } elseif ($key == 'due_date') {
                        $dates = explode(' - ', $item);
                        $startDate = createFromFormatCustom($dates[0]);
                        $endDate = createFromFormatCustom($dates[1]);
                        $q->whereDate('due_date', '>=', $startDate)->whereDate('due_date', '<=', $endDate);
                    } elseif ($key === 'pre_approved_by') {
                        $externalId = CsrNowUser::where("username", 'LIKE', '%' . trim($item) . '%')->pluck('id');
                        $userId = User::whereIntegerInRaw('external_id',$externalId)->pluck('id');
                        $q->whereIntegerInRaw('pre_approved_by',$userId);
                    } elseif ($key === 'approved_by') {
                        $externalId = CsrNowUser::where("username", 'LIKE', '%' . trim($item) . '%')->pluck('id');
                        $userId = User::whereIntegerInRaw('external_id',$externalId)->pluck('id');
                        $q->whereIntegerInRaw('approved_by',$userId);
                    } elseif ($key === 'withdrawal_currency') {
                        $q->whereHas("currency", function ($q) use ($item) {
                                $q->where('description',trim($item));
                        });
                    }  elseif ($key === 'exchange_amount') {
                        $q->where(function ($q) use ($item) {
                            $q->whereHas("currency", function ($q) use ($item) {
                                $q->where('description', 'EUR')
                                ->where('amount', 'LIKE', trim($item) . '%');
                            })->orWhere(function ($q) use ($item) {
                                $q->where('exchange_amount', 'LIKE', trim($item) . '%');
                            });
                        });
                    } elseif ($key === 'wallet_balance') {
                        $q->whereHas("walletLog", function ($q) use ($item) {
                                $q->where('balance', 'LIKE', '%' . trim($item) . '%');
                        });
                    } elseif ($key === 'status') {
                        if ($item === 'Pending') {
                            $q->whereIn("status", [0,3,4]);
                        } else if ($item === 'Approved') {
                            $q->where("status", 1);
                        } else if ($item === 'Rejected') {
                            $q->where("status", 2);
                        }
                    } else {
                        $q->where($key, 'like', '%' . $item . '%');
                    }
                }
            })->when($sort, function ($q) use ($sort, $order) {
                if ($sort == "counter") {
                    $q->orderBy('id', $order);
                } else {
                    $q->orderBy($sort, $order);
                }
            })->where('user_id',Auth::id());

        $count = $query->count();

        $row = $query->when($offset, function ($q) use ($offset) {
            $q->offset($offset);
        })->when($limit, function ($q) use ($limit) {
            $q->limit($limit);
        })->get()->toArray();
        $counter = $offset + 1;
        foreach ($row as $key => $item) {
            $referenceNo =$item['reference_no'] ?? '-';
            $blockchainAddress = $item['blockchain_address'];
            $transformedBlockchainAddress = null;
            if(isset($blockchainAddress)){
                $transformedBlockchainAddress = '<div class="d-flex"><span class="text-monospace">'. getMaskedString($blockchainAddress,8) .'</span>';
                $transformedBlockchainAddress.=' <a type="button" style="float:right" onclick="copyToClipboard(\''. $blockchainAddress .'\')" " data-toggle="tooltip" data-placement="top" title="'. $blockchainAddress .'"><i class="bi bi-copy ms-2 fw-bold"></i></a></div>';
            }
            $transactionHash = $item['transaction_hash'];
            $transformedHash = null;
            if(isset($transactionHash)){
                $transformedHash = '<div class="d-flex"><span class="text-monospace">'. getMaskedString($transactionHash) .'</span>';
                $transformedHash .= ' <a type="button" style="float:right" onclick="copyToClipboard(\'' . $transactionHash . '\')" data-toggle="tooltip" data-placement="top" title="' . $transactionHash . '"><i class="bi bi-copy ms-2 fw-bold"></i></a></div>';
            }
            $row[$key]['counter'] = $counter;
            $row[$key]['reference_no'] = '<span class="text-monospace">'. $referenceNo .'</span>';
            $row[$key]['withdrawal_currency'] = $item['currency']['description'] ?? '-';
            $row[$key]['blockchain_address'] = $transformedBlockchainAddress ?? '-';
            $row[$key]['transaction_hash'] = $transformedHash ?? '-';
            $row[$key]['amount'] = formatDisplayNumber($item['amount']) ?? '-';
            $row[$key]['exchange_amount'] = $item['exchange_amount'] != 0 ? formatDisplayNumber($item['exchange_amount']) : formatDisplayNumber($item['amount']);
            $row[$key]['wallet_balance'] = $item['wallet_log_balance'] ? formatDisplayNumber($item['wallet_log_balance']) : '-';
            $row[$key]['pre_approved_by'] = $item['pre_approved_by']['details']['username'] ?? '-';
            $row[$key]['approved_by'] = $item['approved_by']['details']['username'] ?? '-';
            if($item['status'] == 2){
                if(isset($item['reason']) && strlen($item['reason']) > 50) {
                    $row[$key]['reason'] = substr($item['reason'],0,20) . '... <i class="bi bi-info-circle fw-bold" data-toggle="tooltip" data-placement="top" title="'.$item['reason'].'"></i>';
                }
            }

            $row[$key]['created_at'] = getDateWithIcon($item['created_at']);
            $row[$key]['due_date'] = $item['due_date'] ? getDateWithIcon($item['due_date']) : '-';
            if ($item['status'] == 0 || $item['status'] == 3 || $item['status'] == 4) {
                $row[$key]['status'] = 'Pending';
            } else if ($item['status'] == 1) {
                $row[$key]['status'] = 'Approved';
            } else if ($item['status'] == 2) {
                $row[$key]['status'] = 'Rejected';
            }
            $counter++;
        }
        $data['count'] = $count;
        $data['items'] = $row;
        return response()->json($data);
    }

    public function getDuplicateWithdrawal(Request $request){
        $withdrawal = Withdrawal::where(['blockchain' => $request->blockchain, 'blockchain_address' => $request->blockchain_address])->where('status',0)->first();
        if(isset($withdrawal)){
            return response()->json(['status' => false, 'msg' => 'This withdrawal request has already been submitted.']);
        } else{
            return response()->json(['status' => true]);
        }

    }
}
