<?php

namespace App\Http\Controllers;

use App\Models\CodeUser;
use App\Models\SchemaComptable;
use App\Models\Serveur;
use App\Models\TransactionStatus;
use Carbon\Carbon;
use DOMDocument;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use SimpleXMLElement;
use SoapClient;
use SoapFault;
use Illuminate\Support\Str;

class SoapRequestController extends Controller
{

    public function handleSoapRequest(Request $request)
    {
       // Parse the raw XML content from the request
       $xmlContent = $request->getContent();
        // Log the raw XML request for debugging
        Log::info('Received SOAP Request:', ['xml' => $xmlContent]);

       // Load the XML content using SimpleXMLElement
       $xml = new \SimpleXMLElement($xmlContent);

       // Extract the requestType from the XML structure (adapt based on your actual XML)
       // Adjust the path based on your WSDL structure, this example assumes a path like:
       // /Envelope/Body/GetAccountBalance/AccountBalanceInquiryRequest/mmHeaderInfo/requestType
       $requestType = (string) $xml->xpath('//mmHeaderInfo/requestType')[0];
       // Log the extracted requestType for debugging
       Log::info('Extracted requestType:', ['requestType' => $requestType]);
        //return $requestType;

        try {
            switch ($requestType) {
                case 'GETACCBAL':
                    return $this->getAccountBalance($xml);
                case 'GETMINI':
                    return $this->getMiniStatement($xml);
                case 'W2A':
                    return $this->walletToAccountTransfer($xml);
                case 'A2W':
                    return $this->AccountToWalletTransfer($xml);
                case 'TRANINQ':
                    return $this->transferStatusInquiry($xml);
                case 'CANCELTRAN':
                    return $this->CancelTransfer($xml);
                default:
                    //return $this->sendError('Unknown request type: ' . $requestType);
                     return $this->sendError("010","","","","Unknown request type: ' . $requestType","",null);
            }
        } catch (\Exception $e) {
            return $this->sendError("010","","","",$e->getMessage(),"",null);

        }
    }

    //GET BALANCE


    private function getAccountBalance($xml)
{
    try {
        // Extract mmHeaderInfo fields
        $mmHeaderInfo = $xml->xpath('//AccountBalanceInquiryRequest/mmHeaderInfo')[0];
        $operatorCode = (string) $mmHeaderInfo->operatorCode;
        $requestId = (string) $mmHeaderInfo->requestId;
        $requestToken = (string) $mmHeaderInfo->requestToken;
        $requestType = (string) $mmHeaderInfo->requestType;
        $affiliateCode = (string) $mmHeaderInfo->affiliateCode;

        // Extract other fields from the request
        $accountNo = (string) $xml->xpath('//AccountBalanceInquiryRequest/accountNo')[0];
        $accountAlias = (string) $xml->xpath('//AccountBalanceInquiryRequest/accountAlias')[0];
        $reason = (string) $xml->xpath('//AccountBalanceInquiryRequest/reason')[0];

        // Generate a unique reference number for tracking purposes
        $referenceNumber =  Str::random(16);

        // Log the initial request in the transaction_statuses table
        DB::table('transaction_statuses')->insert([
            'date' => now(),
            'type' => 'GetAccountBalance',
            'alias' => $accountAlias,
            'currency' => 'XOF',
            'amount' => 0,
            'request_code' => $requestId,
            'response_code' => '', // Initially empty, updated after processing
            'response_message' => 'Pending',
            'reference_number' => $referenceNumber,
            'status' => 1, // 1 for pending
            'created_at' => now(),
            'updated_at' => now()
        ]);

        // Retrieve the account balance (simulate errors or fetch actual balance)
        $availableBalance = 0;
        $balanceResult = $this->getBalance($accountAlias);

        if ($balanceResult === "Account not found") {
            $this->updateTransactionStatus($referenceNumber, 'E01', 'Account not found', 2);
            return $this->sendError("E01",$operatorCode,$requestId,$affiliateCode,'Account not found',$referenceNumber,"GetAccountBalanceResponse");
        } elseif ($balanceResult === "Error getting account balance") {
            $this->updateTransactionStatus($referenceNumber, 'E02', 'Error getting account balance', 2);
            return $this->sendError("E02",$operatorCode,$requestId,$affiliateCode,'Error getting account balance',$referenceNumber,"GetAccountBalanceResponse");
        } elseif ($balanceResult === "Database connection failed") {
            $this->updateTransactionStatus($referenceNumber, 'E03', 'Database connection failed', 2);
            return $this->sendError("E03",$operatorCode,$requestId,$affiliateCode,'Database connection failed',$referenceNumber,"GetAccountBalanceResponse");
        } else {
            $availableBalance = $balanceResult;
        }

        // Define currency and build XML success response
        $currency = 'XOF';
        $xmlResponse = <<<XML
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:b2w="http://b2w.banktowallet.com/b2w">
            <soapenv:Header/>
            <soapenv:Body>
                <b2w:GetAccountBalanceResponse>
                <return>
                    <mmHeaderInfo>
                        <operatorCode>{$operatorCode}</operatorCode>
                        <requestId>{$requestId}</requestId>
                        <affiliateCode>{$affiliateCode}</affiliateCode>
                        <responseCode>000</responseCode>
                        <responseMessage>Success</responseMessage>
                    </mmHeaderInfo>
                    <accountAlias>{$accountAlias}</accountAlias>
                    <ccy>{$currency}</ccy>
                    <availableBalance>{$availableBalance}</availableBalance>
                    <currentBalance>{$availableBalance}</currentBalance>
                </return>
                </b2w:GetAccountBalanceResponse>
            </soapenv:Body>
        </soapenv:Envelope>
XML;

        // Update the transaction status as successful
        $this->updateTransactionStatus($referenceNumber, '000', 'Success', 0);

        // Return the XML response
        return response($xmlResponse, 200)
            ->header('Content-Type', 'application/xml');

    } catch (\Exception $e) {
        // Log the error and update the transaction_statuses table
        Log::error('Error processing GetAccountBalance:', ['error' => $e->getMessage()]);
        $this->updateTransactionStatus($referenceNumber, 'E99', $e->getMessage(), 2);
        return $this->sendError("E03",$operatorCode,$requestId,$affiliateCode,'Bank technical error',$referenceNumber,"GetAccountBalanceResponse");

        // Return error response
    }
}

/**
 * Helper method to update transaction status in transaction_statuses table
 */
private function updateTransactionStatus($referenceNumber, $responseCode, $responseMessage, $status)
{
    DB::table('transaction_statuses')
        ->where('reference_number', $referenceNumber)
        ->update([
            'response_code' => $responseCode,
            'response_message' => $responseMessage,
            'status' => $status,
            'updated_at' => now()
        ]);
}

    private function getBalance($accountAlias)
    {
        try {
            Log::info('Check balance Alias : '.$accountAlias);
            $check=Serveur::setDatabaseConnection($accountAlias);
            if($check===false){
                // Log or handle the error
                Log::error("Database connection failed 2 : ");
                return "Database connection failed";

            }
            $code_membre=substr($accountAlias, -11);
            Log::info("Debut du traitement : ".$code_membre);
            //Get accountNo
            $compte= DB::connection('sqlsrv2')
            ->table('CC.CC_CUENTA_EFECTIVO')
            ->join('CF.CF_PRODUCTOS', 'CF.CF_PRODUCTOS.COD_PRODUCTO', '=', 'CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO')
            ->where('CC.CC_CUENTA_EFECTIVO.COD_CLIENTE', $code_membre)
            ->where('CC.CC_CUENTA_EFECTIVO.IND_ESTADO', 'A')
            ->where(function($query) {
                $query->where('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC004')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC003')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC008');
            })->first();
            //Log::info("Compte infos : ".$compte);
            $solde_client=$compte->SAL_DISPONIBLE ?? 0;
            return $solde_client;
        } catch (\Throwable $th) {
            //throw $th;
            Log::error("Error getting account balance : ".$code_membre."  Log: ".$th->getMessage());
            return "Error getting account balance";
        }

}


