• File: UserController.php
  • Full Path: /var/www/imaliapi/app/Http/Controllers/UserController.php
  • Date Modified: 12/15/2025 4:44 PM
  • File size: 183.84 KB
  • MIME-type: text/x-php
  • Charset: utf-8
<?php

namespace App\Http\Controllers;

use App\AmountGenerate;
use App\Bank\MasterAccount;
use App\Bank\Payment;
use App\Classes\GenerateToken;
use App\Classes\CurrentPassword;
use App\Classes\Kyc;
use App\Classes\AuthPIN;
use App\Classes\Record;
use App\Classes\SendSMS;
use App\Classes\SmsManager;
use App\Classes\TransactionGeneration;
use App\Credelec;
use App\Imali\BankConection;
use App\Imali\ImaliAccount;
use App\Imali\RechargeImaliAccount;
use App\PhoneValidation;
use App\PurchaseVoucher;
use App\ReverteImaliAccount;
use App\SendMoneyB2B;
use App\SendMoneyImaliMpesa;
use App\TransferHistory;
use App\User;
use App\Wallet;
use App\WalletFee;
use App\Water;
use App\WithDrawall;
use App\WithdrawalsRequest;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Hash;
use Webpatser\Uuid\Uuid;
use Paymentsds\MPesa\Client;
use Illuminate\Support\Facades\Storage;
use URL;
use File;
use App\AccountDeletionReason;
use App\AccountDeletionRequest;
use App\Classes\Auth;
use App\Classes\GenerateImaliAccount;
use App\Classes\PushNotification;
use App\Classes\SendResponse;
use App\Classes\UserKyc;
use App\Operator;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Session;
use App\Imali\BusinessAccount;
use App\Imali\Transfer;
use App\ImaliSubAccount;
use App\EmailValidation;
use App\Mail\ResetPinEmail;
use App\Store;
use App\SubAccountDeletionRequest;
use App\SubAccountType;
use App\TransactionHistory;
use App\UserRechargPhone;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;

class UserController extends Controller
{
    protected SmsManager $smsManager;

    public function __construct()
    {
        $this->smsManager = new SmsManager();

        $this->baseUrl = URL::to("/") . '/images/avatar/';
        $this->storagePath = public_path() . '/images/avatar';
    }

    public function getAccountDeletionRequests()
    {
        $deletionRequests = AccountDeletionRequest::query()
            ->join('account_deletion_reasons', 'account_deletion_reasons.id', 'account _deletion_requests.account_deletion_reason_id')
            ->join('imali_accounts', 'imali_accounts.account_number', 'account _deletion_requests.account_number')
            ->join('users', 'users.id', 'imali_accounts.user_id')
            ->select('users.name', 'account _deletion_requests.*', 'account_deletion_reasons.reason')
            ->orderBy('account _deletion_requests.id', 'desc')->limit(10)->get();
        return response()->json(['data' => $deletionRequests]);
    }

    public function getAccountDeletionReasons()
    {
        $reasons = AccountDeletionReason::get();
        return response()->json(['data' => $reasons]);
    }


    public function makeAccountDeletionRequest(Request $request)
    {

        $this->validate($request, [
            'account_number' => 'required',
            'account_deletion_reason_id' => 'required',
            'pin' => 'required',
        ], [
            'account_number.required' => 'Campo account_number obrigatório',
            'pin.required' => 'Campo pin obrigatório',
            'account_deletion_reason_id' => 'Campo account_deletion_reason_id obrigatório!',
        ]);

        $imaliAccount = ImaliAccount::query()->where('account_number', $request->account_number)->first();
        $user = User::query()->where('id', $imaliAccount->user_id)->first();
        if (!$imaliAccount) return response()->json(['message' => 'Conta imali inválida!'], 400);

        //Verificando se a conta que esta fazendo o pedido é a mesma que esta loggada
        if ($request->account_number != $request->user()->imaliAccount->account_number) return response()->json(['message' => 'Conta imali inválida!'], 400);

        //Validar PIN
        if (!AuthPIN::validatePIN($request->user()->id, $request->pin, $request->user()->pin)) return response()->json(['message' => 'PIN incorrecto!'], 400);
        // a conta não pode ser cancelada com saldo
        if ($imaliAccount->balance > 0) return response()->json(['message' => 'Não é possível cancelar a tua conta imali, pois ainda tem saldo disponível.'], 400);
        if ($imaliAccount->captive_balance > 0) return response()->json(['message' => 'Não é possível cancelar a tua conta imali, pois tens transaçõs por serem concluídas.'], 400);

        $imaliaccount_has_adr = AccountDeletionRequest::query()->where('account_number', $request->account_number)->first();

        if ($imaliaccount_has_adr) return response()->json(['message' => 'Esta conta ' . $request->account_number . ', já efectuou um pedido de cancelamento de conta.'], 400);

        if ($request->account_deletion_reason_id == 8) {
            $this->validate($request, [
                'commentary_reason' => 'required|min:15',
            ], [
                'commentary_reason.required' => 'Campo commentary_reason obrigatório',
                'commentary_reason.required' => 'Campo commentary_reason tem que ter no mínimo 15 caracteres',
            ]);
        }

        AccountDeletionRequest::create([
            'account_number' => $request->account_number,
            'account_deletion_reason_id' => $request->account_deletion_reason_id,
            'commentary_reason' => $request->commentary_reason,
        ]);

        $user->status = 0;
        $user->is_online = 0;
        $user->update();

        return response()->json(['message' => 'Pedido de encerramento de conta foi enviado com sucesso!'], 200);
    }

    // todo ---- 2024
    public function makeAccountDeletionRequest2024(Request $request)
    {

        $this->validate($request, [
            'account_number' => 'required',
            'account_deletion_reason_id' => 'required',
            'pin' => 'required',
        ], [
            'account_number.required' => 'Campo account_number obrigatório',
            'pin.required' => 'Campo pin obrigatório',
            'account_deletion_reason_id' => 'Campo account_deletion_reason_id obrigatório!',
        ]);

        // Buscar dados do User que faz a transacao
        // $userSender = User::getUserDetails(auth()->user()->id);

        // Buscar dados da conta do User que faz a transacao
        // $imaliAccount = User::getAccountByUser($userSender->id, $userSender->account_id);

        $imaliAccount = ImaliAccount::query()
            ->join('users', 'users.id', 'imali_accounts.user_id')
            ->where('account_number', $request->account_number)
            ->select('users.*', 'imali_accounts.*')
            ->first();

        $user = User::query()->where('id', $imaliAccount->user_id)->first();
        if (!$imaliAccount) return response()->json(['message' => 'Conta imali inválida!'], 400);

        //Verificando se a conta que esta fazendo o pedido é a mesma que esta loggada
        if ($request->account_number != $imaliAccount->account_number) return response()->json(['message' => 'Conta imali inválida!'], 400);

        //Validar PIN
        if (!AuthPIN::validatePIN($imaliAccount->id, $request->pin, $imaliAccount->pin)) return response()->json(['message' => 'PIN incorrecto!'], 400);
        // a conta não pode ser cancelada com saldo
        if ($imaliAccount->balance > 0) return response()->json(['message' => 'Não é possível cancelar a tua conta imali, pois ainda tem saldo disponível.'], 400);
        if ($imaliAccount->captive_balance > 0) return response()->json(['message' => 'Não é possível cancelar a tua conta imali, pois tens transaçõs por serem concluídas.'], 400);

        $imaliaccount_has_adr = AccountDeletionRequest::query()->where('account_number', $request->account_number)->first();

        if ($imaliaccount_has_adr) return response()->json(['message' => 'Esta conta ' . $request->account_number . ', já efectuou um pedido de cancelamento de conta.'], 400);

        if ($request->account_deletion_reason_id == 8) {
            $this->validate($request, [
                'commentary_reason' => 'required|min:15',
            ], [
                'commentary_reason.required' => 'Campo commentary_reason obrigatório',
                'commentary_reason.required' => 'Campo commentary_reason tem que ter no mínimo 15 caracteres',
            ]);
        }

        AccountDeletionRequest::create([
            'account_number' => $request->account_number,
            'account_deletion_reason_id' => $request->account_deletion_reason_id,
            'commentary_reason' => $request->commentary_reason,
        ]);

        $user->status = 0;
        $user->is_online = 0;
        $user->update();

        // return response()->json(['message' => 'Pedido de encerramento de conta foi enviado com sucesso!'], 200);

        // Redirecione para a página de sucesso ou qualquer outra página desejada
        $message = "Pedido de encerramento de conta foi enviado com sucesso!";

        if ($request->wantsJson()) {
            // return JSON-formatted response
            return response()->json(['message' => $message], 200);
        } else {
            // return HTML response
            // return view('email-not-sent', compact('message'));
            // $message = "O seu PIN foi redefinido com sucesso";
            return view('email-sent', compact('message'));
        }

        // if ($user) {
        //     return response()->json(['error' => false, 'status_code' => 200, 'message' => "Pedido de encerramento de conta foi enviado com sucesso!"], 200);
        // } else {
        //     return response()->json(['error' => true, 'status_code' => 500, 'message' => "Houve um erro a inserir os dados"], 200);
        // }
    }


    //? Aceitar pedido de cancelamento de conta
    public function acceptAccountDeletionRequest(Request $request)
    {
        $this->validate(
            $request,
            [
                'account_deletion_request_id' => 'required',
                'account_number' => 'required'
            ],
            [
                'account_deletion_request_id.required' => 'Campo account_deletion_request_id obrigatorio',
                'account_number.required' => 'Campo account_number obrigatorio'
            ]
        );

        $accountDeletionRequest = AccountDeletionRequest::query()->where('id', $request->account_deletion_request_id)
            ->where('account_number', $request->account_number)->where('status', 'pending')->first();

        if (!$accountDeletionRequest) return response()->json(['message' => 'Este pedido de cancelamento de conta nao existe'], 404);

        $imaliAccount = ImaliAccount::query()->where('account_number', $request->account_number)->first();

        if (!$imaliAccount) return response()->json(['message' => 'Este numero de conta nao existe'], 404);


        $user = User::query()->where('id', $imaliAccount->user_id)->first();

        $phone_user = PhoneValidation::query()->where('phone', $user->phone)->first();

        if ($phone_user) $phone_user->delete();

        // $token = new GenerateToken;
        // $codetoken = $token->generatePhoneNumberCode();


        $user->status = 0;
        $user->is_online = 0;
        // $user->phone = 'iMaliPhone'.$codetoken;
        // $user->email = 'iMaliEmail'.$codetoken;
        $user->update();
        $user->delete();


        $accountDeletionRequest->status = 'completed';
        $accountDeletionRequest->update();

        return response()->json(['message' => 'O pedido de cancelamento de conta foi feito com sucesso'], 200);
    }


    //? Cancelar o pedido de remocao da conta
    public function cancelAccountDeletionRequest(Request $request)
    {
        $this->validate(
            $request,
            [
                'account_deletion_request_id' => 'required',
                'account_number' => 'required'
            ],
            [
                'account_deletion_request_id.required' => 'Campo account_deletion_request_id obrigatorio',
                'account_number.required' => 'Campo account_number obrigatorio'
            ]
        );

        $accountDeletionRequest = AccountDeletionRequest::query()->where('id', $request->account_deletion_request_id)
            ->where('account_number', $request->account_number)->where('status', 'pending')->first();

        if (!$accountDeletionRequest) return response()->json(['message' => 'Este pedido de cancelamento de conta nao existe'], 404);

        $imaliAccount = ImaliAccount::query()->where('account_number', $request->account_number)->first();

        if (!$imaliAccount) return response()->json(['message' => 'Este numero de conta nao existe'], 404);


        $user = User::query()->where('id', $imaliAccount->user_id)->first();
        $user->status = 1;
        $user->update();

        $accountDeletionRequest->status = 'canceled';
        $accountDeletionRequest->update();

        return response()->json(['message' => 'O pedido de cancelado com sucesso'], 200);
    }


    //? Bloquear conta iMali
    public function blockOrEnableIMaliAccount(Request $request)
    {

        $this->validate(
            $request,
            [
                'account_number' => 'required'
            ],
            [
                'account_number.required' => 'Campo account_number obrigatorio'
            ]
        );

        $imaliAccount = ImaliAccount::query()->where('account_number', $request->account_number)->first();
        if (!$imaliAccount) return response()->json(['message' => 'Este numero de conta nao existe'], 404);

        $user = User::query()->where('id', $imaliAccount->user_id)->first();
        if (!$user) return response()->json(['message' => 'Esta conta nao existe'], 404);

        $user->status = $user->status ? 0 : 1;
        $user->update();

        return response()->json(['message' => 'Conta ' . $user->status ? 'desactivada' : 'activada' . ' com sucesso'], 200);
    }

    public function hideAndShowBalance(Request $request)
    {
        $user = User::find($request->user()->id);

        if ($user) {

            if ($user->balance_visibility == false) {
                $user->update(['balance_visibility' => true]);
                return response()->json(['message' => 'Actualizado com Sucesso para Verdadeiro'], 200);
            } else {
                $user->update(['balance_visibility' => false]);
                return response()->json(['message' => 'Actualizado com Sucesso para Falso'], 200);
            }
        } else {

            return response()->json(['message' => 'Utilizador não encontrado'], 400);
        }
    }

    public function validatePin(Request $request)
    {

        $this->validate($request, [
            'pin' => 'required|min:4'
        ]);

        if (Hash::check($request->pin, $request->user()->pin)) {
            return response()->json(['message' => 'ok'], 200);
        } else {
            return response()->json(['message' => 'Pin Incorrecto'], 405);
        }
    }

    public function getMyMonthConsuming(Request $request)
    {
        $currentMonth = date('m');
        //        $data = DB::table("items")
        //            ->whereRaw('MONTH(created_at) = ?',[$currentMonth])
        //            ->get();

        //        $data = Item::select('*')
        //            ->whereMonth('created_at', Carbon::now()->month)
        //            ->get();

        $voucher = PurchaseVoucher::query()
            ->whereRaw('MONTH(created_at) = ?', [$currentMonth])
            ->where('user_id', $request->user()->id)
            ->sum('price');

        $transfer = TransferHistory::query()
            ->whereRaw('MONTH(created_at) = ?', [$currentMonth])
            ->where('user_id', $request->user()->id)
            ->where('user_status', 'payer')
            ->sum('amount');

        $payments = Payment::query()
            ->whereRaw('MONTH(created_at) = ?', [$currentMonth])
            ->where('sender_id', $request->user()->id)
            ->sum('amount');

        $credelec = Credelec::query()
            ->whereRaw('MONTH(created_at) = ?', [$currentMonth])
            ->where('user_id', $request->user()->id)
            ->sum('amount');

        $water = Water::query()
            ->whereRaw('MONTH(created_at) = ?', [$currentMonth])
            ->where('user_id', $request->user()->id)
            ->sum('purchaseValue');


        return response()->json(['water' => $water, 'voucher' => $voucher, 'transfer' => $transfer, 'payments' => $payments, 'credelec' => $credelec]);
    }

    public function getUser()
    {
        //        $user = User::query()
        //            ->join('imali_accounts', 'imali_accounts.user_id', '=', 'users.id')
        //            ->where('users.id', auth()->user()->id)
        //            ->select('users.*', 'imali_accounts.account_number', 'imali_accounts.balance', 'imali_accounts.points', 'imali_accounts.account_number', 'imali_accounts.reference')
        //            ->first();

        //$user = ImaliAccount::query()
        //  ->join('users', 'imali_accounts.user_id', '=', 'users.id')
        //  ->join('imali_account_configs', 'imali_accounts.imali_account_config', '=', 'imali_account_configs.id')
        //  ->where('users.id', auth()->user()->id)
        //  ->select('users.*', 'imali_accounts.account_number', 'imali_accounts.balance', 'imali_accounts.points', 'imali_accounts.account_number', 'imali_accounts.reference', 'imali_account_configs.nr_transaction', 'imali_account_configs.max_value_operation', 'imali_account_configs.level')
        //  ->first();

        // $user->makeHidden(['id', 'profile', 'password', 'pin', 'firebase_token', 'created_at', 'updated_at'
        //     , 'phone_reference', 'user_id', 'bi', 'document_id', 'remember_token', 'email_verified_at']);

        $user = User::getUserAccount();

        return response()->json($user);
    }

    public function getMyImaliAccount($id)
    {

        $imali = ImaliAccount::query()->where('user_id', $id)->first();
        return response()->json($imali);
    }

    public function rechargeByReference(Request $request)
    {

        $imaliAccount = User::getAccount($request->reference);
        $user = User::getUserDetails($imaliAccount->user_id);

        // $imaliAccount = ImaliAccount::query()->where('reference', $request->reference)->first();
        $transactionString = new TransactionGeneration();

        // $user = ImaliAccount::query()->join('users', 'users.id', '=', 'imali_accounts.user_id')
        //     ->where('users.id', $imaliAccount->user_id)
        //     ->select('users.*', 'imali_accounts.account_number')
        //     ->first();

        if ($user->profile === 'business') {

            $kyckCheck = false;
        } else {

            $kyc = new Kyc();
            $kyckCheck = $kyc->checkRecharge($request);
        }

        // Get User Authenticated
        $auth_user = User::getUserAccount();



        if ($kyckCheck) {
            return $kyckCheck;
        } else {
            if ($imaliAccount) {
                $balanceActual = $imaliAccount->balance + $request->amount;

                $masterAccount = MasterAccount::find(2);
                $recharge = RechargeImaliAccount::create([
                    'imali_account_id' => $imaliAccount->id,
                    'transaction_id' => $transactionString->generateTransaction(),
                    'description' => $request->description,
                    'amount' => $request->amount,
                    'last_balance' => $imaliAccount->balance,
                    'balance' => $balanceActual,
                    'account_reference' => $request->reference,
                    'recharge_way' => 'Agente i.Mali 0001',
                    'estado' => 'sucesso',
                    'estado_color' => '#388E3C',
                    'master_account_id' => $masterAccount->id,
                    'user_id' => $auth_user->id
                ]);

                $masterBalance = $masterAccount->balance + $request->amount;

                $masterAccount->update(['balance' => $masterBalance]);

                if ($recharge) {

                    $imaliAccount->update(['balance' => $balanceActual]);

                    $notification = array(
                        'icon' => 'ic_imali_logo_verde_01',
                        // 'icon' => 'ic_i_mali_cover',
                        'title' => 'Carregamento ' . $recharge->amount . ' MT',
                        'body' => 'Parabéns, ' . 'carregaste ' . $recharge->amount . ' MT ' . ' na tua conta ' . $imaliAccount->account_number,
                        'click_action' => 'com.imali.payapp.payment_RECHARGE_DETAILS',
                        //                            'color' => '#008577'
                        'color' => '#ffffff'
                    );

                    $data = array(
                        'transaction' => $recharge->transaction_id,
                        'name' => $user->name,
                        'description' => $request->description,
                        'amount' => (float)$recharge->amount,
                        'phone' => $user->phone,
                        'reference' => $imaliAccount->reference,
                        'data' => $recharge->created_at,
                        'estado' => $recharge->estado,
                        'route' => 'RECHARGE_DETAILS',
                        'recharge_way' => $recharge->recharge_way,
                        'account_number' => $user->account_number,
                        'terminal' => 'firebase'
                    );


                    $this->pushNotifification($user->firebase_token, $notification, $data);
                    //$this->smsManager->sendSMSForUserRecharge($recharge);
                }

                if ($recharge) {
                    //                    Mail::to($user->email)->send(new Carregamento($recharge));
                }
                $log = new Record();
                $log->createLog([
                    'description' => $imaliAccount->account_number,
                    'details' => $user->name . ' ' . $user->last_name,
                    'operation' => 'Recharge by Reference',
                    'status' => 'success',
                    'user_id' => $request->user()->id
                ]);

                if ($recharge) {
                    return response()->json(['message' => 'Carregamento, feito com Sucesso'], 200);
                }
            }

            ////////
        }
    }

