<?php

namespace App\Http\Controllers;

use App\Http\Controllers\GSController;
use App\Http\Controllers\BalanceM;
use App\Http\Controllers\BalanceV;
use App\Models\LadgerDB;
use App\Models\LadgerDBV;
use App\Models\PayoutBD;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use App\Models\payoutBDConfigV;
use App\Models\p2cBDConfigV;
use App\Models\p2pBDConfigV;


class DistributeV extends Controller
{

    public static function distributeRequests1($channel, $amount, $type, $mode)
    {
        // Retrieve all vendors with their total received payment and payout amounts
        $vendors = self::getAllVendors($channel, $type, $mode);

       // Distribute the request among vendors with available balances
    if ($mode == 'P2C') {
        $vendor = self::p2cdistributeRequestAmongAvailableVendors($vendors, $amount);
    } else {
        $vendor = self::distributeRequestAmongAvailableVendors($vendors, $amount, $mode);
    }
        return $vendor;
    }

public static function distributeRequests($channel, $amount, $type, $mode)
{

    $vendors = self::getAllVendors($channel, $type, $mode);
    
    // Priority vendors
    $priorityVendors = self::getPriorityVendors($vendors);

    // Priority vendors
    if ($mode == 'P2C') {
        $vendor = self::p2cdistributeRequestAmongAvailableVendors($priorityVendors, $amount);
    } else {
        $vendor = self::distributeRequestAmongAvailableVendors($priorityVendors, $amount, $mode);
    }

    // Normal vendors
    if (!$vendor) {
        if ($mode == 'P2C') {
            $vendor = self::p2cdistributeRequestAmongAvailableVendors($vendors, $amount);
        } else {
            $vendor = self::distributeRequestAmongAvailableVendors($vendors, $amount, $mode);
        }
    }

    return $vendor;
}

    public static function getAllVendors($channel, $type, $mode)
{
    $vendorTable = '';
    $selectColumns = '';

    if ($type == 'OUT' && $mode == 'PAYOUT') {
        $vendorTable = 'payoutBDConfigV';
        $selectColumns = 'payoutBDConfigV.*';
    } elseif ($mode == 'P2P') {
        $vendorTable = 'p2pBDConfigV';
        $selectColumns = 'p2pBDConfigV.*';
    } else {
        $vendorTable = 'p2cBDConfigV';
        $selectColumns = 'p2cBDConfigV.*';
    }

    $query = DB::table('accountList')
        ->join($vendorTable, 'accountList.accountID', '=', $vendorTable . '.accountID')
        ->where('accountList.utype', 'VENDOR')
        ->where('accountList.traffic', 'A')
        ->where("$vendorTable.channel", $channel)
        ->where("$vendorTable.mode", 'ON')
        ->selectRaw($selectColumns) 
        ->addSelect('accountList.wlimit', 'accountList.is_priority');

    
    if ($vendorTable == 'p2cBDConfigV') {
        $query->where("$vendorTable.hold", 'N');
    }
    
    $vendors = $query->get();


    $vendorsWithTotalAmounts = $vendors->map(function ($vendor) use ($mode) {
        $vendor->total_balance = self::getTotalReceivedPaymentForVendor($vendor->accountID,$vendor->wlimit);
        if ($mode == 'P2C') {
            $vendor->vendor_limit = self::getLimitForVendor($vendor->accountID,$vendor->uid);
        }
        return $vendor;
    });

    return $vendorsWithTotalAmounts;
}

public static function getTotalReceivedPaymentForVendor($vendorId, $limit)
{
    try {

        $balance = DB::table('ladgerVBL')
            ->where('accountID', $vendorId)
            ->value('balance'); 
        
        if ($balance !== null && $balance <= 7000) {
            $balance = BalanceV::getBalance($vendorId);
            DB::table('ladgerVBL')
                ->where('accountID', $vendorId)
                ->update(['balance' => $balance]);
         $balance = DB::table('ladgerVBL')
            ->where('accountID', $vendorId)
            ->value('balance');       
        }

        return $balance ?? 0; 
    } catch (\Exception $e) {
        return 0;
    }
}


public static function getPriorityVendors($vendors)
{
    return $vendors->filter(function ($vendor) {
        return $vendor->is_priority === 'Y';
    });
}

public static function getLimitForVendor($vendorId, $channelId)
{
    try {
        $limit = ['daily' => 0, 'monthly' => 0];

        $checkLimit = p2cBDConfigV::where('accountID', $vendorId)
            ->where('uid', $channelId)
            ->first();

        if ($checkLimit) {
            $limit['daily'] = $checkLimit->daily_used;
            $limit['monthly'] = $checkLimit->monthly_used;
        }

        return $limit;

    } catch (\Exception $e) {
        return ['daily' => 0, 'monthly' => 0];
    }
}