private function TransactionB2W($accountAlias,$amount)
{
    Log::info(' TransactionB2W Method info Alias:'.$accountAlias.' Montant:'.$amount);

    $responseCode='010';
    if($this->getBalance($accountAlias)==false){
        return $this->sendError("E01","","","","Account not found","",null);
    }
    else{
        $availableBalance = $this->getBalance($accountAlias);
        if($availableBalance<$amount){
            $responseCode='E16';
            $responseMessage='Insufficient funds';
            //Return them on array data
            return ['responseCode'=>$responseCode,'responseMessage'=>$responseMessage,'availableBalance'=>$availableBalance];
        }
        else{

            Serveur::setDatabaseConnection($accountAlias);
            $code_user=CodeUser::find(1)->code;
            $code_membre=substr($accountAlias, -11);
            //Get accountNo
            $compte= DB::connection('sqlsrv2')
            ->table('CC.CC_CUENTA_EFECTIVO')
            ->join('CF.CF_PRODUCTOS', 'CF.CF_PRODUCTOS.COD_PRODUCTO', '=', 'CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO')
            ->where('CC.CC_CUENTA_EFECTIVO.COD_CLIENTE', $code_membre)
            ->where('CC.CC_CUENTA_EFECTIVO.IND_ESTADO', 'A')
            ->where(function($query) {
                $query->where('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC004')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC003')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC008');
            })->first();
            $accountNo=$compte->NUM_CUENTA;
            $code_agence=$compte->COD_AGENCIA;
            Log::info('Numéro de compte:'.$accountNo);
            //Get client info
            $info_benef=DB::connection('sqlsrv2')->table('CL.CL_CLIENTES')->where('COD_CLIENTE',$compte->COD_CLIENTE)->orderBy('COD_CLIENTE', 'desc')->first();
            Log::info('Opération B2W / Compte :'.$accountNo.'/ Montant:'.$amount);

            $check=SchemaComptable::OperationTransB2W($accountNo,$amount,$code_user,"CC".substr($accountNo,3,3),$info_benef->NOM_CLIENTE,$info_benef->TEL_SECUNDARIO,$code_agence);
            if($check==false){
                $responseCode='E01';
                $responseMessage='Transaction failed';
                //Return them on array data
                return ['responseCode'=>$responseCode,'responseMessage'=>$responseMessage,'availableBalance'=>$availableBalance];
            }
            else{
                 //Get Original Mouvement ID
            $last_mov_id= DB::connection('sqlsrv2')->table('CF.CF_SERIES_X_EMPRESA')->where('COD_SERIE','CC_MOV_DIA')->first()->VAL_SIGUIENTE;
            $last_mov_id_mov=  DB::connection('sqlsrv2')->table('CC.CC_MOVIMTO_DIARIO')->select('NUM_MOVIMIENTO')->orderBy('NUM_MOVIMIENTO', 'desc')->first()->NUM_MOVIMIENTO;
            if($last_mov_id_mov>=$last_mov_id){
                $last_mov_id=$last_mov_id_mov;
            }
            $mouvement_id=$last_mov_id;

            $responseCode='000';
            $responseMessage='Success';
            //Return them on array data
            return ['responseCode'=>$responseCode,'responseMessage'=>$responseMessage,'mouvement_id'=>$mouvement_id];
            }

        }
    }

}
private function TransactionB2WCancel($accountAlias,$amount)
{
    $responseCode='010';
    if($this->getBalance($accountAlias)==false){
        return $this->sendError("E01","","","","Account not found","",null);
    }
    else{
        //$availableBalance = $this->getBalance($accountAlias);

            Serveur::setDatabaseConnection($accountAlias);
            $code_user=CodeUser::find(1)->code;
            $code_membre=substr($accountAlias, -11);
            //Get accountNo
            $compte= DB::connection('sqlsrv2')
            ->table('CC.CC_CUENTA_EFECTIVO')
            ->join('CF.CF_PRODUCTOS', 'CF.CF_PRODUCTOS.COD_PRODUCTO', '=', 'CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO')
            ->where('CC.CC_CUENTA_EFECTIVO.COD_CLIENTE', $code_membre)
            ->where('CC.CC_CUENTA_EFECTIVO.IND_ESTADO', 'A')
            ->where(function($query) {
                $query->where('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC004')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC003')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC008');
            })->first();
            $accountNo=$compte->NUM_CUENTA;
            $code_agence=$compte->COD_AGENCIA;
            //Get client info
            $info_benef=DB::connection('sqlsrv2')->table('CL.CL_CLIENTES')->where('COD_CLIENTE',$compte->COD_CLIENTE)->orderBy('COD_CLIENTE', 'desc')->first();
            Log::info('Opération B2W / Compte :'.$accountNo.'/ Montant:'.$amount);
            $check=SchemaComptable::OperationTransB2WCancel($accountNo,$amount,$code_user,"CC".substr($accountNo,3,3),$info_benef->NOM_CLIENTE,$info_benef->TEL_SECUNDARIO,$code_agence);
            if($check==false){
                $responseCode='E01';
                $responseMessage='Transaction failed';
                //Return them on array data
                return ['responseCode'=>$responseCode,'responseMessage'=>$responseMessage];
            }
            else{
                 //Get Original Mouvement ID
            $last_mov_id= DB::connection('sqlsrv2')->table('CF.CF_SERIES_X_EMPRESA')->where('COD_SERIE','CC_MOV_DIA')->first()->VAL_SIGUIENTE;
            $last_mov_id_mov=  DB::connection('sqlsrv2')->table('CC.CC_MOVIMTO_DIARIO')->select('NUM_MOVIMIENTO')->orderBy('NUM_MOVIMIENTO', 'desc')->first()->NUM_MOVIMIENTO;
            if($last_mov_id_mov>=$last_mov_id){
                $last_mov_id=$last_mov_id_mov;
            }
            $mouvement_id=$last_mov_id;

            $responseCode='000';
            $responseMessage='Success';
            //Return them on array data
            return ['responseCode'=>$responseCode,'responseMessage'=>$responseMessage,'mouvement_id'=>$mouvement_id];
            }


    }

}

private function TransactionW2BCancel($accountAlias,$amount)
{
    $responseCode='010';
    if($this->getBalance($accountAlias)==false){
        return $this->sendError("E01","","","","Account not found","",null);
    }
    else{
        $availableBalance = $this->getBalance($accountAlias);
        if($availableBalance<$amount){
            $responseCode='E16';
            $responseMessage='Insufficient funds';
            //Return them on array data
            return ['responseCode'=>$responseCode,'responseMessage'=>$responseMessage,'availableBalance'=>$availableBalance];
        }
        else{

            Serveur::setDatabaseConnection($accountAlias);
            $code_user=CodeUser::find(1)->code;
            $code_membre=substr($accountAlias, -11);
            //Get accountNo
            $compte= DB::connection('sqlsrv2')
            ->table('CC.CC_CUENTA_EFECTIVO')
            ->join('CF.CF_PRODUCTOS', 'CF.CF_PRODUCTOS.COD_PRODUCTO', '=', 'CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO')
            ->where('CC.CC_CUENTA_EFECTIVO.COD_CLIENTE', $code_membre)
            ->where('CC.CC_CUENTA_EFECTIVO.IND_ESTADO', 'A')
            ->where(function($query) {
                $query->where('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC004')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC003')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC008');
            })->first();
            $accountNo=$compte->NUM_CUENTA;
            $code_agence=$compte->COD_AGENCIA;
            //Get client info
            $info_benef=DB::connection('sqlsrv2')->table('CL.CL_CLIENTES')->where('COD_CLIENTE',$compte->COD_CLIENTE)->orderBy('COD_CLIENTE', 'desc')->first();
            Log::info('Opération B2W / Compte :'.$accountNo.'/ Montant:'.$amount);

            $check=SchemaComptable::OperationTransW2BCancel($accountNo,$amount,$code_user,"CC".substr($accountNo,3,3),$info_benef->NOM_CLIENTE,$info_benef->TEL_SECUNDARIO,$code_agence);
            if($check==false){
                $responseCode='E01';
                $responseMessage='Transaction failed';
                //Return them on array data
                return ['responseCode'=>$responseCode,'responseMessage'=>$responseMessage,'availableBalance'=>$availableBalance];
            }
            else{
                 //Get Original Mouvement ID
            $last_mov_id= DB::connection('sqlsrv2')->table('CF.CF_SERIES_X_EMPRESA')->where('COD_SERIE','CC_MOV_DIA')->first()->VAL_SIGUIENTE;
            $last_mov_id_mov=  DB::connection('sqlsrv2')->table('CC.CC_MOVIMTO_DIARIO')->select('NUM_MOVIMIENTO')->orderBy('NUM_MOVIMIENTO', 'desc')->first()->NUM_MOVIMIENTO;
            if($last_mov_id_mov>=$last_mov_id){
                $last_mov_id=$last_mov_id_mov;
            }
            $mouvement_id=$last_mov_id;

            $responseCode='000';
            $responseMessage='Success';
            //Return them on array data
            return ['responseCode'=>$responseCode,'responseMessage'=>$responseMessage,'mouvement_id'=>$mouvement_id];
            }

        }
    }

}