    public function rechargeByReference2(Request $request)
    {
        //        return $request->all();
        foreach ($request->contentData as $requestData) {
            $imaliAccount = ImaliAccount::query()->where('reference', $requestData['payment_reference'])->first();
            $transactionString = new TransactionGeneration();

            if ($imaliAccount) {

                $user = ImaliAccount::query()->join('users', 'users.id', '=', 'imali_accounts.user_id')
                    ->where('users.id', $imaliAccount->user_id)
                    ->select('users.*')
                    ->first();

                $balanceActual = $imaliAccount->balance + $requestData['paid_amount'];

                $masterAccount = MasterAccount::find(2);
                $recharge = RechargeImaliAccount::create([
                    'imali_account_id' => $imaliAccount->id,
                    'transaction_id' => $transactionString->generateTransaction(),
                    'amount' => $requestData['paid_amount'],
                    'bank_date' => $requestData['datetime_of_transaction'],
                    'account_reference' => $requestData['payment_reference'],
                    'last_balance' => $imaliAccount->balance,
                    'balance' => $balanceActual,
                    'recharge_way' => $requestData['terminal_locality'] ? $requestData['terminal_locality'] : 'SIMO REDE',
                    'estado' => 'sucesso',
                    'estado_color' => '#388E3C',
                    'master_account_id' => $masterAccount->id,
                    'content_id' => $requestData['content_id']
                ]);

                $masterBalance = $masterAccount->balance + $requestData['paid_amount'];

                $masterAccount->update(['balance' => $masterBalance]);

                if ($recharge) {

                    $imaliAccount->update(['balance' => $balanceActual]);

                    $notification = array(
                        'icon' => 'ic_imali_logo_verde_01',
                        //                        'icon' => 'ic_i_mali_cover',
                        'title' => 'Carregamento ' . $recharge->amount . ' MT',
                        'body' => 'Parabéns, ' . 'carregaste com ' . $recharge->amount . ' MT ' . ' na tua conta ' . $imaliAccount->account_number,
                        //                        'click_action' => 'com.imali.payapp.payment_TRANSFER_DETAILS',
                        'click_action' => 'com.imali.payapp.payment_RECHARGE_DETAILS',
                        //                            'color' => '#008577'
                        'color' => '#ffffff'
                    );
                    $data = array(
                        'transaction' => $recharge->transaction_id,
                        'name' => $user->name,
                        'amount' => (float)$recharge->amount,
                        'phone' => $user->phone,
                        'reference' => $imaliAccount->reference,
                        'data' => $recharge->created_at,
                        'estado' => $recharge->estado,
                        'route' => 'RECHARGE_DETAILS',
                        'recharge_way' => $recharge->recharge_way,
                        'terminal' => 'firebase'
                    );


                    $this->pushNotifification($user->firebase_token, $notification, $data);
                    $this->smsManager->sendSMSForUserRecharge($recharge);
                }

                //                if ($recharge) {
                ////                    Mail::to($user->email)->send(new Carregamento($recharge));
                //                }
                //                    $log = new Record();
                //                    $log->createLog([
                //                        'description' => $imaliAccount->account_number,
                //                        'details' => $user->name . ' ' . $user->last_name,
                //                        'operation' => 'Recharge by Reference',
                //                        'status' => 'success',
                //                        'user_id' => $request->user()->id
                //                    ]);

                if ($recharge) {
                    //                    return response()->json(['message' => 'Carregamento, feito com Sucesso'], 200);
                }
            } else {
                //                 PendingRecharge::create([
                //                     'reference' => $requestData['payment_reference'],
                //                     'amount' => $requestData['paid_amount'],
                //                     'content_id' => $requestData['content_id']
                // //                    'content_id' => $request->content_id
                //                 ]);

                $recharge = RechargeImaliAccount::create([
                    'imali_account_id' => 0,
                    'transaction_id' => $transactionString->generateTransaction(),
                    'amount' => $requestData['paid_amount'],
                    'account_reference' => $requestData['payment_reference'],
                    'bank_date' => $requestData['datetime_of_transaction'],
                    'last_balance' => 0,
                    'balance' => 0,
                    'recharge_way' => $requestData['terminal_locality'],
                    'estado' => 'falhou',
                    'estado_color' => '#388E3C',
                    'master_account_id' => 0,
                    'content_id' => $requestData['content_id']
                ]);

                //                return response()->json(['message' => 'Referencia inválida'], 400);
            }

            //            $kyc = new Kyc();
            ////            $kyckCheck = $kyc->checkRecharge($request);
            //            $kyckCheck = $kyc->checkRechargeByBank($requestData);
            //
            //            if ($kyckCheck) {
            //                return $kyckCheck;
            //            } else {
            //
            //
            //            }
        }
        return response()->json(['message' => 'Carregamento, feito com Sucesso'], 200);
    }

    public function rechargeByReferenceNew25(Request $request)
    {
        $this->validate(
            $request,
            [
                'reference' => 'required|exists:imali_accounts,reference|digits:11',
                'amount' => 'required|numeric|min:10',
                'recharge_way' => 'required|in:MPESA,EMOLA,MKESH,SIMO_REDE,IMALI',
            ],
            [
                'amount.required' => 'Campo amount é obrigatório',
                'recharge_way.required' => 'Campo recharge_way é obrigatório',
                'amount.min' => 'O valor minimo deve ser 10MT',
                'amount.numeric' => 'Campo Montente deve ser númerico',

                'reference.required' => 'Campo reference é obrigatório',
                'recharge_way.in' => 'Campo recharge_way tem que estar entre:MPESA,EMOLA,MKESH,SIMO_REDE,IMALI',
                'reference.digits' => 'Campo reference deve ter no maximo 9 digitos',
                'reference.exists' => 'A referencia nao existe',
            ]
        );

        $imaliAccount = User::getAccount($request->reference);
        if (!$imaliAccount) return SendResponse::errorResp404notfound('Referencia nao encontrada', 'Reference not found');

        $user = User::getUserDetails($imaliAccount->user_id);
        if (!$user) return SendResponse::errorResp404notfound('User da conta nao encontrada', 'User Account not found');

        $transactionString = new TransactionGeneration();

        $balanceActual = $imaliAccount->balance + $request->amount;

        $masterAccount = MasterAccount::find(2);
        $recharge = RechargeImaliAccount::create([
            'imali_account_id' => $imaliAccount->id,
            'transaction_id' => $transactionString->generateTransaction(),
            'description' => $request->description,
            'amount' => $request->amount,
            'last_balance' => $imaliAccount->balance,
            'balance' => $balanceActual,
            'recharge_way' => $request->recharge_way,
            'pending_recharge_id' => $request->pending_recharges_id,
            'estado' => 'sucesso',
            'estado_color' => '#388E3C',
            'master_account_id' => $masterAccount->id,
            'user_id' => $user->id
        ]);

        $masterBalance = $masterAccount->balance + $request->amount;

        $masterAccount->update(['balance' => $masterBalance]);

        $imaliAccount->update(['balance' => $balanceActual]);

        $data = array(
            'transaction' => $recharge->transaction_id,
            'name' => $user->name,
            'description' => $request->description,
            'amount' => (float)$recharge->amount,
            'phone' => $user->phone,
            'reference' => $imaliAccount->reference,
            'data' => $recharge->created_at,
            'estado' => $recharge->estado,
            'route' => 'RECHARGE_DETAILS',
            'recharge_way' => $recharge->recharge_way,
            'account_number' => $user->account_number,
            'terminal' => 'firebase'
        );

        $push = new PushNotification(
            'Carregamento ' . $recharge->amount . ' MT',
            'Parabéns, ' . 'carregaste ' . $recharge->amount . ' MT ' . ' na tua conta ' . $imaliAccount->account_number,
            $user->firebase_token,
            'com.imali.payapp.payment_RECHARGE_DETAILS',
            '',
            'ic_imali_logo_verde_01'
        );
        $push->sendPush($data);

        return response()->json(['message' => 'Carregamento, feito com Sucesso'], 200);
    }



    public function rechargeAccount2(Request $request)
    {
        $transactionString = new TransactionGeneration();

        $public_key = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmptSWqV7cGUUJJhUBxsMLonux24u+FoTlrb+4Kgc6092JIszmI1QUoMohaDDXSVueXx6IXwYGsjjWY32HGXj1iQhkALXfObJ4DqXn5h6E8y5/xQYNAyd5bpN5Z8r892B6toGzZQVB7qtebH4apDjmvTi5FGZVjVYxalyyQkj4uQbbRQjgCkubSi45Xl4CGtLqZztsKssWz3mcKncgTnq3DHGYYEYiKq0xIj100LGbnvNz20Sgqmw/cH+Bua4GJsWYLEqf/h/yiMgiBbxFxsnwZl0im5vXDlwKPw+QnO2fscDhxZFAwV06bgG0oEoWm9FnjMsfvwm0rUNYFlZ+TOtCEhmhtFp+Tsx9jPCuOd5h2emGdSKD8A6jtwhNa7oQ8RtLEEqwAn44orENa1ibOkxMiiiFpmmJkwgZPOG/zMCjXIrrhDWTDUOZaPx/lEQoInJoE2i43VN/HTGCCw8dKQAwg0jsEXau5ixD0GUothqvuX3B9taoeoFAIvUPEq35YulprMM7ThdKodSHvhnwKG82dCsodRwY428kg2xM/UjiTENog4B6zzZfPhMxFlOSFX4MnrqkAS+8Jamhy1GgoHkEMrsT5+/ofjCx0HjKbT5NuA2V/lmzgJLl3jIERadLzuTYnKGWxVJcGLkWXlEPYLbiaKzbJb2sYxt+Kt5OxQqC1MCAwEAAQ==";
        $api_host = "api.sandbox.vm.co.mz";
        $api_key = "40dtaa0qj1xcw1rwytyszgq83lp523m0";
        $origin = "*";
        $service_provider_code = "171717";

        $config = new \abdulmueid\mpesa\Config($public_key, $api_host, $api_key, $origin, $service_provider_code, '', '');
        $transaction = new \abdulmueid\mpesa\Transaction($config);
        $msisdn = '258' . $request->phone;
        $amount = $request->amount;
        $reference = 'T12344C';
        //        $third_party_reference = '111PA2D';
        $third_party_reference = $transactionString->generateTransaction();

        $user = User::query()->where('user_id', $request->user_id)->first();

        $imaliAccount = ImaliAccount::query()->where('user_id', $user->id)->first();

        if ($imaliAccount) {
            $payment = $transaction->payment($msisdn, $amount, $reference, $third_party_reference);
            if ($payment->getCode() == 'INS-0') {
                if ($imaliAccount) {
                    $balanceActual = $imaliAccount->balance + $request->amount;

                    $masterAccount = MasterAccount::find(1);
                    $recharge = RechargeImaliAccount::create([
                        'imali_account_id' => $imaliAccount->id,
                        'transaction_id' => $transactionString->generateTransaction(),
                        'amount' => $request->amount,
                        'last_balance' => $imaliAccount->balance,
                        'balance' => $balanceActual,
                        'recharge_way' => 'M-pesa' . $request->phone,
                        'estado' => 'sucesso',
                        'estado_color' => '#388E3C',
                        'master_account_id' => $masterAccount->id
                    ]);


                    $masterBalance = $masterAccount->balance + $request->amount;

                    $masterAccount->update(['balance' => $masterBalance]);

                    if ($recharge) {
                        $imaliAccount->update(['balance' => $balanceActual]);

                        $log = new Record();
                        $log->createLog([
                            'description' => $imaliAccount->account_number . '  ' . $user->name . ' ' . $user->last_name,
                            'details' => 'Carregamento, feito com Sucesso',
                            'operation' => 'Recharge by M-pesa',
                            'status' => 'success',
                            'user_id' => $request->user()->id
                        ]);
                        return response()->json(['message' => 'Carregamento, feito com Sucesso', 'code' => ''], 200);
                    }
                }
            }
            if ($payment->getCode() == 'INS-2006') {

                $log = new Record();
                $log->createLog([
                    'description' => $imaliAccount->account_number . ' ' . $user->name . ' ' . $user->last_name,
                    'details' => 'Saldo Insuficiente',
                    'operation' => 'Recharge by M-pesa',
                    'status' => 'Error',
                    'user_id' => $request->user()->id
                ]);

                return response()->json(['message' => 'Saldo Insuficiente'], 422);
            }
            if ($payment->getCode() == 'INS-9') {

                $log = new Record();
                $log->createLog([
                    'description' => $imaliAccount->account_number . ' ' . $user->name . ' ' . $user->last_name,
                    'details' => 'Excedeu o tempo limite de transacção',
                    'operation' => 'Recharge by M-pesa',
                    'status' => 'Error',
                    'user_id' => $request->user()->id
                ]);

                return response()->json(['message' => 'Excedeu o tempo limite de transacção'], 408);
            }
            if ($payment->getCode() == 'INS-9') {

                $log = new Record();
                $log->createLog([
                    'description' => $imaliAccount->account_number . ' ' . $user->name . ' ' . $user->last_name,
                    'details' => 'Valor inválido',
                    'operation' => 'Recharge by M-pesa',
                    'status' => 'Error',
                    'user_id' => $request->user()->id
                ]);

                return response()->json(['message' => 'Valor inválido'], 400);
            }
            if ($payment->getCode() == 'INS-995') {


                $log = new Record();
                $log->createLog([
                    'description' => $imaliAccount->account_number . ' ' . $user->name . ' ' . $user->last_name,
                    'details' => 'Conta Mpesa com Problemas',
                    'operation' => 'Recharge by M-pesa',
                    'status' => 'Error',
                    'user_id' => $request->user()->id
                ]);

                return response()->json(['message' => 'Conta Mpesa com Problemas'], 400);
            }
            if ($payment->getCode() == 'INS-996') {

                $log = new Record();
                $log->createLog([
                    'description' => $imaliAccount->account_number . ' ' . $user->name . ' ' . $user->last_name,
                    'details' => 'Este número nao tem conta Mpesa',
                    'operation' => 'Recharge by M-pesa',
                    'status' => 'Error',
                    'user_id' => $request->user()->id
                ]);

                return response()->json(['message' => 'Este número nao tem conta Mpesa'], 400);
            }
        }
    }

    public function rechargeAccount(Request $request)
    {
        $transactionString = new TransactionGeneration();

        $public_key = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmptSWqV7cGUUJJhUBxsMLonux24u+FoTlrb+4Kgc6092JIszmI1QUoMohaDDXSVueXx6IXwYGsjjWY32HGXj1iQhkALXfObJ4DqXn5h6E8y5/xQYNAyd5bpN5Z8r892B6toGzZQVB7qtebH4apDjmvTi5FGZVjVYxalyyQkj4uQbbRQjgCkubSi45Xl4CGtLqZztsKssWz3mcKncgTnq3DHGYYEYiKq0xIj100LGbnvNz20Sgqmw/cH+Bua4GJsWYLEqf/h/yiMgiBbxFxsnwZl0im5vXDlwKPw+QnO2fscDhxZFAwV06bgG0oEoWm9FnjMsfvwm0rUNYFlZ+TOtCEhmhtFp+Tsx9jPCuOd5h2emGdSKD8A6jtwhNa7oQ8RtLEEqwAn44orENa1ibOkxMiiiFpmmJkwgZPOG/zMCjXIrrhDWTDUOZaPx/lEQoInJoE2i43VN/HTGCCw8dKQAwg0jsEXau5ixD0GUothqvuX3B9taoeoFAIvUPEq35YulprMM7ThdKodSHvhnwKG82dCsodRwY428kg2xM/UjiTENog4B6zzZfPhMxFlOSFX4MnrqkAS+8Jamhy1GgoHkEMrsT5+/ofjCx0HjKbT5NuA2V/lmzgJLl3jIERadLzuTYnKGWxVJcGLkWXlEPYLbiaKzbJb2sYxt+Kt5OxQqC1MCAwEAAQ==";
        $api_host = "api.sandbox.vm.co.mz";
        $api_key = "40dtaa0qj1xcw1rwytyszgq83lp523m0";
        $origin = "*";
        $service_provider_code = "171717";

        $reference = 'T12344C';

        $third_party_reference = $transactionString->generateTransaction();


        $client = new Client([
            'apiKey' => $api_key,             // API Key
            'publicKey' => $public_key,          // Public Key
            'serviceProviderCode' => $service_provider_code // input_ServiceProviderCode
        ]);

        $paymentData = [
            //            'from' => '+258845030902',       // input_CustomerMSISDN
            'from' => '258' . $request->phone,       // input_CustomerMSISDN
            //            'from' => $request->phone,       // input_CustomerMSISDN
            'reference' => '111PA2D',      // input_ThirdPartyReference
            'transaction' => $third_party_reference, // input_TransactionReference
            'amount' => $request->amount             // input_Amount
        ];


        $user = User::query()->where('user_id', $request->user_id)->first();

        $imaliAccount = ImaliAccount::query()->where('user_id', $user->id)->first();

        if ($imaliAccount) {
            //            $payment = $transaction->payment($msisdn, $amount, $reference, $third_party_reference);

            //            $results = $client->receive($paymentData);
            $results = $client->receive($paymentData);

            if ($results->success) {
                // Handle success
                //                if ($result->getCode() == 'INS-0') {
                //                return response()->json($result);
                if ($imaliAccount) {
                    $balanceActual = $imaliAccount->balance + $request->amount;

                    $masterAccount = MasterAccount::find(1);
                    $recharge = RechargeImaliAccount::create([
                        'imali_account_id' => $imaliAccount->id,
                        'transaction_id' => $transactionString->generateTransaction(),
                        'amount' => $request->amount,
                        'last_balance' => $imaliAccount->balance,
                        'balance' => $balanceActual,
                        'recharge_way' => 'M-pesa' . $request->phone,
                        'estado' => 'sucesso',
                        'estado_color' => '#388E3C',
                        'master_account_id' => $masterAccount->id
                    ]);


                    $masterBalance = $masterAccount->balance + $request->amount;

                    $masterAccount->update(['balance' => $masterBalance]);

                    if ($recharge) {
                        $imaliAccount->update(['balance' => $balanceActual]);

                        $log = new Record();
                        $log->createLog([
                            'description' => $imaliAccount->account_number . '  ' . $user->name . ' ' . $user->last_name,
                            'details' => 'Carregamento, feito com Sucesso',
                            'operation' => 'Recharge by M-pesa',
                            'status' => 'success',
                            'user_id' => $request->user()->id
                        ]);

                        return response()->json(['message' => 'Carregamento, feito com Sucesso', 'code' => ''], 200)->header('Content-Type', 'application/json');
                    }
                }

                //                }
            } else {
                //                return response()->json($result);
                // Handle failure

                //                if ($result->getCode() == 'INS-2006') {
                //
                //                    $log = new Record();
                //                    $log->createLog([
                //                        'description' => $imaliAccount->account_number . ' ' . $user->name . ' ' . $user->last_name,
                //                        'details' => 'Saldo Insuficiente',
                //                        'operation' => 'Recharge by M-pesa',
                //                        'status' => 'Error',
                //                        'user_id' => $request->user()->id
                //                    ]);
                //
                //                    return response()->json(['message' => 'Saldo Insuficiente'], 422);
                //                }
                //                if ($result->getCode() == 'INS-9') {
                //
                //                    $log = new Record();
                //                    $log->createLog([
                //                        'description' => $imaliAccount->account_number . ' ' . $user->name . ' ' . $user->last_name,
                //                        'details' => 'Excedeu o tempo limite de transacção',
                //                        'operation' => 'Recharge by M-pesa',
                //                        'status' => 'Error',
                //                        'user_id' => $request->user()->id
                //                    ]);
                //
                //                    return response()->json(['message' => 'Excedeu o tempo limite de transacção'], 408);
                //                }
                //                if ($result->getCode() == 'INS-9') {
                //
                //                    $log = new Record();
                //                    $log->createLog([
                //                        'description' => $imaliAccount->account_number . ' ' . $user->name . ' ' . $user->last_name,
                //                        'details' => 'Valor inválido',
                //                        'operation' => 'Recharge by M-pesa',
                //                        'status' => 'Error',
                //                        'user_id' => $request->user()->id
                //                    ]);
                //
                //                    return response()->json(['message' => 'Valor inválido'], 400);
                //                }
                //                if ($result->getCode() == 'INS-995') {
                //
                //
                //                    $log = new Record();
                //                    $log->createLog([
                //                        'description' => $imaliAccount->account_number . ' ' . $user->name . ' ' . $user->last_name,
                //                        'details' => 'Conta Mpesa com Problemas',
                //                        'operation' => 'Recharge by M-pesa',
                //                        'status' => 'Error',
                //                        'user_id' => $request->user()->id
                //                    ]);
                //
                //                    return response()->json(['message' => 'Conta Mpesa com Problemas'], 400);
                //                }
                //                if ($result->getCode() == 'INS-996') {
                //
                //                    $log = new Record();
                //                    $log->createLog([
                //                        'description' => $imaliAccount->account_number . ' ' . $user->name . ' ' . $user->last_name,
                //                        'details' => 'Este número nao tem conta Mpesa',
                //                        'operation' => 'Recharge by M-pesa',
                //                        'status' => 'Error',
                //                        'user_id' => $request->user()->id
                //                    ]);
                //
                //                    return response()->json(['message' => 'Este número nao tem conta Mpesa'], 400);
                //                }
            }
        }
    }