    public static function distributeRequestAmongAvailableVendors($vendors, $amount, $mode)
    {
        // Calculate the total available balance of all vendors
        $shuffledVendors = $vendors->shuffle();
        $remainingAmount = $amount;
        $selectedVendor = null;

        // Iterate through vendors with available balances
        foreach ($shuffledVendors as $vendor) {
            if ($vendor->total_balance >= $amount) {
                $selectedVendor = $vendor;
                $remainingAmount -= $amount;
                if($mode== 'PAYOUT'){
                 $balance = $vendor->total_balance + $amount;   
                }else{
                $balance = $vendor->total_balance - $amount;
                }
                self::updateVendorBalance($vendor->accountID, $balance);
                // If the remaining amount is zero, break the loop
                if ($remainingAmount <= 0) {
                    break;
                }
            }else{
            
           $affect = DB::table('p2pBDConfigV')->where('id', $vendor->id)->update(['mode' => 'OFF']);  
            }
        }

        // If there is still a remaining amount, distribute it to another vendor
        if ($remainingAmount > 0) {
            $selectedVendor = self::distributeRemainingAmount($shuffledVendors, $remainingAmount, $mode);
        }

        return $selectedVendor;
    }


public static function p2cdistributeRequestAmongAvailableVendors($vendors, $amount)
{
 
    $shuffledVendors = $vendors->shuffle();
    $remainingAmount = $amount;
    $selectedVendor = null;

    foreach ($shuffledVendors as $vendor) {

        $monthlyAvailable = $vendor->monthly_limit - $vendor->vendor_limit['monthly'];
        $dailyAvailable = $vendor->daily_limit - $vendor->vendor_limit['daily'];

        if (
            $vendor->total_balance >= $amount &&
            $monthlyAvailable >= $amount &&
            $dailyAvailable >= $amount
        ) {

            $selectedVendor = $vendor;
            $remainingAmount -= $amount;
            $newBalance = $vendor->total_balance - $amount;

            $newDailyLimit = $vendor->vendor_limit['daily'] + $amount;
            $newMonthlyLimit = $vendor->vendor_limit['monthly'] + $amount;

            self::updateVendorBalance($vendor->accountID, $newBalance);
            self::updateVendorLimit($vendor->uid, $newDailyLimit, $newMonthlyLimit);

            if ($remainingAmount <= 0) {
                break;
            }
        } else {
      
            if ($vendor->wlimit !== 'N') {
                $error = 'Balance: ' . $vendor->total_balance . ' D_Limit:' . $dailyAvailable . ' M_limit:' . $monthlyAvailable;

                if ($vendor->total_balance <= $amount) {
                    p2cBDConfigV::where('id', $vendor->id)
                        ->update(['error' => $error]);
                        //'mode' => 'OFF', 
                        DB::table('accountList')->where('accountID', $vendor->accountID)->update(['is_priority' => 'N']);
                } else {
                    p2cBDConfigV::where('id', $vendor->id)
                        ->update(['hold' => 'Y', 'error' => $error]);
                }
            }
        }
    }

    if ($remainingAmount > 0) {
        $selectedVendor = self::distributeRemainingAmount($shuffledVendors, $remainingAmount, 'P2C');
    }

    return $selectedVendor;
}


    public static function p2cdistributeRequestAmongAvailableVendors_old($vendors, $amount)
    {
        // Calculate the total available balance of all vendors
        $shuffledVendors = $vendors->shuffle();
        $remainingAmount = $amount;
        $selectedVendor = null;

        // Iterate through vendors with available balances
        foreach ($shuffledVendors as $vendor) {
            $monthly = ($vendor->monthly_limit - $vendor->vendor_limit['monthly']);
            $daily = ($vendor->daily_limit - $vendor->vendor_limit['daily']);

            if ($vendor->total_balance >= $amount && $monthly >= $amount && $daily >= $amount) {
                $selectedVendor = $vendor;
                $remainingAmount -= $amount;
                $balance = $vendor->total_balance - $amount;
                
                $daily_limit = ($vendor->vendor_limit['daily']  + $amount);
                $monthly_limit = ($vendor->vendor_limit['monthly'] + $amount);
                
               self::updateVendorBalance($vendor->accountID, $balance);
                
               self::updateVendorLimit($vendor->uid, $daily_limit,$monthly_limit);
                // If the remaining amount is zero, break the loop
                if ($remainingAmount <= 0) {
                    break;
                }
            }else{
            if($vendor->wlimit !== 'N'){
        $error = 'Balance: '.$vendor->total_balance.'D_Limit:'.$daily.'M_limit:'.$monthly;  
        if($vendor->total_balance <= $amount){
           $affect = DB::table('p2cBDConfigV')->where('id', $vendor->id)->update(['mode' => 'OFF','error' => $error]);  
        }else{
         $affect = DB::table('p2cBDConfigV')->where('id', $vendor->id)->update(['hold' => 'Y','error' => $error]);   
        }
            }
            
            }
        }

        // If there is still a remaining amount, distribute it to another vendor
        if ($remainingAmount > 0) {
            $selectedVendor = self::distributeRemainingAmount($shuffledVendors, $remainingAmount, 'P2C');
        }

        return $selectedVendor;
    }

    public static function distributeRemainingAmount($vendors, $remainingAmount, $mode)
    {
        // Iterate through vendors to distribute the remaining amount
        $shuffledVendors = $vendors->shuffle();
        $selectedVendor = null;

        foreach ($shuffledVendors as $vendor) {
            if ($vendor->total_balance >= $remainingAmount) {
                $selectedVendor = $vendor;
                if($mode=='PAYOUT'){
                 $balance = $vendor->total_balance + $remainingAmount;  
                }else{
                 $balance = $vendor->total_balance - $remainingAmount;   
                }
            
           
                break; // Break the loop after distributing to one vendor
            }
        }

        // Handle the case where there are no vendors with sufficient balance for the remaining amount
        // You might want to throw an exception or log a message here

        return $selectedVendor;
    }

static function updateVendorLimit($uid, $daily,$monthly){

p2cBDConfigV::where('uid', $uid)
            ->update(['daily_used' => $daily, 'monthly_used' => $monthly]);
}

static function updateVendorBalance($accountID, $amount){
DB::table('ladgerVBL')
            ->where('accountID',$accountID)
            ->update(['balance' => $amount]);
}
}