private function TransactionW2B($accountAlias,$amount)
{
    Log::info('Method TransactionW2B start ... Alias: '.$accountAlias);
    $responseCode='010';
    if($this->getBalance($accountAlias)==false){
        return $this->sendError("E01","","","","Account not found","",null);
    }
    else{
        //$availableBalance = $this->getBalance($accountAlias);

            Serveur::setDatabaseConnection($accountAlias);
            $code_user=CodeUser::find(1)->code;
            $code_membre=substr($accountAlias, -11);
            //Get accountNo
            $compte= DB::connection('sqlsrv2')
            ->table('CC.CC_CUENTA_EFECTIVO')
            ->join('CF.CF_PRODUCTOS', 'CF.CF_PRODUCTOS.COD_PRODUCTO', '=', 'CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO')
            ->where('CC.CC_CUENTA_EFECTIVO.COD_CLIENTE', $code_membre)
            ->where('CC.CC_CUENTA_EFECTIVO.IND_ESTADO', 'A')
            ->where(function($query) {
                $query->where('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC004')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC003')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC008');
            })->first();
            $accountNo=$compte->NUM_CUENTA;
            $code_agence=$compte->COD_AGENCIA;
            //Get client info
            $info_benef=DB::connection('sqlsrv2')->table('CL.CL_CLIENTES')->where('COD_CLIENTE',$compte->COD_CLIENTE)->orderBy('COD_CLIENTE', 'desc')->first();
            Log::info('Opération B2W / Compte :'.$accountNo.'/ Montant:'.$amount);
            $check=SchemaComptable::OperationTransW2B($accountNo,$amount,$code_user,"CC".substr($accountNo,3,3),$info_benef->NOM_CLIENTE,$info_benef->TEL_SECUNDARIO,$code_agence);
            if($check==false){
                $responseCode='E01';
                $responseMessage='Transaction failed';
                //Return them on array data
                return ['responseCode'=>$responseCode,'responseMessage'=>$responseMessage];
            }
            else{
                 //Get Original Mouvement ID
            $last_mov_id= DB::connection('sqlsrv2')->table('CF.CF_SERIES_X_EMPRESA')->where('COD_SERIE','CC_MOV_DIA')->first()->VAL_SIGUIENTE;
            $last_mov_id_mov=  DB::connection('sqlsrv2')->table('CC.CC_MOVIMTO_DIARIO')->select('NUM_MOVIMIENTO')->orderBy('NUM_MOVIMIENTO', 'desc')->first()->NUM_MOVIMIENTO;
            if($last_mov_id_mov>=$last_mov_id){
                $last_mov_id=$last_mov_id_mov;
            }
            $mouvement_id=$last_mov_id;

            $responseCode='000';
            $responseMessage='Success';
            //Return them on array data
            return ['responseCode'=>$responseCode,'responseMessage'=>$responseMessage,'mouvement_id'=>$mouvement_id];
            }


    }

}