    public function bankConnections()
    {
        $banks = BankConection::all();

        return response()->json(['data' => $banks], 200);
    }

    public function users()
    {
        $users = User::all();
        return response()->json(['data' => $users], 200);
    }


    public function resendCode(Request $request)
    {
        $token = new GenerateToken();

        $data = ['phone' => $request->phone, 'signature' => $request->signature, 'codigo' => $token->generatePhoneNumberCode()];

        $this->smsManager->smsVerifyUser($data);
        $validate = PhoneValidation::query()->where('phone', $request->phone)->count();

        $convert = strtotime(date('Y-m-d H:i:s')) + (60 * 10);
        $duration = date("Y-m-d H:i:s", $convert);

        if ($validate === 0) {
            $save = PhoneValidation::create([
                'phone' => $request->phone,
                'country_code' => $request->country_code,
                'expire_at' => $duration,
                'duration' => 5,
                'codigo' => $data['codigo'],
                'is_Validated' => 0
            ]);
            if ($save) {

                $log = new Record();
                $log->createLog([
                    'description' => $request->phone . '  ' . $data['codigo'],
                    'details' => 'Código de Verificação enviado com sucesso!',
                    'operation' => 'Resend Verification code',
                    'status' => 'Success',
                    'user_id' => $request->user()->id
                ]);

                return response()->json(['message' => 'Código de Verificação enviado com sucesso!'], 200);
            }
        } else {
            $validate = PhoneValidation::query()->where('phone', $request->phone)->first();
            $save = $validate->update(['codigo' => $data['codigo'], 'expire_at' => $duration]);
            if ($save) {
                $data = ['phone' => $request->phone, 'signature' => $request->signature, 'codigo' => $validate->codigo];
                return response()->json(['message' => 'Código de Verificação reenviado com sucesso!'], 200);
            }
        }
    }


    public function resendCodeOld(Request $request)
    {
        $token = new GenerateToken();


        $validate = PhoneValidation::query()->where('phone', $request->phone)->count();
        $phoneValidate = PhoneValidation::query()->where('phone', $request->phone)->first();

        if ($validate === 0) {
            $data = ['phone' => $request->phone, 'codigo' => $token->generatePhoneNumberCode()];
            $sms = new  SendSMS();
            $save = PhoneValidation::create([
                'phone' => $request->phone,
                'expire_at' => now(),
                'duration' => 5,
                'codigo' => $data['codigo'],
                'is_Validated' => 1
            ]);
            $sent = $sms->verifyUser($data);
            if ($save) {

                $log = new Record();
                $log->createLog([
                    'description' => $request->phone . '  ' . $data['codigo'],
                    'details' => 'Código de Verificação enviado com sucesso!',
                    'operation' => 'Resend Verification code',
                    'status' => 'Success',
                    'user_id' => $request->user()->id
                ]);

                return response()->json(['message' => 'Código de Verificação enviado com sucesso!'], 200);
            }
        } else {
            $validate = PhoneValidation::query()->where('phone', $request->phone)->first();
            //            $save = $validate->update(['codigo' => $data['codigo']]);
            if ($validate) {
                $data = ['phone' => $request->phone, 'codigo' => $validate->phone];
                $sms = new  SendSMS();
                $sms->verifyUser($data);
                return response()->json(['message' => 'Código de Verificação reenviado com sucesso!', 'codigo' => $data['codigo']], 200);
            }
        }
    }


    public function verifyUserNumber(Request $request)
    {
        //        $firstReplace= str_replace(' ', '',$request->phone);
        //        $request['phone'] = str_replace('-', '',$firstReplace);

        $this->validate($request, [
            'name' => 'required',
            'phone' => 'required|unique:users|min:9',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:8',
            'last_name' => 'required',
            //'bi' => 'required|min:13'
        ], [
            'email.required' => 'O Campo Email é de carácter Obrigatório',
            'email.unique' => 'Este Email já está em uso',
            'phone.required' => 'O Número do celular é obrigatório',
            'phone.unique' => 'O Número do celular já está em uso',
            'phone.min' => 'O Campo Celular deve ter 9 dígitos',
            'name.required' => 'O Campo Nome é obrigatório',
            'last_name.required' => 'O Campo Apelido é obrigatório',
            //'bi.required' => 'O campo Bi é Obrigatório',
            //            'bi.min'=>'O campo Bi ter 13 dígitos',
            'password.required' => 'O Campo Senha é obrigatório',
            //'password.confirmed' => 'Senhas incompatíveis',
            'password.min' => 'A senha deve ter 8 digitos no mínimo'
        ]);

        $token = new GenerateToken();
        $data = ['phone' => $request->phone, 'signature' => $request->signature, 'codigo' => $token->generatePhoneNumberCode()];

        //?Temporario
        //$this->smsManager->smsVerifyUser($data);

        try {
            //code...
            $this->smsManager->smsVerifyUser($data);
        } catch (\Throwable $th) {
            //throw $th;
            Log::info('Outgoing Response', [
                'content' => $th->getMessage(),
                'error_line' => $th->getLine(),
                'error_file' => $th->getFile(),
            ]);

            SendResponse::warningResp500serverError('Serviço de SMS indisponível', 'SMS service unavailable');
        }

        //$validate = PhoneValidation::query()->where('phone', $request->phone)->where('is_Validated', 0)->count();
        $validate = PhoneValidation::query()->where('phone', $request->phone)->count();

        $convert = strtotime(date('Y-m-d H:i:s')) + (60 * 10);
        $duration = date("Y-m-d H:i:s", $convert);


        if ($validate === 0) {
            $save = PhoneValidation::create([
                'phone' => $request->phone,
                'country_code' => $request->country_code,
                'expire_at' => $duration,
                'duration' => 5,
                'codigo' => $data['codigo'],
                'is_Validated' => 0
            ]);
            if ($save) {

                //$log = new Record();
                //$log->createLog([
                //    'description' => $request->phone . '  ' . $data['codigo'],
                //    'details' => 'Código de Verificação enviado com sucesso!',
                //    'operation' => 'Resend Verification code',
                //    'status' => 'Success',
                //    'user_id' => $request->user()->id
                //]);

                return response()->json(['message' => 'Codigo de Verificação enviado com sucesso!'], 200);
            }
        } else {
            $validate = PhoneValidation::query()->where('phone', $request->phone)->first();
            $save = $validate->update(['codigo' => $data['codigo'], 'expire_at' => $duration]);
            if ($save) {
                $data = ['phone' => $request->phone, 'signature' => $request->signature, 'codigo' => $validate->codigo];
                return response()->json(['message' => 'Codigo de Verificação enviado com sucesso!', 'codigo' => $data['codigo']], 200);
            }
        }
    }

    public function sendSMSToken(Request $request)
    {
        try {
            $this->validate($request, [
                'phone' => 'required|unique:users|min:9',
            ], [
                'phone.required' => 'O Número do celular é obrigatório',
                'phone.unique' => 'O Número do celular já está em uso',
                'phone.min' => 'O Campo Celular deve ter 9 dígitos',
            ]);
        } catch (ValidationException $ve) {
            return response()->json([
                'message' => $ve->getMessage(),
                'errors' => $ve->errors()
            ], 400);
        }

        $token = new GenerateToken();
        $data = ['phone' => $request->phone, 'signature' => $request->signature, 'codigo' => $token->generatePhoneNumberCode()];

        $this->smsManager->smsVerifyUser($data);
        $validate = PhoneValidation::query()->where('phone', $request->phone)->count();

        $convert = strtotime(date('Y-m-d H:i:s')) + (60 * 10);
        $duration = date("Y-m-d H:i:s", $convert);

        if ($validate === 0) {
            $save = PhoneValidation::create([
                'phone' => $request->phone,
                'country_code' => $request->country_code,
                'expire_at' => $duration,
                'duration' => 2,
                'codigo' => $data['codigo'],
                'is_Validated' => 0
            ]);
            if ($save) {
                return response()->json(['message' => 'Código de Verificação enviado com sucesso!'], 200);
            }
        } else {
            $validate = PhoneValidation::query()->where('phone', $request->phone)->first();
            $save = $validate->update(['codigo' => $data['codigo'], 'expire_at' => $duration]);
            if ($save) {
                $data = ['phone' => $request->phone, 'signature' => $request->signature, 'codigo' => $validate->codigo];
                return response()->json(['message' => 'Código de Verificação reenviado com sucesso!'], 200);
            }
        }
    }

    public function checkCodigo(Request $request)
    {

        $this->validate($request, [
            'phone' => 'required|unique:users|min:9',
            'codigo' => 'required|min:6'
        ], [
            'phone.required' => 'O Número do celular é obrigatório',
            'phone.unique' => 'O Número do celular já está em uso',
            'phone.min' => 'O Campo Celular deve ter 9 dígitos',
            'codigo.required' => 'O campo codigo é Obrigatório',
            'codigo.min' => 'O campo codigo ter 6 dígitos',
        ]);

        try {

            $validate = PhoneValidation::query()->where('phone', $request->phone)->where('codigo', $request->codigo)->first();
            //return $validate;

            if (!$validate) return response()->json(['message' => "Token invalido"], 400);

            $is_expired = strtotime($validate->expire_at) - strtotime(date('Y-m-d H:i:s'));

            if ($is_expired < 0) return response()->json(['message' => "Token expirado"], 400);

            $convert = strtotime(date('Y-m-d H:i:s')) - (60 * 10);
            $duration = date("Y-m-d H:i:s", $convert);

            $validate->is_Validated = 1;
            $validate->expire_at = $duration;
            $validate->update();

            $log = new Record();
            $log->createLog([
                'description' => $request->phone,
                'details' => 'Celular Verificado com Successo!',
                'operation' => 'Check Phone Validation',
                'status' => 'Success',
                'user_id' => 1
            ]);

            return response()->json(['message' => 'Celular Verificado com Successo!'], 200);
        } catch (\Exception $exception) {
            return response()->json($exception);
        }
    }

    public function checkCodigOld(Request $request)
    {
        try {

            $validate = PhoneValidation::query()->where('phone', $request->phone)->where('codigo', $request->codigo)->where('is_Validated', 0)->first();
            //$validate = PhoneValidation::query()->where('phone', $request->phone)->where('codigo', $request->codigo)->count();

            if ($validate) {

                $validate->is_Validated = 1;
                $validate->update();

                $log = new Record();
                $log->createLog([
                    'description' => $request->phone,
                    'details' => 'Celular Verificado com Successo!',
                    'operation' => 'Check Phone Validation',
                    'status' => 'Success',
                    'user_id' => 1
                ]);
                return response()->json(['message' => 'Celular Verificado com Successo!'], 200);
            } else {

                $log = new Record();
                $log->createLog([
                    'description' => $request->phone,
                    'details' => 'Código inválido',
                    'operation' => 'Check Phone Validation',
                    'status' => 'Error',
                    'user_id' => 1
                ]);

                return response()->json(['message' => 'Código inválido'], 400);
            }
        } catch (Exception $exception) {
            return response()->json($exception);
        }
    }

    public function getUsers()
    {
        return response()->json(['users' => User::all()]);
    }

    public function getImaliAccounts(Request $request)
    {
        $perPage = !!$request->input('per_page') ? $request->input('per_page') : 10;
        $orderType = $request->input('order_type') === 'ASC' ? 'ASC' : 'DESC';
        $orderBy = !!$request->input('order_by') && $request->input('order_by') !== 'null' ? $request->input('order_by') : 'users.id';

        $users = User::query()
            ->with([
                'imaliAccount' => function ($imali) {
                    return $imali->join('imali_account_configs', 'imali_account_configs.id', '=', 'imali_accounts.imali_account_config')
                        ->select(
                            'imali_accounts.*',
                            'imali_account_configs.level'
                        )->get();
                },
                'imaliBusinessAccount' => function ($business) {
                    return $business->join('imali_account_configs', 'imali_account_configs.id', '=', 'business_accounts.imali_account_config')
                        ->select(
                            'business_accounts.*',
                            'imali_account_configs.level'
                        )->get();
                },
                'document' => function ($document) {
                    // return $document->orderBy('id', 'desc')->get()->toArray()[0];
                    return $document->orderBy('id', 'desc')->get();
                    // return $document->latest()->first();
                }
            ])
            ->orderBy($orderBy, $orderType)
            ->paginate($perPage);
        // ->map(function ($user) {
        //     // Remove os relacionamentos originais
        //     $combined_accounts = array_merge(
        //         $user->imaliAccount ? $user->imaliAccount->toArray() : [],
        //         $user->imaliBusinessAccount ? $user->imaliBusinessAccount->toArray() : []
        //     );

        //     if ($user->profile === 'client')
        //         $user->last_recharge = $user->imaliAccount->recharges()->orderBy('id', 'desc')->first();
        //     else
        //         $user->last_recharge = $user->imaliBusinessAccount->recharges()->orderBy('id', 'desc')->first();
        //     unset($user->imaliAccount, $user->imaliBusinessAccount);
        //     $user->imaliAccount = $combined_accounts;

        //     return $user;
        // });

        $imali = $users->setCollection($users->getCollection()
            ->transform(function ($user) {
                $combined_accounts = array_merge(
                    $user->imaliAccount ? $user->imaliAccount->toArray() : [],
                    $user->imaliBusinessAccount ? $user->imaliBusinessAccount->toArray() : []
                );

                if ($user->profile === 'client')
                    $user->last_recharge = $user->imaliAccount->recharges()->orderBy('id', 'desc')->first();
                else
                    $user->last_recharge = $user->imaliBusinessAccount->recharges()->orderBy('id', 'desc')->first();
                unset($user->imaliAccount, $user->imaliBusinessAccount);
                $user->imaliAccount = $combined_accounts;
                return $user;
            }));

        $imali->makeHidden([
            'password',
            'pin',
            'remember_token',
            'firebase_token'
        ]);

        return response()->json($imali);
    }

    public function getImaliAccountsORIGINAL(Request $request)
    {
        $perPage = !!$request->input('per_page') ? $request->input('per_page') : 10;
        $orderType = $request->input('order_type') === 'ASC' ? 'ASC' : 'DESC';
        $orderBy = !!$request->input('order_by') && $request->input('order_by') !== 'null' ? $request->input('order_by') : 'imali_accounts.id';


        $users = User::query()->join('imali_accounts', 'imali_accounts.user_id', '=', 'users.id')
            ->join('imali_account_configs', 'imali_account_configs.id', '=', 'imali_accounts.imali_account_config')
            ->select('imali_accounts.*', 'imali_account_configs.level', 'users.id', 'users.name', 'users.last_name', 'users.name', 'users.country_code', 'users.email', 'users.phone', 'users.status')
            ->orderBy($orderBy, $orderType)->paginate($perPage);

        $imali = $users->setCollection($users->getCollection()
            ->transform(function ($item) {
                $item['last_recharge'] = $item->imaliAccount->recharges()->orderBy('id', 'desc')->first();
                $item['document'] = $item->documents()->orderBy('id', 'desc')->first();
                return $item;
            }));



        $imali->makeHidden([
            'password',
            'pin',
            'imali_account_config',
            'profile',
            'remember_token',
            'firebase_token'
        ]);

        return response()->json($imali);
    }

    public function updateUserData(Request $request)
    {

        $user = $imali = ImaliAccount::query()
            ->join('users', 'users.id', '=', 'imali_accounts.user_id')
            ->join('imali_account_configs', 'imali_account_configs.id', '=', 'imali_accounts.imali_account_config')
            ->where('users.user_id', $request->user_id)
            ->first();

        if ($user) {

            $u = User::find($user->id);
            $u->update([
                'name' => $request->name,
                'last_name' => $request->last_name,
                'profile' => $request->profile,
                'status' => $request->status,
                'birthday' => $request->birthday,
                'bi' => $request->bi,
            ]);

            $kyc = ImaliAccount::query()->where('user_id', $user->id)->first();
            if ($kyc) {
                $kyc->update([
                    'imali_account_config' => $request->imali_account_config
                ]);
            }
            return response()->json(['message' => 'Dados do Cliente Actualizados com Sucesso!'], 200);
        }
    }

    public function updateUserStatus($account_number)
    {
        // $imali = ImaliAccount::query()->where('account_number', $account_number)->first();

        // $user = User::findOrFail($imali->user_id);

        $account = User::getAccount($account_number);

        $user = User::getUserDetails($account->user_id);

        $user->status = !$user->status;
        $user->login_attempts = 0;
        $user->pin_attempts = 0;
        $user->user_update_info_status = 0;
        $user->password = Hash::make('12345678');

        $user->save();
        // return "Chegou";

        return response()->json(['message' => 'Estado actualizado com sucesso!'], 200);
    }

    public function updateUserDataMobile(Request $request)
    {
        $user = $request->user();

        if ($user) {

            $update = User::query()
                ->where('id', $user->id)
                ->update([
                    'name' => $request->name,
                    'last_name' => $request->last_name,
                    'bi' => $request->bi,
                    'birthday' => $request->birthday,
                ]);
            if ($update) {
                return response()->json(['message' => 'Dados Actualizados com Sucesso'], 200);
            }
        }
    }

    public function changePassword(Request $request)
    {

        $this->validate(
            $request,
            [
                'current_password' => ['required', new CurrentPassword()],
                //            'new_password' => 'required|min:8|confirmed',
                'new_password' => ['required', 'min:8', 'confirmed'],
                'new_password_confirmation' => 'required|min:8',
            ],
            [
                'current_password.required' => 'O Campo Senha Actual é Obrigatório',
                'new_password.required' => 'O Campo Nova Senha é Obrigatório',
                'new_password_confirmation.required' => 'O Campo Confirmar Senha é Obrigatório',
                'new_password.confirmed' => 'Senhas incompatíveis',
                'current_password.min' => 'A senha deve ter 8 digitos no mínimo',
                'new_password.min' => 'A senha deve ter 8 digitos no mínimo',
                'new_password_confirmation.min' => 'A senha deve ter 8 digitos no mínimo'
            ]
        );


        if (Hash::check($request->current_password, $request->user()->password)) {

            $request->user()->update([
                'password' => bcrypt($request->new_password)
            ]);

            return response()->json(['message' => 'Senhas Compativeis'], 200);
        } else {
            return response()->json(['message' => 'Senha Antiga Inválida'], 404);
        }
    }

    public function uploadPhoto(Request $request)
    {
        return $request->all();
    }

    public function disableUser($id)
    {
        $user = User::query()->where('user_id', $id)->first();


        if ($user->status === 1) {
            $update = $user->update(['status' => 0]);
            return response()->json(['message' => 'Utilizador Bloqueado com Sucesso'], 200);
        } else {
            return response()->json(['message' => 'Utilizador Activo com Sucesso'], 200);
        }
    }

    public function generateAmount(Request $request)
    {
        $imali = ImaliAccount::query()->where('user_id', $request->user()->id)->first();

        $save = AmountGenerate::create([
            'user_id' => $request->user()->id,
            'transaction' => Uuid::generate()->string,
            'amount' => $request->amount,
            'account_number' => $imali->account_number,
            'qrcode' => '',
            'firebase_token' => $request->firebase_token
        ]);

        //        $log = new Record();
        //        $log->createLog([
        //            'description' => $save->account_number . ' ' . $save->amount . ' ' . $save->transaction,
        //            'details' => 'Codigo gerado com Sucesso',
        //            'operation' => 'Generate Amount to Receiver By Qrcode',
        //            'status' => 'Success',
        //            'user_id' => $request->user()->id
        //        ]);

        return response()->json(['message' => 'Codigo gerado com Sucesso', 'transaction' => $save->transaction, 'account_number' => $save->account_number, 'amount' => $save->amount], 200);
    }

    public function getClientDataForPayment($transaction)
    {

        $client = AmountGenerate::query()
            ->join('users', 'users.id', '=', 'amount_generates.user_id')
            ->join('imali_accounts', 'imali_accounts.user_id', '=', 'amount_generates.user_id')
            ->where('amount_generates.transaction', $transaction)
            //            ->select('amount_generates.amount','amount_generates.transaction', 'users.name', 'imali_accounts.account_number')
            ->select('amount_generates.amount', 'users.name', 'imali_accounts.account_number')
            //            ->select('amount_generates.*', 'users.name', 'imali_accounts.account_number')
            ->first();


        if ($client) {
            return response()->json($client, 200);
        } else {

            $user = ImaliAccount::query()
                ->join('users', 'users.id', '=', 'imali_accounts.user_id')
                //            ->join('recharge_imali_accounts', 'recharge_imali_accounts.imali_account_id', '=', 'imali_accounts.id')
                ->where('imali_accounts.account_number', $transaction)
                ->select('users.name', 'imali_accounts.account_number')
                ->first();

            return response()->json($user, 200);
        }
    }

    public function getClientAccount($aacount)
    {

        $client = AmountGenerate::query()
            ->join('users', 'users.id', '=', 'amount_generates.user_id')
            ->join('imali_accounts', 'imali_accounts.user_id', '=', 'amount_generates.user_id')
            ->where('amount_generates.transaction', $aacount)
            //            ->select('amount_generates.amount','amount_generates.transaction', 'users.name', 'imali_accounts.account_number')
            ->select('amount_generates.amount', 'users.name', 'imali_accounts.account_number')
            //            ->select('amount_generates.*', 'users.name', 'imali_accounts.account_number')
            ->first();

        return response()->json($client, 200);
    }

    public function checkPin(Request $request)
    {

        $this->validate(
            $request,
            [
                'pin' => 'required',
            ],
            [
                'pin.required' => 'A senha obrigatoria'
            ]
        );

        if (strlen($request->pin) == 3)
            $request->pin = '0' . $request->pin;

        if (strlen($request->pin) == 2)
            $request->pin = '00' . $request->pin;

        if (strlen($request->pin) == 1)
            $request->pin = '000' . $request->pin;

        $user = User::find($request->user()->id);

        if (Hash::check($request->pin, $user->pin)) {
            return response()->json(['message' => 'Pin Verificado'], 201);
        } else {
            return response()->json(['message' => 'Pin Incorrecto'], 400);
        }
    }

    public function getBalance(Request $request)
    {
        //        return $request->all();
        $imali = ImaliAccount::query()
            ->join('users', 'users.id', '=', 'imali_accounts.user_id')
            ->where('users.phone', $request->phone)
            ->first();

        if ($imali) {
            return response()->json($imali);
        } else {
            return response()->json(['message' => 'Conta invalida']);
        }
    }

    public function updateFirebaseToken(Request $request) {}

    public function reverteTransaction(Request $request)
    {
        $transactionString = new TransactionGeneration();

        $public_key = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmptSWqV7cGUUJJhUBxsMLonux24u+FoTlrb+4Kgc6092JIszmI1QUoMohaDDXSVueXx6IXwYGsjjWY32HGXj1iQhkALXfObJ4DqXn5h6E8y5/xQYNAyd5bpN5Z8r892B6toGzZQVB7qtebH4apDjmvTi5FGZVjVYxalyyQkj4uQbbRQjgCkubSi45Xl4CGtLqZztsKssWz3mcKncgTnq3DHGYYEYiKq0xIj100LGbnvNz20Sgqmw/cH+Bua4GJsWYLEqf/h/yiMgiBbxFxsnwZl0im5vXDlwKPw+QnO2fscDhxZFAwV06bgG0oEoWm9FnjMsfvwm0rUNYFlZ+TOtCEhmhtFp+Tsx9jPCuOd5h2emGdSKD8A6jtwhNa7oQ8RtLEEqwAn44orENa1ibOkxMiiiFpmmJkwgZPOG/zMCjXIrrhDWTDUOZaPx/lEQoInJoE2i43VN/HTGCCw8dKQAwg0jsEXau5ixD0GUothqvuX3B9taoeoFAIvUPEq35YulprMM7ThdKodSHvhnwKG82dCsodRwY428kg2xM/UjiTENog4B6zzZfPhMxFlOSFX4MnrqkAS+8Jamhy1GgoHkEMrsT5+/ofjCx0HjKbT5NuA2V/lmzgJLl3jIERadLzuTYnKGWxVJcGLkWXlEPYLbiaKzbJb2sYxt+Kt5OxQqC1MCAwEAAQ==";
        $api_host = "api.sandbox.vm.co.mz";
        $api_key = "40dtaa0qj1xcw1rwytyszgq83lp523m0";
        $origin = "*";
        $service_provider_code = "171717";
        $reference = 'T12344C';


        $client = new Client([
            'apiKey' => $api_key,             // API Key
            'publicKey' => $public_key,          // Public Key
            'serviceProviderCode' => $service_provider_code // input_ServiceProviderCode
        ]);

        $transaction = RechargeImaliAccount::query()
            ->where('id', $request->id)
            ->where('transaction_id', $request->transaction)
            ->where('imali_account_id', $request->imali_account_id)
            ->first();

        $paymentData = [
            'reference' => 'T12344C',      // input_ThirdPartyReference
            'transaction' => $transaction->transaction_id, // input_TransactionReference
            'amount' => $transaction->amount             // input_Amount
        ];
        $transactionString = new TransactionGeneration();

        if ($transaction) {

            $results = $client->revert($paymentData);

            if ($results->success) {


                ReverteImaliAccount::create([
                    'transaction' => $transactionString->generateTransaction(),
                    'user_id' => $request->user()->id,
                    'imali_account_id' => $transaction->imali_account_id,
                    'recharge_imali_account_id' => $transaction->id
                ]);

                return response()->json(['message' => 'Transacção revertida com Sucesso'], 200);
            }
        }
    }

    public function sendMoneyImaliMpesa(Request $request)
    {
        $transactionString = new TransactionGeneration();

        $public_key = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmptSWqV7cGUUJJhUBxsMLonux24u+FoTlrb+4Kgc6092JIszmI1QUoMohaDDXSVueXx6IXwYGsjjWY32HGXj1iQhkALXfObJ4DqXn5h6E8y5/xQYNAyd5bpN5Z8r892B6toGzZQVB7qtebH4apDjmvTi5FGZVjVYxalyyQkj4uQbbRQjgCkubSi45Xl4CGtLqZztsKssWz3mcKncgTnq3DHGYYEYiKq0xIj100LGbnvNz20Sgqmw/cH+Bua4GJsWYLEqf/h/yiMgiBbxFxsnwZl0im5vXDlwKPw+QnO2fscDhxZFAwV06bgG0oEoWm9FnjMsfvwm0rUNYFlZ+TOtCEhmhtFp+Tsx9jPCuOd5h2emGdSKD8A6jtwhNa7oQ8RtLEEqwAn44orENa1ibOkxMiiiFpmmJkwgZPOG/zMCjXIrrhDWTDUOZaPx/lEQoInJoE2i43VN/HTGCCw8dKQAwg0jsEXau5ixD0GUothqvuX3B9taoeoFAIvUPEq35YulprMM7ThdKodSHvhnwKG82dCsodRwY428kg2xM/UjiTENog4B6zzZfPhMxFlOSFX4MnrqkAS+8Jamhy1GgoHkEMrsT5+/ofjCx0HjKbT5NuA2V/lmzgJLl3jIERadLzuTYnKGWxVJcGLkWXlEPYLbiaKzbJb2sYxt+Kt5OxQqC1MCAwEAAQ==";
        $api_host = "api.sandbox.vm.co.mz";
        $api_key = "40dtaa0qj1xcw1rwytyszgq83lp523m0";
        $origin = "*";
        $service_provider_code = "171717";

        $reference = 'T12344C';

        $third_party_reference = $transactionString->generateTransaction();


        $client = new Client([
            'apiKey' => $api_key,             // API Key
            'publicKey' => $public_key,          // Public Key
            'serviceProviderCode' => $service_provider_code // input_ServiceProviderCode
        ]);


        $paymentData = [
            'to' => '258' . $request->phone,         // input_CustomerMSISDN
            'reference' => 'T12344C',      // input_ThirdPartyReference
            'transaction' => $third_party_reference, // input_TransactionReference
            'amount' => $request->amount             // input_Amount
        ];


        $user = User::query()->where('user_id', $request->user_id)->first();

        //        $imaliAccount = ImaliAccount::query()->where('user_id', $user->id)->first();
        $imaliAccount = ImaliAccount::query()->where('user_id', $request->user_id)->first();

        $total = ($request->amount + $request->amount * 0.3);

        if ($imaliAccount->balance >= $total) {

            $results = $client->send($paymentData);

            if ($results->success) {

                SendMoneyImaliMpesa::create([
                    'transaction' => $third_party_reference,
                    'fee' => ($request->amount * 0.3),
                    'fee_type' => '3%',
                    'amount' => $request->amount,
                    'imali_account' => $request->imali_account,
                    'admin_id' => $request->admin_id,
                    'user_id' => $request->user_id,
                    'phone' => $request->phone
                ]);
                //                dd($results);

                return response()->json(['message' => 'Transacção ' . $results->data['transaction'] . ' efectuada com Sucesso'], 200);
            }
        }
    }


    public function sendMoneyB2B(Request $request)
    {
        $transactionString = new TransactionGeneration();

        $public_key = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmptSWqV7cGUUJJhUBxsMLonux24u+FoTlrb+4Kgc6092JIszmI1QUoMohaDDXSVueXx6IXwYGsjjWY32HGXj1iQhkALXfObJ4DqXn5h6E8y5/xQYNAyd5bpN5Z8r892B6toGzZQVB7qtebH4apDjmvTi5FGZVjVYxalyyQkj4uQbbRQjgCkubSi45Xl4CGtLqZztsKssWz3mcKncgTnq3DHGYYEYiKq0xIj100LGbnvNz20Sgqmw/cH+Bua4GJsWYLEqf/h/yiMgiBbxFxsnwZl0im5vXDlwKPw+QnO2fscDhxZFAwV06bgG0oEoWm9FnjMsfvwm0rUNYFlZ+TOtCEhmhtFp+Tsx9jPCuOd5h2emGdSKD8A6jtwhNa7oQ8RtLEEqwAn44orENa1ibOkxMiiiFpmmJkwgZPOG/zMCjXIrrhDWTDUOZaPx/lEQoInJoE2i43VN/HTGCCw8dKQAwg0jsEXau5ixD0GUothqvuX3B9taoeoFAIvUPEq35YulprMM7ThdKodSHvhnwKG82dCsodRwY428kg2xM/UjiTENog4B6zzZfPhMxFlOSFX4MnrqkAS+8Jamhy1GgoHkEMrsT5+/ofjCx0HjKbT5NuA2V/lmzgJLl3jIERadLzuTYnKGWxVJcGLkWXlEPYLbiaKzbJb2sYxt+Kt5OxQqC1MCAwEAAQ==";
        $api_host = "api.sandbox.vm.co.mz";
        $api_key = "40dtaa0qj1xcw1rwytyszgq83lp523m0";
        $origin = "*";
        $service_provider_code = "171717";

        $reference = 'T12344C';

        $third_party_reference = $transactionString->generateTransaction();


        $client = new Client([
            'apiKey' => $api_key,             // API Key
            'publicKey' => $public_key,          // Public Key
            'serviceProviderCode' => $service_provider_code // input_ServiceProviderCode
        ]);

        //        979797

        $paymentData = [
            'to' => $request->entity,        // input_ReceiverPartyCode
            'reference' => '111PA2D',      // input_ThirdPartyReference
            'transaction' => $third_party_reference, // input_TransactionReference
            'amount' => $request->amount           // input_Amount
        ];


        $results = $client->send($paymentData);

        if ($results->success) {

            SendMoneyB2B::create([
                'entity' => $request->entity,
                'amount' => $request->amount,
                'admin_id' => $request->user()->id,
                'transaction' => $third_party_reference,
            ]);
        }

        return response()->json(['message' => 'Transacção efectuada com Sucesso'], 200);
    }

    public function sendSMS(Request $request)
    {
        $data = [$request->phone];
        $sms = new  SendSMS();
        $sent = $sms->sendMessageTest($data);

        return response($sent);
    }

    public function getContacts()
    {
        $contacts = User::query()->value('phone');
        return response()->json(['data' => $contacts]);
    }

    // NOVO CODIGO UPLOAD IMAGE
    # actualizar no server
    public function imageCompress($image, $newImageName, $imgDefaultRatio)
    {
        $image = \Image::make(file_get_contents($image));
        $image->save($this->storagePath . '/' . $newImageName, $imgDefaultRatio);
    }

    #actualizar no server
    public function imageUpload($image, $newImageName)
    {
        $image->move($this->storagePath, $newImageName);
    }


    # actualizar no server
    public function generateImageUrl(Request $request, $imageAttr)
    {

        if ($request->hasFile($imageAttr) && $request->file($imageAttr)->isValid()) {

            // Validar imagem
            $this->validate(
                $request,
                [
                    $imageAttr => 'mimes:jpeg,jpg,png|max:4096'
                ],
                [
                    'photo.required' => 'O campo photo é Obrigatório',
                    'photo.mimes' => 'Formato de imagem invalido, formatos permitidos jpeg,jpg,png',
                    'photo.max' => 'O tamanho de imagem permitido somente abaixo de 4 MB',
                ]
            );

            //fazer o upload
            $image = $request[$imageAttr];

            $newImageName = time() . $image->getClientOriginalName();

            //verificar size
            $imageSizeMB = round($request->file($imageAttr)->getSize() / (1024 * 1024), 2);

            // Diminuir tamanho..
            if ($imageSizeMB >= 1) {

                $imgDefaultRatio = 65;

                if ($imageSizeMB >= 3) {
                    $imgDefaultRatio = 35;
                }

                //comprimir e fazer upload
                $this->imageCompress($image, $newImageName, $imgDefaultRatio);
            } else {
                $this->imageUpload($image, $newImageName);
            }

            // return  $this->baseUrl . $newImageName;
            return $newImageName; // todo -- actualizacao feita no dia 13 de Marco de 2025 ::. by Ivo Naftal
        } else {

            $exploded = explode(',', $request[$imageAttr]);
            $decoded = base64_decode($exploded[$this->is_string_encoded($request[$imageAttr]) ? 0 : 1], True);

            $f = finfo_open();
            $mime_type = finfo_buffer($f, $decoded, FILEINFO_MIME_TYPE);

            $valiExtension = ['jpeg', 'jpg', 'png'];
            $imageExtention = substr($mime_type, 6, strlen($mime_type));

            if (!in_array($imageExtention, $valiExtension)) return response()->json(['message' => "Formato de imagem invalido, formatos permitidos jpeg,jpg,png"], 400);

            if ($this->getImageSizeMB($decoded) > 4) return response()->json(['message' => "O tamanho de imagem permitido somente abaixo de 4 MB"], 400);


            //            if (base64_encode($decoded) !== $exploded[$this->is_string_encoded($request[$imageAttr])?0:1]) return response()->json(['message' => 'Imagem invalida.'],400);

            //faz o upload temporario no storage - by Rodrigues Mafumo
            $tempFileName = $imageAttr . '.jpg';

            if (Storage::put($tempFileName, $decoded)) {
                $path  = storage_path('app/') . $tempFileName;
                $tempFile = new \Symfony\Component\HttpFoundation\File\File($path);
                $file = UploadedFile::createFromBase(new  UploadedFile($tempFile->getPathname(), $tempFileName, $tempFile->getMimeType(), null, true));
                $newRequest = new Request();
                $newRequest->files->set($imageAttr, $file);
                return $this->generateImageUrl($newRequest, $imageAttr);
            }
        }
    }

    #server
    private function getImageSizeMB($imagebase64)
    {
        $size_in_bytes = (int) (strlen(rtrim($imagebase64, '=')) * 1);
        $size_in_kb    = $size_in_bytes / 1024;
        $size_in_mb    = round($size_in_kb / 1024, 2);
        return $size_in_mb;
    }

    #server
    public function updateAvatar(Request $request)
    {

        $user = User::find($request->user()->id);

        $posicao = strpos($user->photo, 'avatar') + 7;
        //? Retorna a posicao do avatar
        $imageName = substr($user->photo, $posicao, strlen($user->photo));

        File::delete(public_path('/images/avatar/' . $imageName));

        $photo = $this->generateImageUrl($request, 'photo');
        if (!is_string($photo)) return $photo;
        $user->photo = $photo;

        $user->update();

        return response()->json(['message' => 'Avatar Actualizado com Sucesso']);
    }


    #server
    // Check if there are valid base64 characters
    function is_string_encoded($s)
    {
        return !startsWith("data:image/", $s);
    }

    //FIM UPLOAD IMAGE


    public function getMyCredelec(Request $request)
    {
        $size = (!request()->per_page) ? 4 : request()->per_page;

        $new_start_date  = null;
        $new_end_date  = null;

        if ($request->filled('start_date')) {
            $start_date = explode('-', $request->start_date);
            if (strlen($start_date[2]) >= 4)
                $new_start_date = $start_date[2] . '-' . $start_date[1] . '-' . $start_date[0];
        }

        if ($request->filled('end_date')) {
            $end_date = explode('-', $request->end_date);
            if (strlen($end_date[2]) >= 4)
                $new_end_date = $end_date[2] . '-' . $end_date[1] . '-' . $end_date[0];
        }

        $credelec = Credelec::query()
            ->where('user_id', $request->user()->id)
            // new ------------------------
            ->when($request->filled('start_date'), function ($query) use ($request, $new_start_date) {
                $query->whereDate('credelecs.created_at', '>=', $new_start_date ?? $request->start_date);
            })
            ->when($request->filled('end_date'), function ($query) use ($request, $new_end_date) {
                $query->whereDate('credelecs.created_at', '<=', $new_end_date ?? $request->end_date);
            })
            // new ------------------------
            ->orderByDesc('created_at')
            // ->get();
            ->paginate($size);

        return response()->json($credelec, 200);

        //return response()->json(['data' => $credelec]);
    }

    public function getMyWater(Request $request)
    {
        $size = (!request()->per_page) ? 4 : request()->per_page;

        $new_start_date  = null;
        $new_end_date  = null;

        if ($request->filled('start_date')) {
            $start_date = explode('-', $request->start_date);
            if (strlen($start_date[2]) >= 4)
                $new_start_date = $start_date[2] . '-' . $start_date[1] . '-' . $start_date[0];
        }

        if ($request->filled('end_date')) {
            $end_date = explode('-', $request->end_date);
            if (strlen($end_date[2]) >= 4)
                $new_end_date = $end_date[2] . '-' . $end_date[1] . '-' . $end_date[0];
        }

        $credelec = Water::query()
            ->where('user_id', $request->user()->id)
            // new ------------------------
            ->when($request->filled('start_date'), function ($query) use ($request, $new_start_date) {
                $query->whereDate('waters.created_at', '>=', $new_start_date ?? $request->start_date);
            })
            ->when($request->filled('end_date'), function ($query) use ($request, $new_end_date) {
                $query->whereDate('waters.created_at', '<=', $new_end_date ?? $request->end_date);
            })
            // new ------------------------
            ->orderByDesc('created_at')
            //->get();
            ->paginate($size);

        return response()->json($credelec, 200);
        //return response()->json(['data' => $credelec]);
    }