private function getMiniStatement($xml)
    {
        try {
            // Extract mmHeaderInfo fields
            $mmHeaderInfo = $xml->xpath('//MiniStatementRequest/mmHeaderInfo')[0];

            $operatorCode = (string) $mmHeaderInfo->operatorCode;
            $requestId = (string) $mmHeaderInfo->requestId;
            $affiliateCode = (string) $mmHeaderInfo->affiliateCode;
            $requestType = (string) $mmHeaderInfo->requestType;

            // Log mmHeaderInfo data for debugging
            Log::info('MiniStatementRequest mmHeaderInfo:', [
                'operatorCode' => $operatorCode,
                'requestId' => $requestId,
                'affiliateCode' => $affiliateCode,
                'requestType' => $requestType,
            ]);


            // Extract additional request fields
            $accountNo = (string) $xml->xpath('//MiniStatementRequest/accountNo')[0];
            $accountAlias = (string) $xml->xpath('//MiniStatementRequest/accountAlias')[0];

             // Generate a unique reference number for tracking purposes
        $referenceNumber =  Str::random(16);

        // Log the initial request in the transaction_statuses table
        DB::table('transaction_statuses')->insert([
            'date' => now(),
            'type' => 'GetMiniStatementResponse',
            'alias' => $accountAlias,
            'currency' => 'XOF',
            'amount' => 0,
            'request_code' => $requestId,
            'response_code' => '', // Initially empty, updated after processing
            'response_message' => 'Pending',
            'reference_number' => $referenceNumber,
            'status' => 1, // 1 for pending
            'created_at' => now(),
            'updated_at' => now()
        ]);

            //DB CONNEXION
            Serveur::setDatabaseConnection($accountAlias);
            $code_user=CodeUser::find(1)->code;
            $code_membre=substr($accountAlias, -11);
            //Get accountNo
            $compte= DB::connection('sqlsrv2')
            ->table('CC.CC_CUENTA_EFECTIVO')
            ->join('CF.CF_PRODUCTOS', 'CF.CF_PRODUCTOS.COD_PRODUCTO', '=', 'CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO')
            ->where('CC.CC_CUENTA_EFECTIVO.COD_CLIENTE', $code_membre)
            ->where('CC.CC_CUENTA_EFECTIVO.IND_ESTADO', 'A')
            ->where(function($query) {
                $query->where('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC004')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC003')
                      ->orWhere('CC.CC_CUENTA_EFECTIVO.COD_PRODUCTO', 'CC008');
            })->first();
            $accountNo=$compte->NUM_CUENTA;
            //GET MOUVEMENTS

            // Log additional request fields
            Log::info('MiniStatementRequest Data:', [
                'accountNo' => $accountNo,
                'accountAlias' => $accountAlias,
            ]);

            // Simulated transaction data (In a real scenario, retrieve these from the database)
           // Récupérer les 5 dernières opérations
            $transactions = DB::connection('sqlsrv2')
            ->table('CC.CC_MOVIMTO_DIARIO')
            ->where('NUM_CUENTA', $accountNo)
            ->orderByDesc('NUM_MOVIMIENTO')
            ->limit(5)
            ->get(['NUM_MOVIMIENTO', 'FEC_MOVIMIENTO', 'TIP_TRANSACCION', 'MON_MOVIMIENTO'])
            ->map(function ($operation) {
                return [
                    'tranRefNo' => $operation->NUM_MOVIMIENTO,
                    'tranDate' => Carbon::parse($operation->FEC_MOVIMIENTO)->toIso8601String(),
                    'ccy' => "XOF",
                    'crDr' => $operation->TIP_TRANSACCION == 40 ? 'D' : 'C', // Adaptation du type
                    'amount' => (string) $operation->MON_MOVIMIENTO,
                ];
            });

            // Build the success response XML with the specified structure
            $xmlResponse = <<<XML
            <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
            <soap:Body>
                <ns2:GetMiniStatementResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                <return>
                    <mmHeaderInfo>
                    <operatorCode>{$operatorCode}</operatorCode>
                    <requestId>{$requestId}</requestId>
                    <affiliateCode>{$affiliateCode}</affiliateCode>
                    <responseCode>000</responseCode>
                    <responseMessage>Success</responseMessage>
                    </mmHeaderInfo>
    XML;

            // Append each transaction to the XML response
            foreach ($transactions as $transaction) {
                $xmlResponse .= <<<XML
                    <TransactionList>
                    <tranRefNo>{$transaction['tranRefNo']}</tranRefNo>
                    <tranDate>{$transaction['tranDate']}</tranDate>
                    <ccy>{$transaction['ccy']}</ccy>
                    <crDr>{$transaction['crDr']}</crDr>
                    <amount>{$transaction['amount']}</amount>
                    </TransactionList>
    XML;
            }

            // Close the response structure
            $xmlResponse .= <<<XML
                </return>
                </ns2:GetMiniStatementResponse>
            </soap:Body>
            </soap:Envelope>
    XML;

            Log::info("MOUVEMENTS:".$xmlResponse);
            // Return the XML response
            return response($xmlResponse, 200)
                ->header('Content-Type', 'application/xml');

        } catch (\Exception $e) {
            Log::error('Error processing GetMiniStatement:', ['error' => $e->getMessage()]);
            $this->updateTransactionStatus($referenceNumber, 'E99', $e->getMessage(), 2);
            return $this->sendError("E01",$operatorCode,$requestId,$affiliateCode,'Bank technical error',$referenceNumber,"GetMiniStatementResponse");
        }
    }


    private function walletToAccountTransfer($xml)
{
    try {
        // Extract mmHeaderInfo fields from the request XML
        $mmHeaderInfo = $xml->xpath('//MobileTransferRequest/mmHeaderInfo')[0];
        $operatorCode = (string) $mmHeaderInfo->operatorCode;
        $requestId = (string) $mmHeaderInfo->requestId;
        $affiliateCode = (string) $mmHeaderInfo->affiliateCode;
        $requestType = (string) $mmHeaderInfo->requestType;
        $requestToken = (string) $mmHeaderInfo->requestToken;

        // Extract additional request fields
        $accountAlias = (string) $xml->xpath('//MobileTransferRequest/accountAlias')[0];
        $amount = (string) $xml->xpath('//MobileTransferRequest/amount')[0];
        $ccy = (string) $xml->xpath('//MobileTransferRequest/ccy')[0];

        // Generate a unique reference number for tracking purposes
        $referenceNumber =  Str::random(16);

        // Log the request in the transaction_statuses table
        DB::table('transaction_statuses')->insert([
            'date' => now(),
            'type' => 'W2B', // Wallet to Bank
            'alias' => $accountAlias,
            'currency' => $ccy,
            'amount' => $amount,
            'request_code' => $requestId,
            'response_code' => 'Pending', // Initially set as pending
            'response_message' => 'Request received',
            'reference_number' => $referenceNumber,
            'status' => 0, // 0 for pending
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        // Log mmHeaderInfo and additional request fields for debugging
        Log::info('WalletToAccountTransfer mmHeaderInfo:', [
            'operatorCode' => $operatorCode,
            'requestId' => $requestId,
            'affiliateCode' => $affiliateCode,
            'requestType' => $requestType,
            'requestToken' => $requestToken,
            'accountAlias' => $accountAlias,
            'amount' => $amount,
            'ccy' => $ccy,
        ]);

        // Process the transfer
        $result = $this->TransactionW2B($accountAlias, $amount);
        $responseCode = $result['responseCode'];
        $responseMessage = $result['responseMessage'];
        $CBAReferenceNo="";
        if ($responseCode == '000') {
            $CBAReferenceNo = $result['mouvement_id'];
             // Calcul du nombre de caractères nécessaires pour compléter la chaîne
             $randomLength = 16 - strlen($CBAReferenceNo);

             // Génération d'une chaîne aléatoire pour compléter
             $randomString = Str::random($randomLength);

             // Construction de la référence finale
             $CBAReferenceNo = $randomString . $CBAReferenceNo;
            // Successful transaction
            $responseMessage = 'Success';

            // Update transaction status to successful
            DB::table('transaction_statuses')
                ->where('reference_number', $referenceNumber)
                ->update([
                    'response_code' => $responseCode,
                    'response_message' => $responseMessage,
                    'reference_number' => $CBAReferenceNo,
                    'bank_mouvement' => $result['mouvement_id'],
                    'status' => 1, // 1 for successful
                    'updated_at' => now(),
                ]);

            // Build the success response XML
            $xmlResponse = <<<XML
            <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
              <soap:Body>
                <ns2:WalletToAccountTransferResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                  <return>
                    <mmHeaderInfo>
                      <operatorCode>{$operatorCode}</operatorCode>
                      <requestId>{$requestId}</requestId>
                      <affiliateCode>{$affiliateCode}</affiliateCode>
                      <responseCode>000</responseCode>
                      <responseMessage>Success</responseMessage>
                    </mmHeaderInfo>
                    <CBAReferenceNo>{$CBAReferenceNo}</CBAReferenceNo>
                  </return>
                </ns2:WalletToAccountTransferResponse>
              </soap:Body>
            </soap:Envelope>
XML;

Log::info('Response:'.$xmlResponse);

            // Return the XML response
            return response($xmlResponse, 200)
                ->header('Content-Type', 'application/xml');
        } else {
            // Transaction failed, update transaction status
            DB::table('transaction_statuses')
                ->where('reference_number', $referenceNumber)
                ->update([
                    'response_code' => $responseCode,
                    'response_message' => $responseMessage,
                    'status' => 0, // 0 for failed
                    'updated_at' => now(),
                ]);

                return $this->sendError("E01",$operatorCode,$requestId,$affiliateCode,'Bank technical error',$referenceNumber,"WalletToAccountTransferResponse");
            }

    } catch (\Exception $e) {
        Log::error('Error processing WalletToAccountTransfer:', ['error' => $e->getMessage()]);

        // Update the transaction log with the error details
        DB::table('transaction_statuses')
            ->where('reference_number', $referenceNumber)
            ->update([
                'response_code' => 'E99',
                'response_message' => $e->getMessage(),
                'status' => 0, // 0 for failed due to error
                'updated_at' => now(),
            ]);

            return $this->sendError("E99",$operatorCode,$requestId,$affiliateCode,'Bank technical error CODE 99',$referenceNumber,"");
        }
}





private function accountToWalletTransfer($xml)
{
    try {
        // Extract mmHeaderInfo fields from the request XML
        $mmHeaderInfo = $xml->xpath('//MobileTransferRequest/mmHeaderInfo')[0];
        $operatorCode = (string) $mmHeaderInfo->operatorCode;
        $requestId = (string) $mmHeaderInfo->requestId;
        $affiliateCode = (string) $mmHeaderInfo->affiliateCode;
        $requestToken = (string) $mmHeaderInfo->requestToken;
        $requestType = (string) $mmHeaderInfo->requestType;

        // Extract additional fields from the request
        $externalRefNo = (string) $xml->xpath('//MobileTransferRequest/externalRefNo')[0];
        $accountAlias = (string) $xml->xpath('//MobileTransferRequest/accountAlias')[0];
        $amount = (string) $xml->xpath('//MobileTransferRequest/amount')[0];
        $ccy = (string) $xml->xpath('//MobileTransferRequest/ccy')[0];
        $tranDate = (string) $xml->xpath('//MobileTransferRequest/tranDate')[0];

        // Generate a unique reference number for tracking purposes
        $referenceNumber =  Str::random(16);

        // Log the initial request in the transaction_statuses table
        DB::table('transaction_statuses')->insert([
            'date' => $tranDate,
            'type' => 'AccountToWalletTransfer',
            'alias' => $accountAlias,
            'currency' => $ccy,
            'amount' => $amount,
            'request_code' => $requestId,
            'response_code' => '', // Initially empty, updated after processing
            'response_message' => 'Pending',
            'reference_number' => $referenceNumber,
            'status' => 1, // 1 for pending
            'created_at' => now(),
            'updated_at' => now()
        ]);

        // Process the transaction
        Log::info(' Process the transaction info Alias:'.$accountAlias.' Montant:'.$amount);
        $result = $this->TransactionB2W($accountAlias, $amount);
        $responseCode = $result['responseCode'];
        $responseMessage = $result['responseMessage'];
        $CBAReferenceNo="";
        if ($responseCode == '000') {
            $CBAReferenceNo = $result['mouvement_id'];
             // Calcul du nombre de caractères nécessaires pour compléter la chaîne
             $randomLength = 16 - strlen($CBAReferenceNo);

             // Génération d'une chaîne aléatoire pour compléter
             $randomString = Str::random($randomLength);

             // Construction de la référence finale
             $CBAReferenceNo = $randomString . $CBAReferenceNo;
            // Transaction was successful

            // Update the transaction_statuses table with success details
            DB::table('transaction_statuses')
                ->where('reference_number', $referenceNumber)
                ->update([
                    'response_code' => $responseCode,
                    'response_message' => $responseMessage,
                    'reference_number' => $CBAReferenceNo,
                    'bank_mouvement' => $result['mouvement_id'],
                    'status' => 0, // 0 for success
                    'updated_at' => now()
                ]);

            // Build the success XML response
            $xmlResponse = <<<XML
            <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
              <soap:Body>
                <ns2:AccountToWalletTransferResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                  <return>
                    <mmHeaderInfo>
                      <operatorCode>{$operatorCode}</operatorCode>
                      <requestId>{$requestId}</requestId>
                      <affiliateCode>{$affiliateCode}</affiliateCode>
                      <responseCode>{$responseCode}</responseCode>
                      <responseMessage>{$responseMessage}</responseMessage>
                    </mmHeaderInfo>
                    <CBAReferenceNo>{$CBAReferenceNo}</CBAReferenceNo>
                  </return>
                </ns2:AccountToWalletTransferResponse>
              </soap:Body>
            </soap:Envelope>
XML;

                Log::info('Response:'.$xmlResponse);


            // Return the XML response
            return response($xmlResponse, 200)
                ->header('Content-Type', 'application/xml');
        }
        elseif($responseCode=="E16"){
             // Transaction failed; update the transaction_statuses table
             DB::table('transaction_statuses')
             ->where('reference_number', $referenceNumber)
             ->update([
                 'response_code' => $responseCode,
                 'response_message' => $responseMessage,
                 'status' => 2, // 2 for failure
                 'updated_at' => now()
             ]);

         // Return the failure response
         return $this->sendError($responseCode,$operatorCode,$requestId,$affiliateCode,$responseMessage,$referenceNumber,"AccountToWalletTransferResponse");

        }
        
        else {
            // Transaction failed; update the transaction_statuses table
            DB::table('transaction_statuses')
                ->where('reference_number', $referenceNumber)
                ->update([
                    'response_code' => $responseCode,
                    'response_message' => $responseMessage,
                    'status' => 2, // 2 for failure
                    'updated_at' => now()
                ]);

            // Return the failure response
            return $this->sendError("010",$operatorCode,$requestId,$affiliateCode,'Bank technical error',$referenceNumber,"AccountToWalletTransferResponse");

        }

    } catch (\Exception $e) {
        // Log the error for debugging
        Log::error('Error processing AccountToWalletTransfer:', ['error' => $e->getMessage()]);

        // Update the transaction_statuses table with error details
        DB::table('transaction_statuses')
            ->where('reference_number', $referenceNumber)
            ->update([
                'response_code' => $responseCode, // Custom error code
                'response_message' => $e->getMessage(),
                'status' => 2, // 2 for failure
                'updated_at' => now()
            ]);

        // Return error response
        return $this->sendError($responseCode,$operatorCode,$requestId,$affiliateCode,'Bank technical error',$referenceNumber,"AccountToWalletTransferResponse");

    }
}


private function transferStatusInquiry($xml)
{
    try {
        // Extract mmHeaderInfo fields from the request XML
        $mmHeaderInfo = $xml->xpath('//TranRequestInfo/mmHeaderInfo')[0];
        $operatorCode = (string) $mmHeaderInfo->operatorCode;
        $requestId = (string) $mmHeaderInfo->requestId;
        $affiliateCode = (string) $mmHeaderInfo->affiliateCode;
        // Extract the externalRefNo from the request

         // Generate a unique reference number for tracking purposes
         $referenceNumber =  Str::random(16);
         $tranDate=date('Y-m-d H:i:s');
         $externalRefNo = (string) $xml->xpath('//TranRequestInfo/externalRefNo')[0];

         $transfert_info=TransactionStatus::where('reference_number',$externalRefNo)->orWhere('request_code',$externalRefNo)->latest()->first();

         // Log the initial request in the transaction_statuses table
         DB::table('transaction_statuses')->insert([
             'date' => $tranDate,
             'type' => 'transferStatusInquiry',
             'alias' => $transfert_info->alias,
             'currency' => "",
             'amount' => $transfert_info->amount,
             'request_code' => $requestId,
             'response_code' => '', // Initially empty, updated after processing
             'response_message' => 'Pending',
             'reference_number' => $referenceNumber,
             'status' => 1, // 1 for pending
             'created_at' => now(),
             'updated_at' => now()
         ]);
         Log::info(' Process 2 the transaction info Alias:'.$transfert_info->alias.' Montant:'.$transfert_info->amount);


        // Log the request for debugging
        Log::info('TransferStatusInquiry Request:', [
            'operatorCode' => $operatorCode,
            'requestId' => $requestId,
            'affiliateCode' => $affiliateCode,
            'externalRefNo' => $externalRefNo,
        ]);

        //check
        if($transfert_info==null){

             // Transaction failed; update the transaction_statuses table
             DB::table('transaction_statuses')
             ->where('reference_number', $referenceNumber)
             ->update([
                 'response_code' => "E11",
                 'response_message' => "Operation in Timeout",
                 'status' => 2, // 2 for failure
                 'updated_at' => now()
             ]);
            $xmlResponse = <<<XML
        <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
          <S:Body>
            <ns2:TransferStatusInquiryResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
              <return>
                <mmHeaderInfo>
                  <operatorCode>{$operatorCode}</operatorCode>
                  <requestId>{$requestId}</requestId>
                  <affiliateCode>{$affiliateCode}</affiliateCode>
                  <responseCode>E11</responseCode>
                  <responseMessage>Bank Technical error isset</responseMessage>
                </mmHeaderInfo>
                <CBAReferenceNo></CBAReferenceNo>
              </return>
            </ns2:TransferStatusInquiryResponse>
          </S:Body>
        </S:Envelope>
XML;
        Log::info('ResponseError No Transaction found:'.$xmlResponse);


        // Return the XML response
        return response($xmlResponse, 200)
        ->header('Content-Type', 'application/xml');
        }
        else{

            $accountAlias=$transfert_info->alias;
            $amount=$transfert_info->amount;


            // Process the transaction
            if($transfert_info->type=='AccountToWalletTransfer' || $transfert_info->type=='A2W' || $transfert_info->type=='B2W'){
                $result = $this->TransactionB2W($accountAlias, $amount);
            }
            elseif($transfert_info->type=='W2A' || $transfert_info->type=='walletToAccountTransfer' || $transfert_info->type=='W2B'){
                $result = $this->TransactionW2B($accountAlias, $amount);
            }
            else{
                $responseCode = 'E11';
                $responseMessage = "Unsupported transaction type";
                $CBAReferenceNo = Str::random(16);
                 // Transaction failed; update the transaction_statuses table
             DB::table('transaction_statuses')
             ->where('reference_number', $referenceNumber)
             ->update([
                 'response_code' => "E11",
                 'response_message' => "Unsupported transaction type",
                 'status' => 2, // 2 for failure
                 'updated_at' => now()
             ]);
                 // Build the XML response structure
            $xmlResponse = <<<XML
            <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
              <S:Body>
                <ns2:TransferStatusInquiryResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                  <return>
                    <mmHeaderInfo>
                      <operatorCode>{$operatorCode}</operatorCode>
                      <requestId>{$requestId}</requestId>
                      <affiliateCode>{$affiliateCode}</affiliateCode>
                      <responseCode>{$responseCode}</responseCode>
                      <responseMessage>{$responseMessage}</responseMessage>
                    </mmHeaderInfo>
                    <CBAReferenceNo>{$CBAReferenceNo}</CBAReferenceNo>
                  </return>
                </ns2:TransferStatusInquiryResponse>
              </S:Body>
            </S:Envelope>
        XML;
        Log::info('ResponseError Unsupported transaction type:'.$xmlResponse);

        // Return the XML response
        return response($xmlResponse, 200)
        ->header('Content-Type', 'application/xml');

            }


            $responseCode = $result['responseCode'];
            $responseMessage = $result['responseMessage'];
            $CBAReferenceNo="";
            if ($responseCode == '000') {
                $CBAReferenceNo = $result['mouvement_id'];
                // Calcul du nombre de caractères nécessaires pour compléter la chaîne
                $randomLength = 16 - strlen($CBAReferenceNo);

                // Génération d'une chaîne aléatoire pour compléter
                $randomString = Str::random($randomLength);

                // Construction de la référence finale
                $CBAReferenceNo = $randomString . $CBAReferenceNo;
                // Transaction was successful

                // Update the transaction_statuses table with success details
                DB::table('transaction_statuses')
                    ->where('reference_number', $referenceNumber)
                    ->update([
                        'response_code' => $responseCode,
                        'response_message' => $responseMessage,
                        'reference_number' => $CBAReferenceNo,
                        'bank_mouvement' => $result['mouvement_id'],
                        'status' => 0, // 0 for success
                        'updated_at' => now()
                    ]);
                // Fetch the response message based on the code
            $responseMessage = $this->getReturnCodeDescription($responseCode);
            $transfert_info->update([
                'response_code' => $responseCode,
                'response_message' => $responseMessage,
                'reference_number' => $CBAReferenceNo,
                'bank_mouvement' => $result['mouvement_id'],
                'status' => 0, // 0 for success
                'updated_at' => now()
            ]);

            // Build the XML response structure
            $xmlResponse = <<<XML
            <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
              <S:Body>
                <ns2:TransferStatusInquiryResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                  <return>
                    <mmHeaderInfo>
                      <operatorCode>{$operatorCode}</operatorCode>
                      <requestId>{$requestId}</requestId>
                      <affiliateCode>{$affiliateCode}</affiliateCode>
                      <responseCode>{$responseCode}</responseCode>
                      <responseMessage>{$responseMessage}</responseMessage>
                    </mmHeaderInfo>
                    <CBAReferenceNo>{$CBAReferenceNo}</CBAReferenceNo>
                  </return>
                </ns2:TransferStatusInquiryResponse>
              </S:Body>
            </S:Envelope>
        XML;

        Log::info('ResponseSuccess:'.$xmlResponse);

        // Return the XML response
        return response($xmlResponse, 200)
        ->header('Content-Type', 'application/xml');
            }
            elseif($responseCode=="E16"){
                // Transaction failed; update the transaction_statuses table
                DB::table('transaction_statuses')
                ->where('reference_number', $referenceNumber)
                ->update([
                    'response_code' => $responseCode,
                    'response_message' => $responseMessage,
                    'status' => 2, // 2 for failure
                    'updated_at' => now()
                ]);
   
            // Return the failure response
            return $this->sendError($responseCode,$operatorCode,$requestId,$affiliateCode,$responseMessage,$referenceNumber,"AccountToWalletTransferResponse");
   
           }
            else{
                 // Transaction failed; update the transaction_statuses table
             DB::table('transaction_statuses')
             ->where('reference_number', $referenceNumber)
             ->update([
                 'response_code' => "E11",
                 'response_message' => "Operation in Timeout",
                 'status' => 2, // 2 for failure
                 'updated_at' => now()
             ]);
                $xmlResponse = <<<XML
                <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
                  <S:Body>
                    <ns2:TransferStatusInquiryResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                      <return>
                        <mmHeaderInfo>
                          <operatorCode>{$operatorCode}</operatorCode>
                          <requestId>{$requestId}</requestId>
                          <affiliateCode>{$affiliateCode}</affiliateCode>
                          <responseCode>E11</responseCode>
                          <responseMessage>Operation in Timeout</responseMessage>
                        </mmHeaderInfo>
                        <CBAReferenceNo></CBAReferenceNo>
                      </return>
                    </ns2:TransferStatusInquiryResponse>
                  </S:Body>
                </S:Envelope>
        XML;

        Log::info('ResponseErrorCodeDiffSuccess:'.$xmlResponse);


                // Return the XML response
            return response($xmlResponse, 200)
            ->header('Content-Type', 'application/xml');
            }

        }



    } catch (\Exception $e) {
        // Log the error for debugging
        Log::error('Error processing TransferStatusInquiry:', ['error' => $e->getMessage()]);
         // Transaction failed; update the transaction_statuses table
         DB::table('transaction_statuses')
         ->where('reference_number', $referenceNumber)
         ->update([
             'response_code' => "E11",
             'response_message' => "Operation in Timeout",
             'status' => 2, // 2 for failure
             'updated_at' => now()
         ]);
        $responseCode = 'E11';
                $responseMessage = "Unsupported transaction type";
                $CBAReferenceNo = Str::random(16);
                 // Build the XML response structure
            $xmlResponse = <<<XML
            <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
              <S:Body>
                <ns2:TransferStatusInquiryResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                  <return>
                    <mmHeaderInfo>
                      <operatorCode>{$operatorCode}</operatorCode>
                      <requestId>{$requestId}</requestId>
                      <affiliateCode>{$affiliateCode}</affiliateCode>
                      <responseCode>{$responseCode}</responseCode>
                      <responseMessage>{$responseMessage}</responseMessage>
                    </mmHeaderInfo>
                    <CBAReferenceNo></CBAReferenceNo>
                  </return>
                </ns2:TransferStatusInquiryResponse>
              </S:Body>
            </S:Envelope>
        XML;

        Log::info('ResponseErrorServeur:'.$xmlResponse.$e->getMessage());

        // Return the XML response
        return response($xmlResponse, 200)
        ->header('Content-Type', 'application/xml');
    }
}



private function CancelTransfer($xml)
{
    try {
        // Extract mmHeaderInfo fields from the request XML
        $mmHeaderInfo = $xml->xpath('//TranRequestInfo/mmHeaderInfo')[0];
        $operatorCode = (string) $mmHeaderInfo->operatorCode;
        $requestId = (string) $mmHeaderInfo->requestId;
        $affiliateCode = (string) $mmHeaderInfo->affiliateCode;
        // Extract the externalRefNo from the request

         // Generate a unique reference number for tracking purposes
         $referenceNumber =  Str::random(16);
         $tranDate=date('Y-m-d H:i:s');

         // Log the initial request in the transaction_statuses table
         DB::table('transaction_statuses')->insert([
             'date' => $tranDate,
             'type' => 'CancelTransfer',
             'alias' => "",
             'currency' => "",
             'amount' => 0,
             'request_code' => $requestId,
             'response_code' => '', // Initially empty, updated after processing
             'response_message' => 'Pending',
             'reference_number' => $referenceNumber,
             'status' => 1, // 1 for pending
             'created_at' => now(),
             'updated_at' => now()
         ]);
        $externalRefNo = (string) $xml->xpath('//TranRequestInfo/externalRefNo')[0];

        // Log the request for debugging
        Log::info('TransferStatusInquiry Request:', [
            'operatorCode' => $operatorCode,
            'requestId' => $requestId,
            'affiliateCode' => $affiliateCode,
            'externalRefNo' => $externalRefNo,
        ]);

        $transfert_info=TransactionStatus::where('reference_number',$externalRefNo)->orWhere('request_code',$externalRefNo)->latest()->first();
        //check
        if($transfert_info==null){

             // Transaction failed; update the transaction_statuses table
             DB::table('transaction_statuses')
             ->where('reference_number', $referenceNumber)
             ->update([
                 'response_code' => "E11",
                 'response_message' => "Operation in Timeout",
                 'status' => 2, // 2 for failure
                 'updated_at' => now()
             ]);
            $xmlResponse = <<<XML
        <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
          <S:Body>
            <ns2:CancelTransferResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
              <return>
                <mmHeaderInfo>
                  <operatorCode>{$operatorCode}</operatorCode>
                  <requestId>{$requestId}</requestId>
                  <affiliateCode>{$affiliateCode}</affiliateCode>
                  <responseCode>E11</responseCode>
                  <responseMessage>Operation in Timeout</responseMessage>
                </mmHeaderInfo>
                <CBAReferenceNo></CBAReferenceNo>
              </return>
            </ns2:CancelTransferResponse>
          </S:Body>
        </S:Envelope>
XML;    
             Log::info('ResponseError No Transaction found:'.$xmlResponse);

        // Return the XML response
        return response($xmlResponse, 200)
        ->header('Content-Type', 'application/xml');
        }
        else{

            $accountAlias=$transfert_info->alias;
            $amount=$transfert_info->amount;


            // Process the transaction
            if($transfert_info->type=='AccountToWalletTransfer' || $transfert_info->type=='A2W' || $transfert_info->type=='B2W'){
                $result = $this->TransactionB2WCancel($accountAlias, $amount);
            }
            elseif($transfert_info->type=='W2A' || $transfert_info->type=='walletToAccountTransfer' || $transfert_info->type=='W2B'){
                $result = $this->TransactionW2BCancel($accountAlias, $amount);
            }
            else{
                $responseCode = 'E11';
                $responseMessage = "Unsupported transaction type";
                $CBAReferenceNo = Str::random(16);
                 // Transaction failed; update the transaction_statuses table
             DB::table('transaction_statuses')
             ->where('reference_number', $referenceNumber)
             ->update([
                 'response_code' => "E11",
                 'response_message' => "Unsupported transaction type",
                 'status' => 2, // 2 for failure
                 'updated_at' => now()
             ]);
                 // Build the XML response structure
            $xmlResponse = <<<XML
            <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
              <S:Body>
                <ns2:CancelTransferResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                  <return>
                    <mmHeaderInfo>
                      <operatorCode>{$operatorCode}</operatorCode>
                      <requestId>{$requestId}</requestId>
                      <affiliateCode>{$affiliateCode}</affiliateCode>
                      <responseCode>{$responseCode}</responseCode>
                      <responseMessage>{$responseMessage}</responseMessage>
                    </mmHeaderInfo>
                    <CBAReferenceNo></CBAReferenceNo>
                  </return>
                </ns2:CancelTransferResponse>
              </S:Body>
            </S:Envelope>
        XML;

        Log::info('Unsupported transaction type:'.$xmlResponse);
        // Return the XML response
        return response($xmlResponse, 200)
        ->header('Content-Type', 'application/xml');

            }


            $responseCode = $result['responseCode'];
            $responseMessage = $result['responseMessage'];
            $CBAReferenceNo="";
            if ($responseCode == '000') {
                $CBAReferenceNo = $result['mouvement_id'];
                 // Calcul du nombre de caractères nécessaires pour compléter la chaîne
                 $randomLength = 16 - strlen($CBAReferenceNo);

                 // Génération d'une chaîne aléatoire pour compléter
                 $randomString = Str::random($randomLength);
 
                 // Construction de la référence finale
                 $CBAReferenceNo = $randomString . $CBAReferenceNo;
                // Transaction was successful

                // Update the transaction_statuses table with success details
                DB::table('transaction_statuses')
                    ->where('reference_number', $referenceNumber)
                    ->update([
                        'response_code' => $responseCode,
                        'response_message' => $responseMessage,
                        'reference_number' => $CBAReferenceNo,
                        'bank_mouvement' => $result['mouvement_id'],
                        'status' => 0, // 0 for success
                        'updated_at' => now()
                    ]);
                    $transfert_info->update([
                        'response_code' => $responseCode,
                        'response_message' => $responseMessage,
                        'reference_number' => $CBAReferenceNo,
                        'bank_mouvement' => $result['mouvement_id'],
                        'status' => 0, // 0 for success
                        'updated_at' => now()
                    ]);
                // Fetch the response message based on the code
            $responseMessage = $this->getReturnCodeDescription($responseCode);

            // Build the XML response structure
            $xmlResponse = <<<XML
            <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
              <S:Body>
                <ns2:CancelTransferResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                  <return>
                    <mmHeaderInfo>
                      <operatorCode>{$operatorCode}</operatorCode>
                      <requestId>{$requestId}</requestId>
                      <affiliateCode>{$affiliateCode}</affiliateCode>
                      <responseCode>{$responseCode}</responseCode>
                      <responseMessage>{$responseMessage}</responseMessage>
                    </mmHeaderInfo>
                    <CBAReferenceNo>{$CBAReferenceNo}</CBAReferenceNo>
                  </return>
                </ns2:CancelTransferResponse>
              </S:Body>
            </S:Envelope>
        XML;
        Log::info('ResponseSuccess:'.$xmlResponse);
        // Return the XML response
        return response($xmlResponse, 200)
        ->header('Content-Type', 'application/xml');
            }
            else{
                 // Transaction failed; update the transaction_statuses table
             DB::table('transaction_statuses')
             ->where('reference_number', $referenceNumber)
             ->update([
                 'response_code' => "E11",
                 'response_message' => "Operation in Timeout",
                 'status' => 2, // 2 for failure
                 'updated_at' => now()
             ]);
                $xmlResponse = <<<XML
                <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
                  <S:Body>
                    <ns2:CancelTransferResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                      <return>
                        <mmHeaderInfo>
                          <operatorCode>{$operatorCode}</operatorCode>
                          <requestId>{$requestId}</requestId>
                          <affiliateCode>{$affiliateCode}</affiliateCode>
                          <responseCode>E11</responseCode>
                          <responseMessage>Operation in Timeout</responseMessage>
                        </mmHeaderInfo>
                        <CBAReferenceNo></CBAReferenceNo>
                      </return>
                    </ns2:CancelTransferResponse>
                  </S:Body>
                </S:Envelope>
        XML;

        Log::info('ResponseErrorCodeDiffSuccess :'.$xmlResponse);

                // Return the XML response
            return response($xmlResponse, 200)
            ->header('Content-Type', 'application/xml');
            }

        }



    } catch (\Exception $e) {
        // Log the error for debugging
        Log::error('Error processing TransferStatusInquiry:', ['error' => $e->getMessage()]);
         // Transaction failed; update the transaction_statuses table
         DB::table('transaction_statuses')
         ->where('reference_number', $referenceNumber)
         ->update([
             'response_code' => "E01",
             'response_message' => "Bank Technical error",
             'status' => 2, // 2 for failure
             'updated_at' => now()
         ]);
        $responseCode = 'E11';
                $responseMessage = "Unsupported transaction type";
                $CBAReferenceNo = Str::random(16);
                 // Build the XML response structure
            $xmlResponse = <<<XML
            <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
              <S:Body>
                <ns2:CancelTransferResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">
                  <return>
                    <mmHeaderInfo>
                      <operatorCode>{$operatorCode}</operatorCode>
                      <requestId>{$requestId}</requestId>
                      <affiliateCode>{$affiliateCode}</affiliateCode>
                      <responseCode>{$responseCode}</responseCode>
                      <responseMessage>{$responseMessage}</responseMessage>
                    </mmHeaderInfo>
                    <CBAReferenceNo></CBAReferenceNo>
                  </return>
                </ns2:CancelTransferResponse>
              </S:Body>
            </S:Envelope>
        XML;
        Log::info('ResponseErrorServeur :'.$xmlResponse.$e->getMessage());

        // Return the XML response
        return response($xmlResponse, 200)
        ->header('Content-Type', 'application/xml');
    }
}




private function sendError($responseCode,$operatorCode,$requestId,$affiliateCode,$responseMessage,$CBAReferenceNo,$action)
{

    if($action==null){
        $errorXml = '<?xml version="1.0" encoding="UTF-8"?>';
        $errorXml .= '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">';
        $errorXml .= '<soapenv:Body>';
        $errorXml .= '<soapenv:Fault>';
        $errorXml .= '<faultcode>SOAP-ENV:Client</faultcode>';
        $errorXml .= '<responseCode>' . $responseCode . '</responseCode>';
        $errorXml .= '<faultstring>' . $responseMessage . '</faultstring>';
        $errorXml .= '<CBAReferenceNo></CBAReferenceNo>';
        $errorXml .= '</soapenv:Fault>';
        $errorXml .= '</soapenv:Body>';
        $errorXml .= '</soapenv:Envelope>';
        Log::info("ErrorResponse : ".$errorXml);


    return response($errorXml, 500)
        ->header('Content-Type', 'application/xml');

    }
    else{
        $errorXml = '<?xml version="1.0" encoding="UTF-8"?>';
        $errorXml .= '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">';
        $errorXml .= '<soap:Body>';
        $errorXml .= '<ns2:' . $action . ' xmlns:ns2="http://b2w.banktowallet.com/b2w">';
        $errorXml .= '<return>';
        $errorXml .= '<mmHeaderInfo>';
        $errorXml .= '<operatorCode>' . $operatorCode . '</operatorCode>';
        $errorXml .= '<requestId>' . $requestId . '</requestId>';
        $errorXml .= '<affiliateCode>' . $affiliateCode . '</affiliateCode>';
        $errorXml .= '<responseCode>' . $responseCode . '</responseCode>';
        $errorXml .= '<responseMessage>' . $responseMessage . '</responseMessage>';
        $errorXml .= '</mmHeaderInfo>';
        $errorXml .= '<CBAReferenceNo>' . $CBAReferenceNo . '</CBAReferenceNo>';
        $errorXml .= '</return>';
        $errorXml .= '</ns2:' . $action . '>';
        $errorXml .= '</soap:Body>';
        $errorXml .= '</soap:Envelope>';
        Log::info("ErrorResponse : ".$errorXml);


    return response($errorXml, 200)
        ->header('Content-Type', 'application/xml');

    }
    
}
private static function sendtransfertError($responseCode, $requestId,$operatorCode,$affiliateCode, $CBAReferenceNo)
{
    $instance = new self();
    $responseMessage = $instance->getReturnCodeDescription($responseCode);

    $errorXml = '<?xml version="1.0" encoding="UTF-8"?>';
    $errorXml .= '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">';
    $errorXml .= '<soap:Body>';
    $errorXml .= '<ns2:TransferStatusInquiryResponse xmlns:ns2="http://b2w.banktowallet.com/b2w">';
    $errorXml .= '<return>';
    $errorXml .= '<mmHeaderInfo>';
    $errorXml .= '<operatorCode>' . $operatorCode . '</operatorCode>';
    $errorXml .= '<requestId>' . $requestId . '</requestId>';
    $errorXml .= '<affiliateCode>' . $affiliateCode . '</affiliateCode>';
    $errorXml .= '<responseCode>' . $responseCode . '</responseCode>';
    $errorXml .= '<responseMessage>' . $responseMessage . '</responseMessage>';
    $errorXml .= '</mmHeaderInfo>';
    $errorXml .= '<CBAReferenceNo>' . $CBAReferenceNo . '</CBAReferenceNo>';
    $errorXml .= '</return>';
    $errorXml .= '</ns2:TransferStatusInquiryResponse>';
    $errorXml .= '</soap:Body>';
    $errorXml .= '</soap:Envelope>';


    Log::info("ErrorResponseCode : ".$errorXml);

    return response($errorXml, 500)
        ->header('Content-Type', 'application/xml');
}



// Define an associative array of return codes and descriptions
private function getReturnCodeDescription($code)
{
    $errorCodes = [
        '000' => 'Success',
        '010' => 'Bank Technical Error',
        'E01' => 'Bank Technical Error',
        'E02' => 'Bank Technical Error',
        'E03' => 'Bank Technical Error',
        'E04' => 'Bank Technical Error',
        'E05' => 'Bank Technical Error',
        'E06' => 'Bank Technical Error',
        'E07' => 'Bank Technical Error',
        'E08' => 'Bank Technical Error',
        'E09' => 'Bank Technical Error',
        'E10' => 'Bank Technical Error',
        'E11' => 'Operation in Timeout. Use TransferStatusInquiry to check status',
        'E12' => 'Bank Technical Error',
        'E13' => 'Unauthorized Request on Account (crossed thresholds)',
        'E14' => 'Unauthorized Request on Account (crossed thresholds)',
        'E15' => 'Unauthorized Request on Account (crossed thresholds)',
        'E16' => 'Insufficient Balance',
        'E17' => 'Bank Technical Error',
        'E18' => 'Bank Technical Error',
        'E19' => 'Bank Technical Error',
        'E20' => 'Bank Technical Error',
        'E21' => 'Bank Technical Error',
        'E22' => 'Transaction Violates Account\'s Minimum Balance',
        'E35' => 'Bank Technical Error',
        'E99' => 'Bank Technical Error',
    ];

    // Return the description for the given code, or a default message if the code is not found
    return isset($errorCodes[$code]) ? $errorCodes[$code] : 'Unknown Error';
}










//First example method teste pass ok


// public function getAccountBalance(Request $request)
//     {
//     // Retrieve the raw XML request
//     $xmlRequest = $request->getContent();


//     // Use internal error handling for libxml
//     libxml_use_internal_errors(true);

//     // Try to create a SimpleXMLElement
//     try {
//         $xml = new SimpleXMLElement($xmlRequest);
//     } catch (Exception $e) {
//         throw new Exception("Failed to parse XML: " . $e->getMessage());
//     }

//     // Check for XML parsing errors
//     if (libxml_get_errors()) {
//         $errors = libxml_get_errors();
//         libxml_clear_errors();
//         throw new Exception("XML Errors: " . implode(", ", array_map(fn($error) => $error->message, $errors)));
//     }

//     // Print the parsed XML for debugging
//     //print_r($xml);

//     // Register the namespaces for XPath queries
//     $xml->registerXPathNamespace('soapenv', 'http://schemas.xmlsoap.org/soap/envelope/');
//     $xml->registerXPathNamespace('ns1', 'http://b2w.banktowallet.com/b2w');

//     // Get the SOAP body
//     $body = $xml->xpath('//soapenv:Body');

//     if (empty($body)) {
//         throw new Exception("No SOAP body found in the response.");
//     }

//     // Get the specific response (e.g., GetAccountBalance)
//     $accountBalance = $body[0]->xpath('//ns1:GetAccountBalance');

//     if (empty($accountBalance)) {
//         throw new Exception("No GetAccountBalance found in the response.");
//     }

//     // Convert the body to JSON and then decode it
//     $json = json_encode((array)$accountBalance[0], JSON_THROW_ON_ERROR);
//     $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);

//     $operatorCode = $data['AccountBalanceInquiryRequest']['mmHeaderInfo']['operatorCode'] ?? null;
//     $requestId = $data['AccountBalanceInquiryRequest']['mmHeaderInfo']['requestId']?? null;
//     $requestToken = $data['AccountBalanceInquiryRequest']['mmHeaderInfo']['requestToken']?? null;
//     $requestType = $data['AccountBalanceInquiryRequest']['mmHeaderInfo']['requestType']?? null;
//     $affiliateCode = $data['AccountBalanceInquiryRequest']['mmHeaderInfo']['affiliateCode']?? null;
//     $accountNo = $data['AccountBalanceInquiryRequest']['accountNo']?? null;
//     $accountAlias = $data['AccountBalanceInquiryRequest']['accountAlias']?? null;
//     //return $data;

//     //GET BALANCES SOLDE
//     $availableBalance=$this->getBalance($accountNo);
//     $ccy="XOF";


//         // Construct the response XML
//         $responseXml = <<<XML
//         <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:b2w="http://b2w.banktowallet.com/b2w">
//             <soapenv:Header/>
//             <soapenv:Body>
//                 <b2w:GetAccountBalanceResponse>
//                 <return>
//                     <mmHeaderInfo>
//                         <operatorCode>$operatorCode</operatorCode>
//                         <requestId>$requestId</requestId>
//                         <affiliateCode>$affiliateCode</affiliateCode>
//                         <responseCode>000</responseCode>
//                         <responseMessage>Success</responseMessage>
//                     </mmHeaderInfo>
//                     <accountAlias>$accountAlias</accountAlias>
//                     <ccy>$ccy</ccy>
//                     <availableBalance>$availableBalance</availableBalance>
//                     <currentBalance>$availableBalance</currentBalance>
//                 </return>

//                 </b2w:GetAccountBalanceResponse>
//             </soapenv:Body>
//         </soapenv:Envelope>
//         XML;

//         return response($responseXml, 200)
//             ->header('Content-Type', 'text/xml');

// }


}