    public function pushNotifification($token, $notification = array(), $data = array())
    {
        $apiKey = 'AAAA8zVzEPQ:APA91bHl_DXB6UGb_6gZlmFnaLTQoANtX_OBjvl3nOy2bSlnFhxedvk6EhGj7cZoIvmlbKeCnqGxXbuyMH_rEPuhRXvuitXzo6Pfl2TMXLar1PlifXqEhYq6tS55UMrY2Kffzj-P_UH-';
        $fields = array('to' => $token, 'notification' => $notification, 'data' => $data);
        $headers = array('Authorization: key=' . $apiKey, 'Content-Type: application/json');
        $url = 'https://fcm.googleapis.com/fcm/send';

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($fields));
        $result = curl_exec($curl);
        curl_close($curl);

        return json_decode($result, true);
    }


    //? Check User Name
    public function checkUserName(Request $request)
    {
        $regex = "/^[a-zA-Z0-9]+(_{0,1})[a-zA-Z0-9]*$/";

        if (!preg_match($regex, $request->username)) return response()->json(['message' => 'Username inválido, caracteres permitidos [ a-z ou A-Z ou 0-9 ou _ ]'], 400);

        if (strlen($request->username) > 15) return response()->json(['message' => 'Username deve ter no maximo 15 caracteres'], 400);

        $user = User::query()->where('username', $request->username)->first();

        if ($user) return response()->json(['message' => 'Username já esta em uso'], 409);
        return response()->json(['message' => 'Username disponivel'], 200);
    }


    //? Check Phone
    public function checkUserPhone(Request $request)
    {

        // $regex = "/^[0-9]+$/";
        $regex = "/^(82|83|84|85|86|87)+[0-9]{7,7}$/";

        if (!preg_match($regex, $request->phone)) return response()->json(['message' => 'Número de telefone inválido'], 400);

        $user = User::query()->where('phone', $request->phone)->first();

        if ($user) return response()->json(['message' => 'Número de telefone já está em uso'], 409);
        return response()->json(['message' => 'Numero de telefone disponivel'], 200);
    }


    //? Check Email
    public function checkUserEmail(Request $request)
    {

        $this->validate(
            $request,
            [
                'email' => 'required'
            ],
            [
                'email.required' => 'O campo email é Obrigatório',
            ]
        );

        // $regex = "/^[a-zA-Z0-9]+(_{0,1})[a-zA-Z0-9]*$/";
        // $regex = "/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/";
        $regex = "/^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i";

        if (!preg_match($regex, $request->email)) return response()->json(['message' => 'Email inválido'], 400);

        $user = User::query()->where('email', $request->email)->first();

        if ($user) return response()->json(['message' => 'Email já esta em uso'], 409);
        return response()->json(['message' => 'Email disponivel'], 200);
    }



    //? Update Username 
    public function updateUsername(Request $request)
    {
        // Validar imagem
        $this->validate(
            $request,
            [
                'username' => 'required|max:15'
            ],
            [
                'username.required' => 'O campo nome de utilizador é obrigatório',
            ]
        );

        $regex = "/^[a-zA-Z0-9]+(_{0,1})[a-zA-Z0-9]*$/";

        if (!preg_match($regex, $request->username)) return response()->json(['message' => 'Nome de utilizador inválido, caracteres permitidos [ a-z ou A-Z ou 0-9 ou _ ]'], 400);

        $user = User::query()->where('username', $request->username)->first();

        if ($user) return response()->json(['message' => 'O nome de utilizador já está em uso.'], 409);
        // return response()->json(['message'=> 'Username disponivel'], 200);

        $user = $request->user();

        if ($user) {

            $update = User::query()
                ->where('id', $user->id)
                ->update([
                    'username' => $request->username
                ]);
            if ($update) {
                return response()->json(['message' => 'O nome de utilizador foi actualizado com sucesso.'], 200);
            }
        }
    }

    public function walletCSV()
    {
        return Excel::download(new Wallet, 'wallet.csv');
    }

    public function getWallets()
    {
        $wallets = Wallet::query()->get();

        return response()->json(['data' => $wallets], 200);
    }


    public function createWithDrawalls(Request $request)
    {


        $request->request->add([
            'mobile_wallets_id' => 21,
            'phone' => $request->account_number,
            'amount' => $request->amount,
            'imaliReference' => User::getUserAccount()->reference
        ]);

        $req = Request::create('/api/withdrawall-by-mpesa', 'POST', $request->all());
        // return Route::dispatch($req);

        // Dispatch the request to the application
        $response = app()->handle($req);

        // Get the content of the response
        $content = $response->getContent();

        // Optionally, convert JSON response to an array
        $data = json_decode($content, true);

        //$data2 = [
        //    'account_number' => $data['phone'],
        //    'account_type' => 'client',
        //    'amount' => $data['amount'],
        //    'wallets_id' => 2,
        //    'operators_id' => 21,
        //    'total' => $data['total'],
        //    'imali_fee' => $data['imali_fee'],
        //    'commission' => $data['commission'],
        //    'bank_fee' => $data['bank_fee'],
        //    'stamp_tax' => $data['stamp_tax'],
        //];

        return $data;


        //verifica se pode efectuar a transacao
        $checkWithDrawall = $this->checkWithdrawallTransaction($request);
        if ($checkWithDrawall->getStatusCode() >= 400 && $checkWithDrawall->getStatusCode() < 500)  return $checkWithDrawall->getData();

        //verifica o PIN de confirmacao de transacoes
        $auth = new Auth;
        // $resp = $auth->checkUserPin($request);
        $resp = $auth->checkUserPinAndFingerprint($request);
        if ($resp->getStatusCode() >= 400 && $resp->getStatusCode() < 500) return $resp->getData();

        //conta imali para pegar saldo anterior  
        $imali2 = ImaliAccount::query()->where('user_id', auth('api')->user()->id)->first();
        //conta imali para pegar saldo actual  
        $imali = ImaliAccount::query()->where('user_id', auth('api')->user()->id)->first();
        //variavel para colocar o nome do operador na descricao da transacao
        $operator = Operator::query()->where('id', $checkWithDrawall->getData()->operators_id)->first();

        //actualizacao do saldo principal e do saldo cativo
        $imali->balance = $imali->balance -  $checkWithDrawall->getData()->total;

        $imali->captive_balance += $checkWithDrawall->getData()->total;

        $imali->update();
        /*variavel para pegar a conta imali de acordo com o account_type 
        * se o account_type for "client" entao vai buscar a conta iMali do cliente iMali
        * se o account_type for "store" entao vai buscar a conta iMali da Loja
        */

        $account_number = ImaliAccount::query()
            ->where('imali_accounts.user_id', auth('api')->user()->id)
            ->select('imali_accounts.balance', 'imali_accounts.account_number', 'imali_accounts.user_id')
            ->first()->account_number;

        //regista o pedido de transferencia
        $trasactionGeneration = new TransactionGeneration();

        $transaction_id = $trasactionGeneration->generateTransaction();


        $withdrawalls = WithdrawalsRequest::create([
            'imali_account' => $account_number,
            'account_type' => $request->account_type,
            'amount' => $request->amount,
            'imali_fee' => $checkWithDrawall->getData()->imali_fee,
            'bank_fee' => $checkWithDrawall->getData()->bank_fee,
            'description' => 'TRF. ' . $operator->acronym,
            'account_number' => $request->account_number,
            'wallets_id' => $request->wallets_id,
            'operators_id' => $operator->id,
            'status' => 'pending',
            'old_balance' => $imali2->balance,
            'new_balance' => $imali->balance,
            'total' => $checkWithDrawall->getData()->total,
            'transaction_id' => $transaction_id,
            'commission' => $checkWithDrawall->getData()->commission,
            'stamp_tax' => $checkWithDrawall->getData()->stamp_tax,
            'user_id' => $imali->user_id,
            'imali_account_id' => $imali->id
        ]);

        //? -----------------INICIO---------------------

        /**
         * gerar um ficheiro excel de transacoes para enviar para o MOZA Banco
         * Utilizando template localizado em storage/app/template.csv
         * Salvando em storage/app/downloads
         * */
        $data = new \App\Exports\WalletExport();

        // return $data->collection();

        $date = date('Y') . date('m') . date('d');
        $hours = date('H') . date('i') . date('s');
        $fileName = "Transac_iMali_" . $date . "-" . $hours  . '.csv';

        $this->generateMozaTransactionFile($data, $fileName);

        //encryptar o ficheiro e enviar no diretorio do moza banco
        $this->encryptGeneratedFileAndSendToMoza($fileName);

        //actualizar o status da transacao para pending
        // $withdrawalls->status = 'pending';
        // $withdrawalls->update();

        return response()->json(['message' => 'Pedido de transferência efectuado com sucesso!'], 200);
    }


    private function generateMozaTransactionFile($data, $fileName)
    {

        file_put_contents(storage_path('/app/template/' . $fileName), file_get_contents(storage_path('/app/template/template.csv')));

        $file = fopen(storage_path('/app/template/' . $fileName), 'a') or die('unable to open file');

        foreach ($data->collection() as $key => $value) {
            $text = $value['value' . $key] . "\n";
            fwrite($file, $text);
        }

        fclose($file);

        rename(storage_path('/app/template/' . $fileName), storage_path('/app/downloads/' . $fileName));
    }


    private function encryptGeneratedFileAndSendToMoza($fileName)
    {

        $filePath = "/downloads/" . $fileName;
        $uploadPath = storage_path('app' . $filePath);

        $filePath = str_replace('\\', '/', $uploadPath);

        //ENCRIPTAR FICHEIRO
        $commands = explode(",", "gpg --homedir /home/paytek/.gnupg --recipient einstein.bata@mozabanco.co.mz --encrypt " . $filePath . "," . "mv " . $filePath . ".gpg" . " /var/sftp/uploads_mozabanco/imali_transac_files/" . $fileName . ".gpg");
        // $commands = explode(",", "gpg --homedir /home/paytek/.gnupg --recipient lourino.junior@mozabanco.co.mz --encrypt " . $filePath . "," . "mv " . $filePath . ".gpg" . " /var/sftp/uploads_mozabanco/imali_transac_files/" . $fileName . ".gpg");

        foreach ($commands as $command) {
            exec($command, $output, $returnDir);
        }
    }


    public function checkWithdrawallTransaction(Request $request)
    {

        //return response()->json(['message' => 'Serviço temporariamente indisponível.'], 400);

        $request->request->add([
            'mobile_wallets_id' => 21,
            'phone' => $request->account_number,
            'amount' => $request->amount,
            'imaliReference' => User::getUserAccount()->reference
        ]);

        $req = Request::create('/api/check-mpesa-withdrawall-transaction', 'GET', $request->all());

        // $req = Request::create('/api/check/mpesa/b2c-transaction', 'GET');
        // return Route::dispatch($req);

        // Dispatch the request to the application
        $response = app()->handle($req);

        if ($response->getStatusCode() != 200) return $response;

        // Get the content of the response
        $content = $response->getContent();

        Log::info('[LOG_TEST_CONTENT_WITHDRAWAL]', ['data' => $response->getStatusCode()]);

        // Optionally, convert JSON response to an array
        $data = json_decode($content, true);

        $data2 = [
            'account_number' => $data['phone'],
            'account_type' => 'client',
            'amount' => $data['amount'],
            'wallets_id' => 2,
            'operators_id' => 21,
            'total' => $data['total'],
            'imali_fee' => $data['imali_fee'],
            //'bank_fee' => $data['bank_fee'],
            'commission' => $data['commission'],
            'stamp_tax' => $data['stamp_tax'],
        ];

        //return $data2;
        return response()->json($data2, 200);

        //return $data;
        //?return response()->json(['message'=> 'Feito com sucesso'], 201);

        // return response()->json(['message' => 'Este serviço vai estar disponível a partir do dia 1 de Outubro.'], 400);
        // return response()->json(['message' => 'Este serviço está disponível somente para ambiente em Produção.'], 400);

        $this->validate(
            $request,
            [
                'account_type' => 'required|in:client',
                'amount' => 'required',
                'wallets_id' => 'required',
            ],
            [
                'account_type.required' => 'O campo account_type é obrigatório',
                'account_type.in' => 'O campo account_type só pode ser (client)',
                'amount.required' => 'Campo amount é obrigatório',
                'wallets_id.required' => 'Campo wallets_id é obrigatório',
            ]
        );

        //? validacao
        //  $rules = [
        //      'account_type' => 'required|in:client',
        //      'amount' => 'required',
        //      'wallets_id' => 'required',
        //  ];

        // $messages = [
        //     'account_type.required' => 'O campo account_type é obrigatório',
        //     'account_type.in' => 'O campo account_type só pode ser (client)',
        //     'amount.required' => 'Campo amount é obrigatório',
        //     'wallets_id.required' => 'Campo wallets_id é obrigatório',
        // ];

        // $fail = Validator::make($request->all(), $rules, $messages);

        //if ($fail->fails()) return response()->json(['errors' => $fail->errors()], 400);
        //? validacao

        $wallets = Wallet::query()->where('id', $request->wallets_id)->first();

        if (!$wallets) return response()->json(['message' => 'Opção de transferência inválida'], 400);

        if ($request->wallets_id == 2) {

            $this->validate(
                $request,
                [
                    'account_number' => 'required|numeric|digits:9',
                ],
                [
                    'account_number.required' => 'Campo telefone é obrigatório',
                    'account_number.numeric' => 'Campo telefone é numérico',
                    'account_number.digits' => 'Campo telefone deve ter 9 digitos',
                ]
            );

            // $rules = [
            //     'account_number' => 'required|numeric|digits:9',
            // ];

            // $messages = [
            //     'account_number.required' => 'Campo telefone é obrigatório',
            //     'account_number.numeric' => 'Campo telefone é numérico',
            //     'account_number.digits' => 'Campo telefone deve ter 9 digitos',
            //  ];

            //  $fail = Validator::make($request->all(), $rules, $messages);

            //  if ($fail->fails()) return response()->json(['errors' => $fail->errors()], 400);

            $regex = "/^(82|83|84|85|86|87)+[0-9]{7,7}$/";
            if (!preg_match($regex, $request->account_number)) return response()->json(['message' => 'Número de telefone inválido'], 400);

            $operator = Operator::query()->where('code', 'LIKE', '%' . substr($request->account_number, 0, 2) . '%')->first();
            if (!$operator) return response()->json(['message' => 'Número de telefone inválido'], 400);
        }

        if ($request->wallets_id == 1) {
            $this->validate(
                $request,
                [
                    'account_number' => 'required|numeric|digits:21',
                ],
                [
                    'account_number.required' => 'Campo NIB é obrigatório',
                    'account_number.numeric' => 'Campo NIB é númerico',
                    'account_number.digits' => 'Campo NIB deve ter 21 digitos',
                ]
            );

            //$rules = [
            //   'account_number' => 'required|numeric|digits:21',
            // ];

            // $messages = [
            //    'account_number.required' => 'Campo NIB e obrigatorio',
            //    'account_number.numeric' => 'Campo NIB e numerico',
            //    'account_number.digits' => 'Campo NIB deve ter 21 digitos',
            //];

            // $fail = Validator::make($request->all(), $rules, $messages);

            // if ($fail->fails()) return response()->json(['errors' => $fail->errors()], 400);


            $ibanToValidate = "MZ59" . $request->account_number;
            if (!$this->validateIBAN($ibanToValidate)) return response()->json(['message' => 'Número de NIB inválido'], 400);

            $operator = Operator::query()->where('code', 'LIKE', '%' . substr($request->account_number, 0, 4) . '%')->first();
            if (!$operator) return response()->json(['message' => 'Número de NIB inválido'], 400);

            if ($operator->code !== '0034') return response()->json(['message' => 'Serviço de Transferencias interbancária indisponivel. Caso tenha uma conta MOZA tente novamente com o teu NIB MOZA'], 400);
        }

        //? validate amount
        //if (!is_numeric($request->amount)) return response()->json(['message' => 'Montante inválido'], 400);


        // verificacao do nivel de KYC.
        // $kyc = new UserKyc(auth()->user()->id);
        $user = User::getUserDetails(auth()->user()->id);
        $kyc = new UserKyc($user);

        $kycResp = $kyc->checkUserKYC($request->amount);
        if ($kycResp->getStatusCode() == 400) return $kycResp;
        // verificacao do nivel de KYC.

        //if ($request->amount < 0) return response()->json(['message' => 'Montante inválido'], 400);

        if ($request->wallets_id == 1) {
            if ($operator->code == '0034') { //intrabancaria
                $walletsFee = WalletFee::query()
                    ->where('id', 1)
                    ->where('wallets_id', $request->wallets_id)
                    ->first();
            } else { //interbancaria
                $walletsFee = WalletFee::query()
                    ->where('id', 2)
                    ->where('wallets_id', $request->wallets_id)
                    ->first();
            }

            if (!$walletsFee) return response()->json(['message' => 'Operação não pode ser processada'], 400);
        } else {

            $walletsFee = WalletFee::query()
                ->where('wallets_id', $request->wallets_id)
                ->where('min_amount', '<=', $request->amount)
                ->where('max_amount', '>=', $request->amount)
                ->first();

            if (!$walletsFee) return response()->json(['message' => 'Montante inválido'], 400);
        }

        // verificar saldo da conta iMali que esta a fazer a transferencia..
        //$user = auth('api')->user();
        //$imali_account = ImaliAccount::query()->where('user_id', $user->id)->first();
        $total = $request->amount + $walletsFee->imali_fee;

        // Limitando o valor para duas casas decimais
        $total = number_format($total, 2, '.', '');
        $total = floatval($total);

        $kycRespBalance = $kyc->checkUserBalance($total);
        if ($kycRespBalance->getStatusCode() == 400) return $kycRespBalance;

        //if($imali_account->balance < $total) return response()->json(['message' => 'Saldo insuficiente'], 400);


        // verificar nivel de KYC se lhe compete fazer essa transferencia..
        //if(($imali_account->imali_account_config == 1) && ($request->amount > 300)) return response()->json(['message' => 'O seu nível de KYC não permite fazer a transação'], 400);


        if ($request->wallets_id == 1) {
            $data = [
                'account_number' => $request->account_number,
                'account_type' => $request->account_type,
                'amount' => $request->amount,
                'wallets_id' => $request->wallets_id,
                'operators_id' => $operator->id,
                'total' => $total,
                'imali_fee' => $walletsFee->imali_fee,
                'commission' => $walletsFee->commission,
                'bank_fee' => $walletsFee->bank_fee,
                'stamp_tax' => $walletsFee->stamp_tax
            ];

            return response()->json($data, 200);
        } else {

            $data = [
                'account_number' => $request->account_number,
                'account_type' => $request->account_type,
                'amount' => $request->amount,
                'wallets_id' => $request->wallets_id,
                'operators_id' => $operator->id,
                'total' => $total,
                'imali_fee' => $walletsFee->imali_fee,
                'commission' => $walletsFee->commission,
                'bank_fee' => $walletsFee->bank_fee,
                'stamp_tax' => $walletsFee->stamp_tax
            ];

            return response()->json($data, 200);
        }
    }

    function validateIBAN($iban)
    {
        // Remover espaços e caracteres não numéricos do IBAN
        $iban = preg_replace('/\s+/', '', $iban);

        // Verificar se o IBAN tem o comprimento correto para Moçambique (25 caracteres)
        if (strlen($iban) !== 25) {
            return false;
        }

        // Mover os primeiros 4 caracteres para o final do IBAN
        $iban = substr($iban, 4) . substr($iban, 0, 4);

        // Substituir letras por números (A=10, B=11, ..., Z=35)
        $ibanNumeric = '';
        foreach (str_split($iban) as $char) {
            if (ctype_alpha($char)) {
                $ibanNumeric .= ord(strtoupper($char)) - ord('A') + 10;
            } else {
                $ibanNumeric .= $char;
            }
        }

        // Verificar se o IBAN é divisível por 97
        if (bcmod($ibanNumeric, '97') !== '1') {
            return false;
        }

        return true;
    }


    public function checkNIB(Request $request)
    {
        $this->validate(
            $request,
            [
                'account_number' => 'required|numeric|digits:21',
            ],
            [
                'account_number.required' => 'Campo NIB é obrigatório',
                'account_number.numeric' => 'Campo NIB é númerico',
                'account_number.digits' => 'Campo NIB deve ter 21 digitos',
            ]
        );

        //$rules = [
        //     'account_number' => 'required|numeric|digits:21',
        // ];

        // $messages = [
        //     'account_number.required' => 'Campo NIB e obrigatorio',
        //     'account_number.numeric' => 'Campo NIB e numerico',
        //     'account_number.digits' => 'Campo NIB deve ter 21 digitos',
        // ];

        // $fail = Validator::make($request->all(), $rules, $messages);
        // if ($fail->fails()) return response()->json(['errors' => $fail->errors()], 400);

        if (!$this->validateIBAN("MZ59" . $request->account_number)) return response()->json(['message' => 'NIB inválido'], 400);

        return response()->json(['message' => 'NIB válido'], 200);
    }


    //? reset PIN
    public function resetPIN(Request $request)
    {
        //
        // $user = User::where('email', $request->email)->orWhere('username', $request->email)->first();
        $user = User::where('email', $request->email)->first();

        $messageError = "O email não foi encontrado!";
        if (!$user) if ($request->wantsJson()) {
            // return JSON-formatted response
            return response()->json(['message' => $messageError], 404);
        } else {
            // return HTML response
            return view('email-not-found', compact('messageError'));
        }

        // return response()->json(['message' => $messageError], 404);

        $validate = EmailValidation::query()->where('email', $request->email)->first();

        // $user = User::query()->where('email', $request->email)->first();
        $token = $user->createToken('TokenName')->accessToken;

        $convert = strtotime(date('Y-m-d H:i:s')) + (60 * 10);
        $duration = date("Y-m-d H:i:s", $convert);

        if (!$validate) {
            EmailValidation::create([
                'email' => $request->email,
                'codigo' => $token,
                'is_Validate' => 0,
                'duration' => $duration
            ]);
        } else {
            $validate->duration = $duration;
            $validate->codigo = $token;
            $validate->status = 'active';
            $validate->update();
        }

        try {
            //code...
            Mail::to($user->email)->send(new ResetPinEmail($user, $token));
            $message = "Foi enviado um email para a tua caixa de correio eletrônico. Clique no link enviado para redefinir o teu PIN";

            if ($request->wantsJson()) {
                // return JSON-formatted response
                return response()->json(['message' => $message], 200);
            } else {
                // return HTML response
                return view('email-sent', compact('message'));
            }
        } catch (\Throwable $th) {
            //throw $th;
            $message = "O teu Email não foi enviado";

            if ($request->wantsJson()) {
                // return JSON-formatted response
                return response()->json(['message' => $message], 400);
            } else {
                // return HTML response
                return view('email-not-sent', compact('message'));
            }
        }

        // return response()->json(['message' => 'definir-pin'.$token], 200);
        // return response()->json(['message' => 'Email enviado com sucesso'], 200);
    }


    public function definirPin($token)
    {
        // Verifique se o token é válido (você precisará implementar esta lógica)
        // $user = User::where('pin_reset_token', $token)->first();
        $user = EmailValidation::where('codigo', $token)->first();
        if (!$user) return response()->json(['message' => 'token invalido'], 400);

        $is_expired = strtotime($user->duration) - strtotime(date('Y-m-d H:i:s'));

        if ($is_expired < 0) {
            $user->status = 'expired';
            $user->update();

            $message = "Token Expirado";

            return view('email-not-sent', compact('message'));
        }

        $errors = Validator::make([], [])->errors();

        // Passe o usuário e o token para a view
        return view('definir-pin', compact('user', 'token', 'errors'));
    }


    public function salvarPin(Request $request)
    {

        // $request->validate([
        //     'new_pin' => ['required', new PinValidation],
        //     'confirm_new_pin' => ['required', new PinValidation],
        // ]);

        $rules = [
            'new_pin' => 'required|max:4|same:confirm_new_pin',
            'confirm_new_pin' => 'required|max:4',
        ];

        $messages = [
            'new_pin.required' => 'O PIN é Obrigatório',
            'confirm_new_pin.required' => 'O Campo Confirmar PIN é Obrigatório',
            'new_pin.same' => 'Senhas incompatíveis',
            'new_pin.max' => 'A PIN deve ter 4 digitos no maximo',
            'confirm_new_pin.max' => 'A PIN deve ter 4 digitos no maximo'
        ];

        $validator = Validator::make($request->all(), $rules, $messages);

        if ($validator->fails()) {
            // $errors = Arr::flatten($validator->messages()->toArray());
            // return response()->json(['state' => 412, 'message' => $errors], 200);
            // return Redirect::back()->with($errors);
            // $errors=$errors;
            // dd($token);
            // return Redirect::route('definir-pin', [$request->token])->with($validator->);
            // return to_route('definir-pin',[$request->token])->withErrors();
            // return Redirect::back()->withInput();
            return back()->with(['errors', $validator->errors()]);
            // return view('definir-pin', compact('token'))->with('errors', $errors);
        }

        // return $request->token;

        // $this->validate(
        //     $request,
        //     [
        //         'new_pin' => ['required|max:4|same:confirm_new_pin'],
        //         'confirm_new_pin' => 'required|max:4',
        //     ],
        //     [
        //         'new_pin.required' => 'O PIN é Obrigatório',
        //         'confirm_new_pin.required' => 'O Campo Confirmar PIN é Obrigatório',
        //         'new_pin.same' => 'Senhas incompatíveis',
        //         'new_pin.max' => 'A PIN deve ter 4 digitos no maximo',
        //         'confirm_new_pin.max' => 'A PIN deve ter 4 digitos no maximo'
        //     ]
        // );

        // if ($validator->fails()) {
        //     return Redirect::back()->withErrors($validator);
        // }


        // $user = User::where('pin_reset_token', $token)->first();
        $user = EmailValidation::where('codigo', $request->token)->first();

        // return $user;

        if (!$user) return response()->json(['message' => 'token invalido....'], 400);

        if ($user->status === 'expired') return response()->json(['message' => 'Token expirado'], 400);

        $userFinal = User::where('email', $user->email)->first();

        //Salve o novo PIN
        $userFinal->update([
            'pin' => Hash::make($request->confirm_new_pin),
        ]);

        $convert = strtotime(date('Y-m-d H:i:s')) - (60 * 10);
        $duration = date("Y-m-d H:i:s", $convert);

        $user->update([
            'is_Validated' => 1,
            'status' => 'used',
            'duration' => $duration
        ]);

        //$user->update([
        //    'is_Validated' => 1,
        //    'status' => 'used',
        //    'duration' => date('Y-m-d H:i:s') - (60*5)
        //]);

        //$user->is_Validated = 1;
        //$user->status = 'used';
        //$user->duration = date('Y-m-d H:i:s') - (60 * 5);
        //$user->save();

        // Redirecione para a página de sucesso ou qualquer outra página desejada
        // return redirect()->route('pagina-de-sucesso');
        // return response()->json(['message' => 'Pin redefinido com sucesso'], 200);
        $message = "O seu PIN foi redefinido com sucesso";
        // return view('email-sent', compact('message'));

        if ($request->wantsJson()) {
            // return JSON-formatted response
            return response()->json(['message' => $message], 200);
        } else {
            // return HTML response
            // return view('email-not-sent', compact('message'));
            // $message = "O seu PIN foi redefinido com sucesso";
            return view('email-sent', compact('message'));
        }
    }

    public function checkContact(Request $request)
    {
        $this->validate(
            $request,
            [
                'phone' => 'required|numeric|digits:9',
            ],
            [
                // 'phone.required' => 'Campo Phone é obrigatório',
                // 'phone.numeric' => 'Campo Phone é númerico',
                // 'phone.digits' => 'Campo Phone deve ter 9 digitos',

                'phone.required' => 'Número telefone é obrigatório',
                'phone.numeric' => 'Número telefone é númerico',
                'phone.digits' => 'Número de telefone deve ter 9 digitos',
            ]
        );

        //$phone_exist = UserRechargPhone::query()->where('phone', $request->phone)->first();
        $phone_exist = UserRechargPhone::query()->where('phone', $request->phone)->where('user_id', auth('api')->user()->id)->first();
        if ($phone_exist) return response()->json(['message' => "Este contacto já está em uso!"], 400);

        $prefix = substr($request->phone, 0, 2);

        if ($prefix == 84 || $prefix == 85) {
            $phones = UserRechargPhone::query()->where('user_id', auth('api')->user()->id)->where('operator_name', 'vodacom')->count();
            if ($phones == 3) return response()->json(['message' => "Atingiu o limite de contactos para a operadora Vodacom"], 400);
        }
        if ($prefix == 82 || $prefix == 83) {
            $phones = UserRechargPhone::query()->where('user_id', auth('api')->user()->id)->where('operator_name', 'tmcel')->count();
            if ($phones == 3) return response()->json(['message' => "Atingiu o limite de contactos para a operadora Tmcel"], 400);
        }
        if ($prefix == 86 || $prefix == 87) {
            $phones = UserRechargPhone::query()->where('user_id', auth('api')->user()->id)->where('operator_name', 'movitel')->count();
            if ($phones == 3) return response()->json(['message' => "Atingiu o limite de contactos para a operadora Movitel"], 400);
        }

        return $this->resendCode($request);
    }

    public function addContact(Request $request)
    {
        $this->validate(
            $request,
            [
                'token' => 'required|numeric|digits:6',
            ],
            [
                'token.required' => 'Campo token é obrigatório',
                'token.numeric' => 'Campo token é númerico',
                'token.digits' => 'Campo token deve ter 6 digitos',
            ]
        );

        $phone = PhoneValidation::query()->where('codigo', $request->token)->first();
        if (!$phone) return response()->json(['message' => "Token invalido"], 404);

        $is_expired = strtotime($phone->expire_at) - strtotime(date('Y-m-d H:i:s'));
        if ($is_expired < 0) return response()->json(['message' => "Token expirado"], 404);

        $operator_name = '';
        $prefix = substr($phone->phone, 0, 2);
        if ($prefix == 84 || $prefix == 85)
            $operator_name = 'vodacom';
        else if ($prefix == 82 || $prefix == 83)
            $operator_name = 'tmcel';
        else if ($prefix == 86 || $prefix == 87)
            $operator_name = 'movitel';
        else
            $operator_name = 'desconhecido';

        UserRechargPhone::create([
            'operator_name' => $operator_name,
            'phone' => $phone->phone,
            'user_id' => auth('api')->user()->id
        ]);

        $convert = strtotime(date('Y-m-d H:i:s')) - (60 * 10);
        $duration = date("Y-m-d H:i:s", $convert);

        $phone->is_Validated = 1;
        $phone->expire_at = $duration;
        $phone->update();

        return response()->json(['message' => "Contacto adicionado com sucesso!!"], 200);
    }


    public function removeContact(Request $request)
    {
        $this->validate(
            $request,
            [
                'phone' => 'required|numeric|digits:9',
            ],
            [
                // 'phone.required' => 'Campo Phone é obrigatório',
                // 'phone.numeric' => 'Campo Phone é númerico',
                // 'phone.digits' => 'Campo Phone deve ter 9 digitos',

                'phone.required' => 'Número telefone é obrigatório',
                'phone.numeric' => 'Número telefone é númerico',
                'phone.digits' => 'Número de telefone deve ter 9 digitos',
            ]
        );

        $phone_validation = PhoneValidation::query()->where('phone', $request->phone)->first();
        if (!$phone_validation) return response()->json(['message' => "Contacto invalido"], 404);

        $phone = UserRechargPhone::query()->where('phone', $request->phone)->where('user_id', auth('api')->user()->id)->first();
        if (!$phone) return response()->json(['message' => "Contacto nao encontrado"], 404);

        try {
            //code...
            $phone_validation->delete();
            $phone->delete();
            return response()->json(['message' => 'Contacto removido com sucesso.'], 200);
        } catch (\Throwable $th) {
            //throw $th;
            return response()->json(['message' => 'Nao foi possivel remover o seu contacto'], 500);
        }
    }

    public function getMyConctacts()
    {
        $phones = UserRechargPhone::query()
            ->orderBy('user_recharg_phones.created_at', 'desc')
            ->select('user_recharg_phones.*')
            ->where('user_id', auth('api')->user()->id)
            ->get();

        return response()->json(['data' => $phones], 200);
    }

    public function checkDefaultNumber(Request $request)
    {
        $this->validate(
            $request,
            [
                'phone' => 'required|numeric|digits:9',
            ],
            [
                'phone.required' => 'Campo Phone é obrigatório',
                'phone.numeric' => 'Campo Phone é númerico',
                'phone.digits' => 'Campo Phone deve ter 9 digitos',
            ]
        );

        $user_total = User::query()->where('phone', $request->phone)->count();

        if ($user_total > 0) return response()->json(['message' => "Este contacto está em uso!"], 404);

        return $this->resendCode($request);
    }

    public function changeDefaultNumber(Request $request)
    {
        $this->validate(
            $request,
            [
                'token' => 'required|numeric|digits:6',
            ],
            [
                'token.required' => 'Campo token é obrigatório',
                'token.numeric' => 'Campo token é númerico',
                'token.digits' => 'Campo token deve ter 6 digitos',
            ]
        );

        $phone = PhoneValidation::query()->where('codigo', $request->token)->first();
        if (!$phone) return response()->json(['message' => "Token invalido"], 400);

        $is_expired = strtotime($phone->expire_at) - strtotime(date('Y-m-d H:i:s'));

        if ($is_expired < 0) return response()->json(['message' => "Token expirado"], 400);

        $user = User::query()->where('id', auth('api')->user()->id)->first();
        $user->phone = $phone->phone;
        $phone2 = PhoneValidation::query()->where('phone', auth('api')->user()->phone)->first();
        if ($phone2) $phone2->forceDelete();
        $convert = strtotime(date('Y-m-d H:i:s')) - (60 * 10);
        $duration = date("Y-m-d H:i:s", $convert);
        $phone->expire_at = $duration;
        $phone->is_Validated = 1;
        $phone->update();
        $user->update();

        return response()->json(['message' => "Contacto actualizado"], 200);
    }


    public function createSubAccounts2024(Request $request)
    {

        // return "Chegou";

        $this->validate(
            $request,
            [
                'name' => 'required',
                'sub_account_types_id' => 'required',
            ],
            [
                'name.required' => 'Campo name é obrigatório',
                'sub_account_types_id.required' => 'Campo sub_account_types_id é obrigatório',
            ]
        );

        // todo -------------------teste de criacao de conta
        // Verificar o limite de subcontas  que podem ser criadas

        $userAuth = User::getUserDetails(auth()->user()->id);

        $nr_subaccounts = ImaliSubAccount::where('main_account_number', $userAuth->account_number)
            ->get()->count();

        $last_subaccount = ImaliSubAccount::where('main_account_number', $userAuth->account_number)
            ->orderBy('id', 'desc')->first();

        if ($nr_subaccounts != 0) {

            $last_subaccount_len = (int)strlen($last_subaccount->account_number);

            if ($nr_subaccounts >= 9 || $last_subaccount_len > 9) return response()->json(['message' => 'Atingui o limite de subcontas.'], 404);
        }

        // todo -------------------teste de criacao de conta

        if ($request->store_account_number) {

            // Buscar a loja onde se fara o pagamento
            $store_account = Store::getStoreAccount($request->store_account_number);
            // return $store_account;
            if (!$store_account)  return response()->json(['message' => 'Comerciante invalido'], 400);
        }



        // if ($request->has('has_card_associated') && $request->has_card_associated) {
        //     $this->validate(
        //         $request,
        //         [
        //             'card_number' => 'required|unique:imali_sub_accounts',
        //         ],
        //         [
        //             'card_number.required' => 'Campo card_number é obrigatório',
        //             'card_number.unique' => 'Campo card_number ja existe',
        //         ]
        //     );
        // }
        // Obter detalhes do usuário autenticado

        // ->get(['account_number'])
        // ->pluck('account_number');

        $account_generator = new GenerateImaliAccount();
        $newSubaccount = $account_generator->generateSubImaliAccount2024();
        return $newSubaccount;

        // Buscar dados do User que faz a transacao
        $userAuth = User::getUserDetails(auth()->user()->id);

        // Buscar dados da conta do User que faz a transacao
        $imaliAccount = User::getAccountByUser($userAuth->id, $userAuth->account_id);

        // tabela de iMaliSubAccount
        $imaliSubAccount = new ImaliSubAccount();
        $imaliSubAccount->name = $request->name;
        $imaliSubAccount->account_number = $newSubaccount;
        $imaliSubAccount->sub_account_types_id = $request->sub_account_types_id;
        $imaliSubAccount->user_id = $userAuth->id;
        $imaliSubAccount->main_account_id = $imaliAccount->id;
        $imaliSubAccount->main_account_number = $imaliAccount->account_number;

        if ($request->store_account_number)
            $imaliSubAccount->store_id = $store_account->id;

        // if ($request->has('has_card_associated') && $request->has_card_associated) {
        //     $imaliSubAccount->card_number = $request->card_number;
        //     $imaliSubAccount->has_card_associated = $request->has_card_associated;
        // }


        // Verifica se o campo card_number foi preenchido
        if ($request->filled('card_number')) {
            $sub_account = ImaliSubAccount::query()->where('card_number', $request->card_number)->first();
            if ($sub_account) return response()->json(['message' => 'Este número de cartão já está associado a uma conta.'], 400);

            $imaliSubAccount->card_number = $request->card_number;
            $imaliSubAccount->has_card_associated = 1;
        }


        try {
            $imaliSubAccount->save();
            return response()->json(['message' => 'SubConta criada com sucesso!'], 200);
        } catch (\Exception $e) {
            return response()->json(['message' => 'Erro ao salvar' . $e], 500);
        }
    }


    public function createSubAccounts(Request $request)
    {
        $this->validate(
            $request,
            [
                'name' => 'required',
                'sub_account_types_id' => 'required',
            ],
            [
                'name.required' => 'Campo name é obrigatório',
                'sub_account_types_id.required' => 'Campo sub_account_types_id é obrigatório',
            ]
        );


        // Verificar o limite de subcontas  que podem ser criadas

        $userAuth = User::getUserDetails(auth()->user()->id);

        $nr_subaccounts = ImaliSubAccount::where('main_account_number', $userAuth->account_number)
            ->get()->count();

        $last_subaccount = ImaliSubAccount::where('main_account_number', $userAuth->account_number)
            ->orderBy('id', 'desc')->first();

        if ($nr_subaccounts != 0) {

            $last_subaccount_len = (int)strlen($last_subaccount->account_number);

            if ($nr_subaccounts >= 9 || $last_subaccount_len > 9) return response()->json(['message' => 'Atingiu o limite de subcontas.'], 404);
        }

        // todo -------------------teste de criacao de conta


        if ($request->store_account_number) {

            // Buscar a loja onde se fara o pagamento
            $store_account = Store::getStoreAccount($request->store_account_number);
            // return $store_account;
            if (!$store_account)  return response()->json(['message' => 'Comerciante invalido'], 400);
        }

        //if ($request->has('has_card_associated') && $request->has_card_associated) {
        //    $this->validate(
        //        $request,
        //        [
        //            'card_number' => 'required|unique:imali_sub_accounts',
        //        ],
        //        [
        //            'card_number.required' => 'Campo card_number é obrigatório',
        //            'card_number.unique' => 'Campo card_number ja existe',
        //        ]
        //    );
        // }

        $account_generator = new GenerateImaliAccount();
        $newSubaccount = $account_generator->generateSubImaliAccount();

        // Buscar dados do User que faz a transacao
        $userAuth = User::getUserDetails(auth()->user()->id);

        // Buscar dados da conta do User que faz a transacao
        $imaliAccount = User::getAccountByUser($userAuth->id, $userAuth->account_id);

        // tabela de iMaliSubAccount
        $imaliSubAccount = new ImaliSubAccount();
        $imaliSubAccount->name = $request->name;
        $imaliSubAccount->account_number = $newSubaccount;
        $imaliSubAccount->sub_account_types_id = $request->sub_account_types_id;
        $imaliSubAccount->user_id = $userAuth->id;
        $imaliSubAccount->main_account_id = $imaliAccount->id;
        $imaliSubAccount->main_account_number = $imaliAccount->account_number;


        if ($request->store_account_number)
            $imaliSubAccount->store_id = $store_account->id;

        //if ($request->has('has_card_associated') && $request->has_card_associated) {
        //    $imaliSubAccount->card_number = $request->card_number;
        //    $imaliSubAccount->has_card_associated = $request->has_card_associated;
        //}


        $sub_account_type = SubAccountType::find($request->sub_account_types_id);
        if ($sub_account_type && $sub_account_type->type_id === 'NFC_CARD') {

            $this->validate(
                $request,
                [
                    'card_number' => 'required|unique:imali_sub_accounts',
                    'store_account_number' => 'required',
                ],
                [
                    'card_number.required' => 'Número de cartão é obrigatório',
                    'card_number.unique' => 'Número de cartão já existe',
                    'store_account_number.required' => 'O campo número de conta de comerciante é obrigatório',
                ]
            );

            $sub_account = ImaliSubAccount::query()->where('card_number', $request->card_number)->first();
            if ($sub_account) return response()->json(['message' => 'Este número de cartão já está associado a uma conta.'], 400);

            $imaliSubAccount->card_number = $request->card_number;
            $imaliSubAccount->has_card_associated = 1;

            $imaliSubAccount->is_credit_allowed = 1;
            $imaliSubAccount->is_debit_allowed = 0;
        } else if ($sub_account_type && $sub_account_type->type_id === 'BNPL') {

            $imaliSubAccount->is_credit_allowed = 0;
            $imaliSubAccount->is_debit_allowed = 0;
        }


        // Verifica se o campo card_number foi preenchido
        //if ($request->filled('card_number')) {

        //    $sub_account = ImaliSubAccount::query()->where('card_number', $request->card_number)->first();
        //    if ($sub_account) return response()->json(['message' => 'Este número de cartão já está associado a uma conta.'], 400);

        //    $imaliSubAccount->card_number = $request->card_number;
        //    $imaliSubAccount->has_card_associated = 1;
        // }

        try {
            $imaliSubAccount->save();
            return response()->json(['message' => 'SubConta criada com sucesso!'], 200);
        } catch (\Exception $e) {
            return response()->json(['message' => 'Erro ao salvar' . $e], 500);
        }
    }


    public function createSubAccountsTypes(Request $request)
    {
        $this->validate(
            $request,
            [
                'name' => 'required',
                'short_description' => 'required',
                'long_description' => 'required',
            ],
            [
                'name.required' => 'Campo name e obrigatorio',
                'short_description.required' => 'Campo short_description e obrigatorio',
                'long_description.required' => 'Campo long_description e obrigatorio',
            ]
        );

        $sub_account = new SubAccountType();
        $sub_account->name = $request->name;
        $sub_account->short_description = $request->short_description;
        $sub_account->long_description = $request->long_description;

        $sub_account->type_id = $request->type_id;
        $sub_account->name_en = $request->name_en;
        $sub_account->short_description_en = $request->short_description_en;
        $sub_account->long_description_en = $request->long_description_en;

        if ($sub_account) {
            try {
                $sub_account->save();
                return response()->json(['message' => 'Adicionado com sucesso!'], 200);
            } catch (\Exception $e) {
                return response()->json(['message' => 'Erro ao salvar'], 500);
            }
        } else {
            return response()->json(['message' => 'Nao pode registar os dados informados ja estao em uso'], 400);
        }
    }


    public function deleteSubAccounts(Request $request)
    {
        $this->validate(
            $request,
            [
                'account_number' => 'required',
            ],
            [
                'account_number.required' => 'Campo account_number é obrigatório',
            ]
        );

        $sub_account = ImaliSubAccount::query()->where('account_number', $request->account_number)->first();

        if (!$sub_account) return response()->json(['message' => 'Conta não encontrada.'], 400);

        /* dados da subconta */
        // return response()->json(['data' => $sub_account], 200);

        // $imaliaccount_has_adr = SubAccountDeletionRequest::query()->where('account_number', $request->account_number)->first();

        // if ($imaliaccount_has_adr) return response()->json(['message' => 'A subconta ' . $request->account_number . ', já efectuou um pedido de cancelamento.'], 400);

        // if ($sub_account->balance >= 1 || $sub_account->captive_balance >= 1) {

        //    SubAccountDeletionRequest::create([
        //        'account_number' => $request->account_number,
        //        'main_account_number' => $sub_account->main_account_number,
        //        'user_id' => auth('api')->user()->id
        //    ]);

        //    $sub_account->status = 0;
        //    $sub_account->update();

        //   return response()->json(['message' => 'Pedido de exclusão de subconta foi enviado com sucesso!'], 200);
        //}

        if ($sub_account->balance > 0) return response()->json(['message' => 'Não é possível excluir a tua subconta imali, pois ainda tem saldo disponível.'], 400);
        // if ($sub_account->captive_balance > 0) return response()->json(['message' => 'Não é possível excluir a tua subconta imali, pois tens transaçõs por serem concluídas.'], 400);

        // Validar o PIN e Fingerprint do userPayer
        $auth = new Auth();
        $authResp = $auth->checkUserPinAndFingerprint($request);
        if ($authResp->getStatusCode() != 200) return $authResp;

        if ($sub_account) $sub_account->delete();

        return response()->json(['message' => 'Conta removida com sucesso.'], 200);
    }


    public function updateSubAccounts(Request $request, $account_number)
    {

        $sub_account = ImaliSubAccount::query()->where('account_number', $account_number)->first();

        if (!$sub_account) return response()->json(['message' => 'Subconta não encontrada.'], 400);

        //$subAccountCard = ImaliSubAccount::query()->where('card_number', $request->card_number)->first();
        $subAccountCard = ImaliSubAccount::query()->where('card_number', $request->card_number)->where('account_number', '!=', $account_number)->first();

        // Verifica se o card_number foi informado e se já existe um sub_account com o mesmo card_number
        if ($request->filled('card_number') && $subAccountCard) {
            // return redirect()->route('sua_rota')->with('error', 'Já existe uma conta associada a este número de cartão.');
            return response()->json(['message' => 'Já existe uma conta associada a este número de cartão.'], 400);
        }

        // Se o card_number foi informado, atualiza o sub_account
        if ($request->filled('card_number')) {
            $sub_account->card_number = $request->card_number;
        }

        // Atualiza outros campos, como o nome
        $sub_account->name = $request->filled('name') ? $request->name : $sub_account->name;

        // Verifica se o campo card_number foi preenchido
        if ($request->filled('card_number')) {
            $sub_account->has_card_associated = 1;
        }

        $sub_account->update();

        return response()->json(['message' => 'Dados da subconta alterados com sucesso.'], 200);
    }

    public function getSubAccounts()
    {
        // $userAuth = User::getUserDetails(auth()->user()->id);
        // // return $userAuth->balance;
        // $subaccounts = ImaliSubAccount::query()->where('imali_account_id', $userAuth->account_number)->get();
        // return $subaccounts;

        $userAuth = User::getUserDetails(auth()->user()->id);
        // $subaccounts = ImaliAccount::query()->where('imali_account_id', $userAuth->account_number)->get();
        // $subaccounts = ImaliSubAccount::query()->where('imali_account_id', $userAuth->account_number)->get();

        //ORIGINAL
        // $subaccounts = ImaliSubAccount::query()->where('main_account_number', $userAuth->account_number)->get();


        // trazer resultados de $subaccounts mesmo quando store_id for igual a null,
        //  você pode usar uma cláusula leftJoin em vez de join. Isso garantirá que
        //   todas as linhas da tabela ImaliSubAccount sejam retornadas, independentemente
        //    de haver uma correspondência na tabela stores.

        $subaccounts = ImaliSubAccount::query()
            ->leftJoin('stores', 'stores.id', '=', 'imali_sub_accounts.store_id')
            ->select('imali_sub_accounts.*', 'stores.account_number as store_account_number')
            ->where('imali_sub_accounts.main_account_number', $userAuth->account_number)
            ->get();

        //$subaccounts = ImaliSubAccount::query()
        //  ->join('stores', 'stores.id', 'store_id')
        //  ->select('imali_sub_accounts.*', 'stores.account_number as store_account_number')
        //  ->where('main_account_number', $userAuth->account_number)
        //  ->get();

        // Adicionar o balance principal na query com um nome diferente para cada item em $subaccounts
        $subaccountsWithBalance = $subaccounts->map(function ($subaccount) use ($userAuth) {
            $subaccount->main_balance = $userAuth->balance;
            return $subaccount;
        });

        return response()->json(['data' => $subaccountsWithBalance], 200);
    }

    public function getSubAccountsTypes()
    {
        $subaccounts = SubAccountType::all();

        //return $subaccounts;
        return response()->json(['data' => $subaccounts], 200);
    }


    public function getSubAccountsTransactionsOLD()
    {
        $userAuth = User::getUserDetails(auth()->user()->id);
        $subaccounts = ImaliSubAccount::query()->where('main_account_number', $userAuth->account_number)->first();
        $card = $subaccounts->card_number;


        $transaction = Payment::query()
            ->join('stores', 'stores.id', 'payments.store_id')
            ->where('sender_card_number', $card)
            ->select(
                'payments.id',
                'transaction_id',
                'amount',
                'estado',
                DB::raw("'Pagamento' as description"),
                'payment_type',
                'sender_name',
                'sender_account_number',
                'sender_card_number',
                'store_id',
                'stores.name as store_name',
                'payments.status',
                'payments.created_at',
                'payments.updated_at'
            )->get();

        //return $transaction;
        return response()->json(['data' => $transaction], 200);
    }


    // Transacoes das subcontas
    public function getSubAccountsTransactions_SERVER(Request $request)
    {

        $size = (!request()->per_page) ? 4 : request()->per_page;

        $userAuth = User::getUserDetails(auth()->user()->id);

        $subaccounts = ImaliSubAccount::query()
            ->where('main_account_number', $userAuth->account_number)
            ->get();

        $accountNumbers = $subaccounts->pluck('account_number')->toArray();

        $subConta = ImaliSubAccount::query()
            ->where('account_number', $request->subaccount_number)
            ->first();

        if (!$subConta) return response()->json(['message' => 'A subconta informada não foi encontrada.'], 400);

        // Obter transações normais
        $payments = Payment::query()
            ->join('stores', 'stores.id', 'payments.store_id')
            ->whereIn('sender_account_number', $accountNumbers)

            ->orWhere('sender_account_number', $subConta->account_number)

            ->select(
                'payments.id',
                'transaction_id',
                'amount',
                'transaction_type',
                'transaction_name',
                'estado',
                'payment_type',
                'sender_name',
                'sender_account_number',
                'sender_card_number',
                'store_id',
                'stores.name as store_name',
                'payments.status',
                'payments.created_at',
                'payments.updated_at'
            );
        //->get();


        $transfers = Transfer::query()
            ->join('transfer_histories', 'transfer_histories.transaction_id', '=', 'transfers.transaction_id')
            ->whereIn('sender_account', $accountNumbers)
            ->orWhere(function ($query) use ($userAuth, $subConta) {
                $query->where('sender_account', '=', $userAuth->account_number)
                    ->where('reciever_account', '=', $subConta->account_number);
            })
            ->orWhere(function ($query) use ($subConta, $userAuth) {
                $query->where('sender_account', '=', $subConta->account_number)
                    ->where('reciever_account', '=', $userAuth->account_number);
            })
            ->select(
                'transfer_histories.id',
                'transfer_histories.transaction_id',
                'transfer_histories.amount',
                'transfer_histories.transaction_type',
                'transfer_histories.transaction_name',
                'transfer_histories.estado',
                'transfers.sender_id',
                'transfers.sender_name',
                'transfers.sender_account',
                'transfers.reciever_id',
                'transfers.reciever_name',
                'transfers.reciever_account',
                'transfers.status',
                'transfer_histories.created_at',
                'transfer_histories.updated_at'
            );
        //->get();

        // Unir os resultados de $transfers e $payments
        //$allData = $payments->concat($transfers);
        $allData = $payments->union($transfers)->paginate($size);

        return response()->json($allData, 200);
        //return response()->json(['data' => $allData], 200);
    }



    // NOVO METODO
    public function getMyTransactionSubAccount(Request $request)
    {
        // $size = $request->per_page ?? 100;
        $size = (!request()->per_page) ? 100 : request()->per_page;

        if (!User::is_subAccount($request->subaccount_number)) return response()->json(['data' => []], 400);

        // Verificar se a subconta fornecida existe
        $subConta = ImaliSubAccount::where('account_number', $request->subaccount_number)->first();
        if (!$subConta) return response()->json(['data' => []], 400);

        $sub_account_type = SubAccountType::where('id', $subConta->sub_account_types_id)->first();

        if ($sub_account_type && $sub_account_type->type_id == 'NFC_CARD') {
            $myPayments = $this->getMySubAccountPayments($subConta, $size);

            return response()->json($myPayments, 200);
        } else if ($sub_account_type && $sub_account_type->type_id == 'BNPL') {
            $myPayments = $this->getSubAccountKRBPayments($subConta, $size);

            return response()->json($myPayments, 200);
        } else {

            // Transferencia
            $myTransfers = $this->getMySubAccountTransfers($subConta, $size);
            return response()->json($myTransfers, 200);
        }
    }


    private function getMySubAccountPayments($subConta, $size)
    {
        $payments = Payment::join('stores', 'stores.id', 'payments.store_id')
            ->where('sender_card_number', $subConta->card_number)
            ->where('payments.created_at', '>=', $subConta->created_at)
            ->orderByDesc('payments.created_at')
            ->select([
                'payments.id',
                'transaction_id',
                'amount',
                'transaction_type',
                'transaction_name',
                'estado',
                'payment_type',
                'sender_name',
                'sender_account_number',
                'sender_card_number',
                'store_id',
                'stores.name as store_name',
                DB::raw(
                    "CASE WHEN payments.status = 'success' THEN 'Sucesso'
                        WHEN payments.status = 'pending' THEN 'Pendente'
                        WHEN payments.status = 'completed' THEN 'Concluído'
                        WHEN payments.status = 'failed' THEN 'Falhou'
                        ELSE payments.status END as status"
                ),
                'payments.created_at',
                'payments.updated_at'
            ]);

        return $payments->orderByDesc('created_at')->paginate($size);
    }


    public function getSubAccountKRBPayments999($subConta, $size)
    {
        // Definir o tamanho padrão da página se não especificado
        // $size = $request->per_page ?? 5;

        // Verificar se a subconta fornecida existe
        return $subConta = ImaliSubAccount::where('account_number', $subConta)->first();

        if (!$subConta) {
            return SendResponse::errorResp404notfound('Número de conta inválido', 'Invalid Account Number');
        }

        $sub_account_type = SubAccountType::query()->where('id', $subConta->sub_account_types_id)->first();
        if ($sub_account_type === null || $sub_account_type->type_id != 'BNPL') {
            return SendResponse::errorResp400('Tipo de conta inválido', 'Invalid Account Type');
        }

        // Obter transações normais
        $payments = Payment::join('stores', 'stores.id', 'payments.store_id')
            ->where('sender_account_number',  $subConta->subaccount_number)
            ->where('payments.created_at', '>=', $subConta->created_at)
            ->orderByDesc('payments.created_at')
            ->select([
                'payments.id',
                'transaction_id',
                'amount',
                DB::raw("'Pagamento' as transaction_type"),
                DB::raw("'Pagamento normal' as transaction_name"),
                'sender_name',
                'sender_account_number',
                DB::raw("CASE WHEN payments.status = 'success' THEN 'Sucesso'
                      WHEN payments.status = 'pending' THEN 'Pendente'
                      WHEN payments.status = 'completed' THEN 'Concluído'
                      WHEN payments.status = 'failed' THEN 'Falhou'
                      ELSE payments.status END as status"),
                'payments.created_at',
                'payments.updated_at'
            ]);

        // Obter recargas
        $recharge = RechargeImaliAccount::query()
            ->join('users', 'users.id', 'recharge_imali_accounts.user_id')
            ->where('account_reference', $subConta)
            ->where('recharge_imali_accounts.created_at', '>=', $subConta->created_at)
            ->select([
                'recharge_imali_accounts.id',
                'transaction_id',
                'amount',
                DB::raw("'Recarga' as transaction_type"),
                DB::raw("'Recarga iMali' as transaction_name"),
                'recharge_way',
                'users.name as sender_name',
                'account_reference as sender_account_number',
                'recharge_imali_accounts.estado as status',
                'recharge_imali_accounts.created_at',
                'recharge_imali_accounts.updated_at'
            ]);

        // Unir os dados e aplicar paginação
        $allData = $payments->union($recharge)->orderByDesc('created_at')->paginate($size);

        return SendResponse::successResp200(['data' => $allData]);
    }



    // Get Account Transactions - KRB
    public function getSubAccountKRBPayments($subConta, $size)
    {

        // return $subConta->account_number;

        $payments = Payment::join('stores', 'stores.id', 'payments.store_id')
            ->where('sender_account_number',  $subConta->account_number)
            ->where('payments.created_at', '>=', $subConta->created_at)
            ->orderByDesc('payments.created_at')
            ->select([
                'payments.id',
                'transaction_id',
                'amount',
                'transaction_type',
                'transaction_name',
                'sender_name',
                'sender_account_number',
                DB::raw(
                    "CASE WHEN payments.status = 'success' THEN 'Sucesso'
                         WHEN payments.status = 'pending' THEN 'Pendente'
                         WHEN payments.status = 'completed' THEN 'Concluído'
                         WHEN payments.status = 'failed' THEN 'Falhou'
                         ELSE payments.status END as status"
                ),
                'payments.created_at',
                'payments.updated_at'
            ]);


        $recharge = RechargeImaliAccount::query()
            ->join('users', 'users.id', 'recharge_imali_accounts.user_id')
            ->where('account_reference', $subConta->account_number)
            ->where('recharge_imali_accounts.created_at', '>=', $subConta->created_at)
            ->select([
                'recharge_imali_accounts.id',
                'transaction_id',
                'amount',
                'recharge_way as transaction_type',
                'description as transaction_name',
                'users.name as sender_name',
                'account_reference as sender_account_number',
                'recharge_imali_accounts.estado as status',
                'recharge_imali_accounts.created_at',
                'recharge_imali_accounts.updated_at'
            ]);

        $payments->union($recharge)->orderByDesc('created_at')->paginate($size);

        return $payments->orderByDesc('created_at')->paginate($size);
    }

    private function getMySubAccountTransfers($sub_account, $size)
    {
        $transfers = TransferHistory::query()
            ->join('transfers', 'transfers.transaction_id', '=', 'transfer_histories.transaction_id')
            //->where('user_id', $sub_account_id)
            ->where('transfers.created_at', '>=', $sub_account->created_at)
            ->where(auth()->user()->id == $sub_account->id ? 'transfer_histories.sender_account' : 'transfer_histories.user_id', auth()->user()->id == $sub_account->id ? $sub_account->account_number : $sub_account->id)
            ->select([
                'transfer_histories.id',
                'transfer_histories.transaction_id',
                'transfer_histories.amount',
                'transfer_histories.transaction_type',
                'transfer_histories.transaction_name',
                'transfer_histories.estado',
                'transfers.sender_id',
                'transfers.sender_name',
                'transfers.sender_account',
                DB::raw('NULL as sender_account'),
                DB::raw('NULL as reciever_name'),
                DB::raw('NULL as reciever_account'),
                DB::raw(
                    "CASE WHEN transfers.status = 'sucess' THEN 'Sucesso'
                    WHEN transfers.status = 'pending' THEN 'Pendente'
                    WHEN transfers.status = 'completed' THEN 'Concluído'
                    WHEN transfers.status = 'failed' THEN 'Falhou'
                    ELSE transfers.status END as status"
                ),
                'transfer_histories.created_at',
                'transfer_histories.updated_at'
            ]);

        return $transfers->orderBy('transfer_histories.created_at', 'desc')->paginate($size);
    }


    // Transacoes das subcontas NEW CODE 11-April-2024
    public function getSubAccountsTransactions(Request $request)
    {

        Log::info('Outgoing Response', [
            'content' => $request->url(),
            'params' => $request->all(),
        ]);

        // Definir o tamanho padrão da página se não especificado
        $size = $request->per_page ?? 50;

        // Obter detalhes do usuário autenticado
        $userAuth = User::getUserDetails(auth()->user()->id);

        // Obter subcontas associadas ao usuário autenticado
        $subaccounts = ImaliSubAccount::where('main_account_number', $userAuth->account_number)
            ->get(['account_number'])
            ->pluck('account_number');

        // Verificar se a subconta fornecida existe
        $subConta = ImaliSubAccount::where('account_number', $request->subaccount_number)
            ->first();

        if (!$subConta) {
            return response()->json(['message' => 'A subconta informada não foi encontrada.'], 400);
        }

        // Obter transações normais
        $payments = Payment::join('stores', 'stores.id', 'payments.store_id')
            //->whereIn('sender_account_number', $subaccounts)
            //->orWhere('sender_account_number', $subConta->account_number)
            ->where('sender_account_number',  $request->subaccount_number)
            ->orWhere('sender_card_number', $request->subaccount_number)
            ->orderByDesc('payments.created_at')
            ->select([
                'payments.id',
                'transaction_id',
                'amount',
                'transaction_type',
                'transaction_name',
                'estado',
                'payment_type',
                'sender_name',
                'sender_account_number',
                'sender_card_number',
                'store_id',
                'stores.name as store_name',

                //'payments.status',

                DB::raw(
                    "CASE WHEN payments.status = 'success' THEN 'Sucesso'
                        WHEN payments.status = 'pending' THEN 'Pendente'
                        WHEN payments.status = 'completed' THEN 'Concluído'
                        WHEN payments.status = 'failed' THEN 'Falhou'
                        ELSE payments.status END as status"
                ),

                'payments.created_at',
                'payments.updated_at'
            ]);

        // Obter transferências
        // $transfers = Transfer::join('transfer_histories', 'transfer_histories.transaction_id', '=', 'transfers.transaction_id')
        //     ->whereIn('sender_account', $subaccounts)
        //     ->orWhere(function ($query) use ($userAuth, $subConta) {
        //         $query->where('sender_account', $userAuth->account_number)
        //             ->where('reciever_account', $subConta->account_number);
        //     })
        //     ->orWhere(function ($query) use ($subConta, $userAuth) {
        //         $query->where('sender_account', $subConta->account_number)
        //             ->where('reciever_account', $userAuth->account_number);
        //     })

        // return $sub_account_id;

        // CODIGO MIGUEL CUMBE
        $sub_account_id = ImaliSubAccount::query()
            ->where('account_number', $request->subaccount_number)
            ->select('id')
            ->first();

        $transfers = Transfer::leftJoin('transfer_histories', 'transfer_histories.transaction_id', '=', 'transfers.transaction_id')

            //$transfers = Transfer::join('transfer_histories', 'transfer_histories.transaction_id', '=', 'transfers.transaction_id')
            // ->where(function ($query) use ($request, $subConta) {
            //     $query->where('sender_account', $request->subaccount_number)
            //         ->orWhere('reciever_account', $request->subaccount_number)
            //         ->orWhere(function ($query) use ($subConta) {
            //             $query->where('sender_account', $subConta->account_number)
            //                 ->orWhere('reciever_account', $subConta->account_number);
            //         });
            // })


            ->where(function ($query) use ($request, $subConta, $sub_account_id, $userAuth) {
                $query->where('sender_account', $request->subaccount_number)->where('user_id', $sub_account_id)
                    ->orWhere('reciever_account', $request->subaccount_number)->where('client_id', $userAuth->id)
                    ->orWhere(function ($query) use ($subConta, $userAuth, $sub_account_id) {
                        $query->where('sender_account', $subConta->account_number)->where('client_id', $userAuth->id)
                            ->orWhere('reciever_account', $subConta->account_number)->where('user_id', $sub_account_id);
                    });
            })


            // ->where(function ($query) use ($sub_account_id, $userAuth) {
            //      $query->where('user_id', $sub_account_id)
            //          ->orWhere(
            //              function ($query) use ($userAuth) {
            //                  $query->where('client_id', $userAuth->id);
            //              }
            //          );
            //  })

            ->orderByDesc('transfer_histories.created_at')
            ->select([
                'transfer_histories.id',
                'transfer_histories.transaction_id',
                'transfer_histories.amount',
                'transfer_histories.transaction_type',
                'transfer_histories.transaction_name',
                'transfer_histories.estado',
                'transfers.sender_id',
                'transfers.sender_name',
                // 'transfers.sender_account',
                // 'transfers.reciever_id',
                'transfers.sender_account',
                DB::raw('NULL as sender_account'),
                // 'transfers.reciever_name',
                DB::raw('NULL as reciever_name'),
                DB::raw('NULL as reciever_account'),
                // 'transfers.reciever_account',

                //'transfers.status',

                DB::raw(
                    "CASE WHEN transfers.status = 'sucess' THEN 'Sucesso'
                        WHEN transfers.status = 'pending' THEN 'Pendente'
                        WHEN transfers.status = 'completed' THEN 'Concluído'
                        WHEN transfers.status = 'failed' THEN 'Falhou'
                        ELSE transfers.status END as status"
                ),

                'transfer_histories.created_at',
                'transfer_histories.updated_at'
            ]);

        // ->select([
        //     'transfer_histories.id',
        //     'transfer_histories.transaction_id',
        //     'transfer_histories.amount',
        //     'transfer_histories.transaction_type',
        //     'transfer_histories.transaction_name',
        //     'transfer_histories.estado',
        //     'transfers.sender_id',
        //     'transfers.sender_name',
        //     'transfers.sender_account',
        //     'transfers.reciever_id',
        //     'transfers.reciever_name',
        //     'transfers.reciever_account',
        //     'transfers.status',
        //     'transfer_histories.created_at',
        //     'transfer_histories.updated_at'
        // ]);


        // Unir e paginar os resultados
        $allData = $payments->union($transfers)->orderByDesc('created_at')->paginate($size);

        return response()->json($allData, 200);
    }



    public function addMoneySubAccount(Request $request)
    {

        $this->validate(
            $request,
            [
                'amount' => 'required',
            ],
            [
                'amount.required' => 'Campo amount e obrigatorio',
            ]
        );

        // Buscar dados do User que faz a transacao
        // $userPayer = User::getUserDetails(auth()->user()->id);
        $userPayer = User::getUserAccount();
        //return $userPayer;

        // Buscar dados da conta principal
        $accountPayerMainAccount = User::getAccountByUser($userPayer->id, $userPayer->account_id);
        //return $accountPayerMainAccount;

        // Buscar dados da subconta
        $accountPayerOld = User::getAccount($request->account_number);
        $accountPayer = User::getAccount($request->account_number);
        //return $accountPayer;

        if (!$accountPayer->is_credit_allowed) return SendResponse::errorResp400(
            'Crédito na subconta não permitido',
            'Subaccount credit not allowed',
        );


        try {
            DB::beginTransaction();

            // Validar o PIN e Fingerprint do userPayer
            $auth = new Auth();
            $authResp = $auth->checkUserPinAndFingerprint($request);
            if ($authResp->getStatusCode() != 200) return $authResp;

            if ($accountPayerMainAccount->balance < $request->amount) return response()->json(['message' => 'O saldo disponivel é menor do que o valor solicitado.'], 400);

            if ($accountPayerMainAccount->balance === 0 && $request->amount > 0) return response()->json(['message' => 'Não é possível realizar a operação. O saldo da conta é zero.'], 400);

            $accountPayer->balance += $request->amount;
            $accountPayer->update();

            $accountPayerMainAccount->balance -= $request->amount;
            $accountPayerMainAccount->update();

            // ----------------------------------------------------

            // Registar a transacao de transferencia | Envio de Dinheiro
            $random = new TransactionGeneration();
            $transactionReference = $random->generateTransaction();

            $transferencia = Transfer::create([
                'transaction_id' => $transactionReference,
                'sender_id' => $accountPayerMainAccount->id,
                'sender_account' => $accountPayerMainAccount->account_number,
                'sender_name' => $userPayer->name,
                'reciever_id' => $accountPayer->id,
                'reciever_name' => $accountPayer->name,
                'reciever_account' => $accountPayer->account_number,
                'amount' => $request->amount,
                'total_amount' => $request->amount,
                'comissao' => 0,
                'estado_color' => '#388E3C',
                'estado' => 'Pago',
                'status' => 'sucess',
                'description' => 'TRF. Main Account to Sub Account',
                'amount_debited' => $request->amount,
                'imali_transac_type' => 'TRANSAC_C2C_TRANSFERENCIA',
                'old_balance' => $accountPayerOld->balance,
                'new_balance' => $accountPayer->balance
            ]);

            $senderHistory = TransferHistory::create([
                'transaction_id' => $transactionReference,

                'sender_account' => $accountPayerMainAccount->account_number,
                'reciever_account' => $accountPayer->account_number,

                'user_id' => $accountPayerMainAccount->id,
                'client_id' => $accountPayer->id,

                'amount' => $request->amount,
                'comissao' => 0,
                'estado_color' => '#388E3C',
                'estado' => 'Pago',
                'user_status' => 'payer',
                'amount_debited' => $request->amount,

                'transaction_type' => 'debit',
                'transaction_name' => 'Transferência'
            ]);

            $receiverHistory = TransferHistory::create([
                'transaction_id' => $transactionReference,

                'sender_account' => $accountPayer->account_number,
                'reciever_account' => $accountPayerMainAccount->account_number,

                'user_id' => $accountPayer->id,
                'client_id' => $accountPayerMainAccount->id,

                'amount' => $request->amount,
                'description' => $request->description,
                'comissao' => 0,
                'estado_color' => '#388E3C',
                'estado' => 'Recebido',
                'user_status' => 'receiver',
                'amount_debited' => $request->amount,

                'transaction_type' => 'credit',
                'transaction_name' => 'Transferência'
            ]);

            TransactionHistory::create([
                'user_id' => $senderHistory->user_id,
                'transfer_history_id' => $senderHistory->id,
                'transaction_type' => 'transfer_history'
            ]);

            TransactionHistory::create([
                'user_id' => $receiverHistory->user_id,
                'transfer_history_id' => $receiverHistory->id,
                'transaction_type' => 'transfer'
            ]);

            // ----------------------------------------------------
            DB::commit();

            return response()->json([
                'message' => 'Transferência feita com sucesso!',
                'transaction' => $transactionReference,
                'created_at' => $transferencia->created_at
            ], 200);
        } catch (\Throwable $th) {
            DB::rollBack();

            // Escrever no ficheiro de log as mensagens de erro.
            return response()->json(['message' => 'Falha na operação', $th->getMessage()], 500);
        }
    }

    public function removeMoneySubAccount(Request $request)
    {

        //$req = Request::create('/api/mine-transaction-store-2024', 'POST', $request->all());
        //return Route::dispatch($req);

        $this->validate(
            $request,
            [
                'amount' => 'required',
            ],
            [
                'amount.required' => 'Campo amount e obrigatorio',
            ]
        );

        // Buscar dados do User que faz a transacao
        $userPayer = User::getUserDetails(auth()->user()->id);
        // return $userPayer;

        // Buscar dados da conta principal
        $accountPayerMainAccount = User::getAccountByUser($userPayer->id, $userPayer->account_id);
        // return $accountPayerMainAccount;
        $accountPayerMainAccountOld = User::getAccountByUser($userPayer->id, $userPayer->account_id);

        // Buscar dados da subconta
        $accountPayer = User::getAccount($request->account_number);
        // return $accountPayer;

        if (!$accountPayer) return SendResponse::errorResp404notfound(
            'Subconta não encontrada',
            'Subaccount not found',
        );
        // return $accountPayer;

        if (!$accountPayer->is_debit_allowed) return SendResponse::errorResp400(
            'Dédito na subconta não permitido',
            'Subaccount debit not allowed',
        );

        // $kyc = new UserKyc($accountPayer);
        // $kycSenderResp = $kyc->checkSenderKYC($request->amount);
        // if ($kycSenderResp->getStatusCode() != 200) return $kycSenderResp;

        try {
            DB::beginTransaction();

            // Validar o PIN e Fingerprint do userPayer
            $auth = new Auth();
            $authResp = $auth->checkUserPinAndFingerprint($request);
            if ($authResp->getStatusCode() != 200) return $authResp;

            if ($accountPayer->balance < $request->amount) return response()->json(['message' => 'O saldo disponivel é menor do que o valor solicitado.'], 400);

            // if ($accountPayer->balance === 0 && $request->amount > 0) return response()->json(['message' => 'Não é possível realizar a operação. O saldo da conta é zero.'], 400);

            $accountPayer->balance -= $request->amount;
            $accountPayer->update();

            $accountPayerMainAccount->balance += $request->amount;
            $accountPayerMainAccount->update();

            // ----------------------------------------------------

            // Registar a transacao de transferencia | Envio de Dinheiro
            $random = new TransactionGeneration();
            $transactionReference = $random->generateTransaction();

            $transferencia = Transfer::create([
                'transaction_id' => $transactionReference,
                'sender_id' => $accountPayer->id,
                'sender_account' => $accountPayer->account_number,
                'sender_name' => $accountPayer->name,
                'reciever_id' => $accountPayerMainAccount->id,
                'reciever_name' => $userPayer->name,
                'reciever_account' => $accountPayerMainAccount->account_number,
                'amount' => $request->amount,
                'total_amount' => $request->amount,
                'comissao' => 0,
                'estado_color' => '#388E3C',
                'estado' => 'Pago',
                'status' => 'sucess',
                'description' => 'TRF. Sub Account to Main Account',
                'amount_debited' => $request->amount,
                'imali_transac_type' => 'TRANSAC_C2C_TRANSFERENCIA',
                'old_balance' => $accountPayerMainAccountOld->balance,
                'new_balance' => $accountPayerMainAccount->balance
            ]);

            $senderHistory = TransferHistory::create([
                'transaction_id' => $transactionReference,

                'sender_account' => $accountPayerMainAccount->account_number,
                'reciever_account' => $accountPayer->account_number,

                'user_id' => $accountPayer->id,
                'client_id' => $accountPayerMainAccount->id,
                'amount' => $request->amount,
                'comissao' => 0,
                'estado_color' => '#388E3C',
                'estado' => 'Pago',
                'user_status' => 'payer',
                'amount_debited' => $request->amount,

                'transaction_type' => 'debit',
                'transaction_name' => 'Transferência',
            ]);

            $receiverHistory = TransferHistory::create([
                'transaction_id' => $transactionReference,

                'sender_account' => $accountPayer->account_number,
                'reciever_account' => $accountPayerMainAccount->account_number,

                'user_id' => $accountPayerMainAccount->id,
                'client_id' => $accountPayer->id,
                'amount' => $request->amount,
                'description' => $request->description,
                'comissao' => 0,
                'estado_color' => '#388E3C',
                'estado' => 'Recebido',
                'user_status' => 'receiver',
                'amount_debited' => $request->amount,

                'transaction_type' => 'credit',
                'transaction_name' => 'Transferência',
            ]);

            TransactionHistory::create([
                'user_id' => $senderHistory->user_id,
                'transfer_history_id' => $senderHistory->id,
                'transaction_type' => 'transfer_history'
            ]);

            TransactionHistory::create([
                'user_id' => $receiverHistory->user_id,
                'transfer_history_id' => $receiverHistory->id,
                'transaction_type' => 'transfer'
            ]);

            // ----------------------------------------------------
            DB::commit();

            return response()->json([
                'message' => 'Transferência feita com sucesso!',
                'transaction' => $transactionReference,
                'created_at' => $transferencia->created_at
            ], 200);
        } catch (\Throwable $th) {
            DB::rollBack();

            // Escrever no ficheiro de log as mensagens de erro.
            return response()->json(['message' => 'Falha na operação', $th->getMessage()], 500);
        }
    }

    public function removeSubAccountMoney(Request $request)
    {
        // $userAuth = User::getUserDetails(auth()->user()->id);
        // $accountSender = ImaliAccount::query()->where('imali_account_id', $userAuth->account_number)->get();

        // Buscar dados do User que faz a transacao
        $userSender = User::getUserDetails(auth()->user()->id);
        // Buscar dados da conta do User que faz a transacao
        $accountSender = User::getAccountByUser($userSender->id, $userSender->account_id);
        return $accountSender;

        $userReceiver = User::getUserDetails(User::getAccount($request->account_number)->user_id);
        $accountReceiver = User::getAccountByUser($userReceiver->id, $userReceiver->account_id);
    }

    public function tvcaboCheckClient(Request $request)
    {
        try {
            $response = Http::get('http://localhost:3004/api/tvcabo/check-client-invoice?NContrato=' . $request->client_number);
            return response()->json($response);
        } catch (\Throwable $th) {
            return response()->json($th->getMessage());
        }
    }


    public function getUserToken($phone)
    {
        $config = PhoneValidation::query()
            ->select('phone', 'codigo', 'duration', 'expire_at', 'is_Validated')
            ->where('phone', $phone)
            ->first();

        if ($config) {

            // Hora atual e expiração (sem Carbon)
            $now = time();
            $expire = strtotime($config->expire_at);

            if ($now > $expire) {
                $status = 'TOKEN EXPIRADO';
                $tempoRestante = '0 segundos';
            } else {
                $status = 'TOKEN VÁLIDO';
                $diff = $expire - $now; // diferença em segundos

                // Converter para minutos e segundos
                $min = floor($diff / 60);
                $sec = $diff % 60;

                if ($min > 0) {
                    $tempoRestante = "{$min} minutos e {$sec} segundos";
                } else {
                    $tempoRestante = "{$sec} segundos";
                }
            }

            return response()->json([
                'phone'          => $config->phone,
                'codigo'         => $config->codigo,
                'duration'       => $config->duration,
                'expire_at'      => $config->expire_at,
                'is_Validated'   => $config->is_Validated,
                'status'         => $status,
                'tempo_restante' => $tempoRestante,
            ]);
        }

        return response()->json(['message' => 'OTP não encontrado.'], 400);
    }


    public function switchLang(Request $request)
    {

        $this->validate(
            $request,
            [
                'lang' => 'required|in:PT,EN,ES,FR',
            ],
            [
                'lang.required' => 'Campo de Idioma obrigatório',
                'lang.in' => 'Os idiomas validos são: PT, EN, ES, FR',
            ]
        );

        $auth_user = User::getUserDetails(auth()->user()->id);
        if ($auth_user->lang === $request->lang) return response()->json(['message' => 'O idioma selecionado já esta em uso'], 200);
        $auth_user->lang = $request->lang;
        $auth_user->update();
        return response()->json(['message' => 'Idioma actualizado com sucesso'], 200);
    }
}