<?php

//get the payment type - R006
function GetPaymentTypes($Param)
{
  global $dbo;
  $PayIDCond = (isset($Param['PayID']) && (int)$Param['PayID'] > 0) ? "ID=" . $Param['PayID'] : "1=1";
  //return $Param['PayID'];
  $paydet = $dbo->Select("item_tb", "ID as PayID, ItemName as PayName, ItemDescr as PayDescr", $PayIDCond);
  if (!is_array($paydet)) {
    Error(4);
  } else {
    return $dbo->FetchAll($paydet[0], MYSQLI_ASSOC);
  }
}


//R028
//get the current payment type for a student
function GetAllPaymentTypes($Param)
{
  session_start();
  Error(4);
  global $dbo;
  //get all payment types for student (except application payments)
  $payIds = $dbo->Select("item_tb", "ID,ItemName", "studType='r'");

  if (is_array($payIds) && $payIds[1] > 0) {

    $itemdetails = [];
    $cnt = 0;
    while ($paydet = $payIds[0]->fetch_assoc()) {
      $PayAmount = $pstatus = [];
      $Param["PayID"] = $paydet['ID'];
      //check if student has paid
      //$payst = $dbo->SelectFirstRow("pay")
      //get payamount
      $PayAmount = GetPaymentAmt($Param);
      if ((float)$PayAmount['Amount'] <= 0) continue; //if amount is zero, meaning it is not a valid payment
      if (!isset($Param['StudentDetails'])) $Param['StudentDetails'] = $PayAmount['StudentDetails'];
      $cnt++;
      //if($cnt == 3){
      $Param['cnt'] = $cnt;
      $pstatus = CheckPayStatus($Param);

      // }

      $itemdetails[] = array_merge($PayAmount, $paydet, $pstatus);
    }

    return $itemdetails;
  } else {
    Error(4);
  }
}

//R031
//get the current payment type for a student
function GetAllPaymentTypes2($Param)
{
  session_start();

  // Confirm if student regno is available
  if (!isset($Param['LoginName']) || trim($Param['LoginName']) == "") Error(8);
  $extrystr = '';
  //level cache
  $levelCache = [];
  //level cache
  $semesterCache = [];
  global $dbo;
  
  //get the student programme details 
  $progdet = GetBasicInfo($Param['LoginName'], "", "a", 1, MYSQLI_ASSOC);
  if (!is_array($progdet)) Error(8," ".$progdet);

  $Param['ProgID'] = $progdet['ProgID'];
  $Param['StudentDetails'] = $progdet;

  //make sure the loginName has the RegNo incase its the JambNo use to login
  $Param['LoginName'] = (is_null($progdet['RegNo']) || trim($progdet['RegNo']) == "") ? $progdet['JambNo'] : $progdet['RegNo'];

  $yearst = (int)$progdet['YearOfStudy']; //the student year of Study
  //get all payment types for student (except application payments)
  $payIds = $dbo->Select("item_tb", "*,ID as PayID, ItemName as PayName, ItemDescr as PayDescr, PayBrkDn as BreakDown", "studType='r'", MYSQLI_ASSOC);

  //payment items exist
  if (is_array($payIds) && $payIds[1] > 0) {

    $itemdetails = [];
    $cnt = 0;
    $highsemarr = HighestSemester();
    $paysetCache = []; //hold payset
    $curentSemCache = NULL;
    //Loop through all payment items and identify the level, semester the student is to pay
    while ($paydet = $payIds[0]->fetch_assoc()) {
      $PayAmount = $pstatus = [];
      $Param["PayID"] = $paydet['ID'];
      $Param["PayDetails"] = $paydet; //to be use in functions, not need to get it again

      //get the payment control details
      if(!isset($paysetCache[$paydet['ControlTable']."_".$paydet['ControlTableID']])){
        $paysetting = $dbo->SelectFirstRow($paydet['ControlTable'], "", "ID=" . $paydet['ControlTableID'] . " LIMIT 1");
        $paysetCache[$paydet['ControlTable']."_".$paydet['ControlTableID']] = $paysetting;
      }else{
        $paysetting = $paysetCache[$paydet['ControlTable']."_".$paydet['ControlTableID']];
      }
      
     
      //if no setting set up for the payment item skip it
      if (!is_array($paysetting)) {
        continue;
      } //if no setting found ignore

       //check if auto semester set if its current semester, get thee current semester details
       $curentSem = NULL;
       if($paysetting['AutoSem'] == 'FALSE'){
         if(is_null($curentSemCache)){
            //get the current semester details
         $curentSem = $dbo->SelectFirstRow("semester_tb","","Current=1",MYSQLI_ASSOC);
         if(!is_array($curentSem))Error(77, ": ".$paydet['ItemName']);
         $curentSemCache = $curentSem;
         }else{
          $curentSem = $curentSemCache;
         }
        
       } 
      //check status
      if ($paysetting['Status'] == "CLOSED") continue;
      if ($paysetting['PartPay'] == "FALSE") $paysetting['PartPayShare'] = "FULL";

      $allowedLevel = [];
      if(isset($paysetting['PayLvl']) && trim($paysetting['PayLvl']) != "-1"){
        //if specific level set
        $allowedLevel = explode("~",$paysetting['PayLvl']);
      }
  //hold progressive payment status
  $IsProgessive = true;
      //if($paysetting['AutoLevel'] == 'TRUE'){
        if(isset($paysetting['Progressive']) && $paysetting['Progressive'] == 'FALSE'){ //if not progressive
          //if current semester already set
          $pCurentSem = [];
          if(!is_null($curentSemCache)){
            $pCurentSem = $curentSemCache;
          }else{
            $pCurentSem = $dbo->SelectFirstRow("semester_tb","","Current=1",MYSQLI_ASSOC);
           if(!is_array($pCurentSem))Error(77, ": ".$paydet['ItemName']);
          }
          //get student current level
          $lvlc = StudLevelSes($Param['LoginName']);
          $sempart = 3;
          $higestPayInner = GetHighestPayment($Param);
          //check if current payment is current level/semester
          if($higestPayInner['LevelID'] == $lvlc && $higestPayInner['SemesterID'] == $pCurentSem['Num']){
            $sempart = $higestPayInner['SemesterPartID'];
            $studschstartsem = $pCurentSem['Num'];
            if($sempart == 3 || $sempart == 2){
              continue;
            }
          }else{
            $studschstartsem = $pCurentSem['Num'] - 1; //take back so that GetNextLSS will take it to the start level
          
            if ($studschstartsem < 1) { //if lower level
              // if($studschstartlvl > 1){
                $lvlc = $lvlc - 1;
              $studschstartsem = $highsemarr['Num']; //use the maximum semester set
             
            }
          }
        
        $higestPay = ["LevelID" => $lvlc, "SemesterID" => $studschstartsem, "SemesterNum" => $studschstartsem, "SemesterPartID" => $sempart];
        // Error(77, ": ".json_encode($higestPay));
        $IsProgessive = false;
        }else{
          //get highest payment
          $higestPay = GetHighestPayment($Param);
        }
      
      $higestPay['HighestSemesterNumber'] = $highsemarr['Num']; //the highest semster num in the school

      //merge the control details for details data for GetNextLSS
      $higestPay = array_merge($higestPay, $paysetting);

      //if no payment found, use the school start lvl and sem of the student to determine his/her last payment
      if (isset($higestPay['Error'])) { //no payment found

        list($studschstartlvl, $studschstartsem) = GetStudentLevelSemesterWhenSchoolStart($Param['LoginName']);
        $studschstartsem = $studschstartsem - 1; //take back so that GetNextLSS will take it to the start level
        if ($studschstartsem < 1) { //if lower level
          // if($studschstartlvl > 1){
          $studschstartlvl = $studschstartlvl - 1;
          $studschstartsem = $higestPay['HighestSemesterNumber']; //use the maximum semester set
          // }else{

          // }
        }
        $startpay = ["LevelID" => $studschstartlvl, "SemesterID" => $studschstartsem, "SemesterNum" => $studschstartsem, "SemesterPartID" => 3];
        $higestPay = array_merge($higestPay, $startpay);
        //Error(8,": ".json_encode($startpay));
        //get the next LSS
        $NLSS = GetNextLSS($higestPay);

        //check for the level check mode
        if($paysetting['AutoLevel'] == 'FALSE' && $IsProgessive){
          //get the calculated level
          $lvlc = StudLevelSes($Param['LoginName']);
          if($lvlc != $NLSS[0]['LevelID'])continue;
        }

      } else { //if last payment found

        //get the next LSS
        $NLSS = GetNextLSS($higestPay);
        //check for the level check mode
        if($paysetting['AutoLevel'] == 'FALSE' && $IsProgessive){
          //get the calculated level
          $lvlc = StudLevelSes($Param['LoginName']);
          if($lvlc != $NLSS[0]['LevelID'])continue;
        }
        //Include the last payment in the front of the array, to int the student of his/her last payment
        //array_unshift($NLSS, ["LevelID" => $higestPay['LevelID'], "SemesterID" => $higestPay['SemesterID'], "SemesterPartID" => $higestPay['SemesterPartID'], "SemesterNum" => $higestPay['SemesterNum']]);
      }
   // }else{

    //}



      //if($paydet['ID'] == 7)Error(8,json_encode($NLSS));

      //SemesterID represent the payment policy can be higher than the school highest semester (Full Session Payment)
      //Include the last payment in the front of the array, to int the student of his/her last payment
      /*  if(!isset($higestPay['Error'])){
             array_unshift($NLSS,["LevelID"=>$higestPay['LevelID'],"SemesterID"=>$higestPay['SemesterID'],"SemesterPartID"=>$higestPay['SemesterPartID'],"SemesterNum"=>$higestPay['SemesterNum']]);
          } */



      /* if(!isset($Param['PayID']) || (int)$Param['PayID'] == 0)Error(11);
     if(!isset($Param['LevelID']) || (int)$Param['LevelID'] == 0)$Param['LevelID']=1;
     if(!isset($Param['SemesterID']) || (int)$Param['SemesterID'] == 0)$Param['SemesterID']=1;
     if(!isset($Param['SemesterPartID']) || (int)$Param['SemesterPartID'] == 0)$Param['SemesterPartID']=3;
     if(!isset($Param['PayDate']) || trim($Param['PayDate']) == "")$Param['PayDate']=NULL; */

      //check if student has paid
      //$payst = $dbo->SelectFirstRow("pay")
      foreach ($NLSS as $LSS) {
        $Param['LevelID'] = $LSS['LevelID'];
        $Param['SemesterID'] = $LSS['SemesterID'];
        $Param['SemesterPartID'] = $LSS['SemesterPartID'];
        $Param['SemesterNum'] = $LSS['SemesterNum'];
        if($LSS['SemesterID'] != $highsemarr['Num'] + 1){
          if(!is_null($curentSem) && $LSS['SemesterID'] != $curentSem['Num']) continue;
        }else{ //if full session
          if(!is_null($curentSem) && $curentSem['Num'] != 1)  continue;
        }
        
        //get level det

        //get payamount
        $PayAmount = GetPaymentAmt($Param);
        //Error(4," - ".$paydet['ID']." Amt-".$PayAmount['Amount']);
        if ((float)$PayAmount['Amount'] <= 0) continue; //if amount is zero, meaning it is not a valid payment
        //help GetPaymentAmt to not try get student details again so far it has gotten it once
        if (!isset($Param['StudentDetails'])) $Param['StudentDetails'] = $PayAmount['StudentDetails'];
        $studet = $PayAmount['StudentDetails']; //$yearst
        if ((int)$Param['LevelID'] > $yearst) { //Extra Year
          //get the extrayear string
          if ($extrystr == '') $extrystr = ExtraLevelString();
          //get the extrayear elapse
          $elapsyear = (int)$Param['LevelID'] - $yearst;
          $leveldet = ["LevelName" => $extrystr . " " . $elapsyear, "Level" => $Param['LevelID']];
        } else { //if valid level
          if (isset($studet['StudyID'])) {
            //check if the level is ni cache already
            if (isset($levelCache[$Param['LevelID']])) {
              $leveldet = $levelCache[$Param['LevelID']];
            } else {
              //get level details
              //get the student current Level details
              $leveldet = $dbo->SelectFirstRow("schoollevel_tb", "*, ID as LID, IF(Descr='',Name,Descr) as LevelName", "Level={$Param['LevelID']} AND StudyID=" . $studet['StudyID'], MYSQLI_ASSOC);
              $levelCache[$Param['LevelID']] = $leveldet;
            }

            //if the level doeas not exist

          } else {
            $leveldet = ["LevelName" => $Param['LevelID'], "Level" => $Param['LevelID']];
          }
        }

        //check if level is allowed to make payment from settings
        if(count($allowedLevel) > 0 && !in_array("".$leveldet['Level'],$allowedLevel))continue;


        if ($Param['SemesterID'] > $highsemarr['Num']) {
          $semdet = ["SemName" => "Full Session", "SemID" => $highsemarr['Num'] + 1];
        } else {
          if (isset($semesterCache[$Param['SemesterID']])) {
            $semdet =  $semesterCache[$Param['SemesterID']];
          } else {
            //get the student semester det
            $semdet = $dbo->SelectFirstRow("semester_tb", "*, IF(Num=0,ID,Num) as SemID, Descr as SemName", "(Num > 0 && Num={$Param['SemesterID']}) || ID={$Param['SemesterID']} ORDER BY Num DESC", MYSQLI_ASSOC);
            $semesterCache[$Param['SemesterID']] = $semdet;
          }
        }
        //if($Param["PayID"] == 7)Error(8, json_encode($semdet));

        if ($Param['SemesterPartID'] == 1) {
          $semdet["SemPartName"] = "PART";
        } else if ($Param['SemesterPartID'] == 2) {
          $semdet["SemPartName"] = "BALANCE";
        } else {
          $semdet["SemPartName"] = "FULL";
        }
        $semdet["SemPartID"] = $Param['SemesterPartID'];

        //if(!is_array($semdet))Error(31);
        $cnt++;
        //if($cnt == 3){
        $Param['cnt'] = $cnt;
        //disable deep verification
        $Param['Deep'] = false;
        $pstatus = CheckPayStatus($Param);

        // }
        if (trim($studet['RegNo']) == "") $studet['RegNo'] = $studet['JambNo'];
        $itemdetails[] = array_merge($PayAmount, $paydet, $pstatus, $leveldet, $semdet, ["RegNo" => $studet['RegNo']]);
      }
    }

    return $itemdetails;
  } else {
    Error(4);
  }
}

//get the student Highest Payment
//R032
function GetHighestPayment($Param)
{
  //Level Based - will still work on Ses and Manual Based
  session_start();
  global $dbo;
  if (!isset($Param['LoginName']) || trim($Param['LoginName']) == "") {
    //Error(5); 
    if (isset($_SESSION['LoginName']) && trim($_SESSION['LoginName']) != "") {
      $Param['LoginName'] = $_SESSION['LoginName'];
    } else {
      // Error(5);
    }
  }

  if (isset($Param['LoginName']) && trim($Param['LoginName']) != "") {
    //   $progID = GetStudentProgIDForPay($Param['LoginName']);
    $progID = $Param['ProgID'];
    //get the student higest Payment Record
    $highpay = $dbo->SelectFirstRow("payhistory_tb", "*, Lvl as LevelID, Sem as SemesterID, SemPart as SemesterPartID, IF(SchSem=0,Sem,SchSem) as SemesterNum", "RegNo='" . $dbo->SqlSafe($Param['LoginName']) . "' AND PayID=" . $Param["PayID"] . " AND ProgID=$progID ORDER BY Lvl DESC, Sem DESC, SemPart DESC LIMIT 1", MYSQLI_ASSOC);
    if (is_array($highpay)) {
      return $highpay;
    } else {
      return ["Error" => true];
    }
  }
}

//initialize payment - R008
function InitalizePayment($Param)
{
  //Error("CE",$Param['PayRef']);
  //Error(11);
  //return 'aaaa';
  session_start();
  global $dbo;
  global $__Root__; //global $Config;
  //Error("CE",json_encode($Param));
  if (!isset($Param['PayRef']) || trim($Param['PayRef']) == "") {
    if (!isset($Param['PayID']) || (int)$Param['PayID'] == 0) Error(11, json_encode($Param));
    if (!isset($Param['LevelID']) || (int)$Param['LevelID'] == 0) $Param['LevelID'] = NULL;
    if (!isset($Param['SemesterID']) || (int)$Param['SemesterID'] == 0) $Param['SemesterID'] = NULL;
    if (!isset($Param['SemesterPartID']) || (int)$Param['SemesterPartID'] == 0) $Param['SemesterPartID'] = 3;
    if (!isset($Param['PayDescr']) || trim($Param['PayDescr']) == '') $Param['PayDescr'] = '';
    $BankPre = isset($Param['BankPre']) && trim($Param['BankPre']) != "" ? $Param['BankPre'] : 'a';
     
    //initialize payment
    $RegNo = "";

    //check if anonymous payee
    if (isset($Param["RegNo"])) {

      $RegNo = $Param["RegNo"];
    } elseif (isset($Param["PayeeEmail"])) {
      //anaonymous
      //check if exist already in payee_tb
      $payeedet = $dbo->SelectFirstRow("payee_tb", "", "PayeeID='" . $Param["PayeeEmail"] . "'");

      if (!is_array($payeedet)) {

        //insert in payee_tb
        $jsotherdet = json_encode($Param);

        $insert = $dbo->Insert("payee_tb", array(
          "PayeeID" => $Param["PayeeEmail"],
          "Name" => $Param['PayeeFullName'],
          "Descr" => $Param['PayeePhone'],
          "OtherDet" => $jsotherdet
        ));
        //return $insert;
      }
      $RegNo = $Param["PayeeEmail"];
    } elseif (isset($_SESSION["LRegNo"])) {
      $RegNo = $Param["LRegNo"];
    } else {
      Error(1);
    }

    //!isset($RegNo) || !isset($Lvl) || !isset($Sem) || !isset($SemPart) || !isset($PayID)
    if (is_null($Param['LevelID']) || is_null($Param['SemesterID'])) { //if no level set
      //get the student current level
      $curlvlsem = GetStudentCurrentLevelSemester(["LoginName" => $RegNo]);
      $Param['SemesterID'] = $curlvlsem['SemID'];
      $Param['LevelID'] = $curlvlsem['LevelID'];
    }
    //get the student bank prefix

    //run the initialization script
    $data = ["RegNo" => $RegNo, "Lvl" => $Param['LevelID'], "Sem" => $Param['SemesterID'], "SemPart" => $Param['SemesterPartID'], "PayID" => $Param['PayID'], "SubDir" => urlencode($dbo->Config['SubDir']), "BankPre" => $BankPre, "PayDescr"=>$Param['PayDescr']];
    if (isset($Param['Amt'])) $data["Amt"] = $Param['Amt'];

    
    //include api.php
    require __DIR__."/../../epapi/api.php";
    $epapi = new epapi($dbo->Config);
    
    $int = $epapi->Post(__DIR__. "/../../general/Payment/init.php", $data);
    //print_r($int);
    //exit;
    //Error("CE",$int['Error']);
    //Error(12," : No Valid Ref");
    //return $int;
    //check if error occur
    if (isset($int['Error'])) {

      if (trim($int['Error']) == "") $int['Error'] = "UNKNOWN ERROR";
      // Error(12,'jjj');
      Error("CE", $int['Error']);
    }

    if (!isset($int['Ref'])) Error(12, " : No Valid Ref");
  } else { //if pay ref already generated
    //Error("CE",$Param['PayRef']);
    //get the details
    $int = $dbo->SelectFirstRow("order_tb", "TransNum,Amt", "TransNum='" . $dbo->SqlSafe($Param['PayRef']) . "'");
    if (!is_array($int)) Error(4, ", Invalid Payment Reference");
    $int['Ref'] = $int['TransNum'];
  }




  $paytypeid = 1; //bank
  //bank print url
  if (isset($Param['PayOptionCard']) && $Param['PayOptionCard'] == 1) {
    $rd = $dbo->Config['Core'] . "general/Payment/post.php?Ref=" . $int['Ref'] . "&SubDir=" . urlencode($dbo->Config['SubDir']) . "&BankPre=" . $BankPre;
    $paytypeid = 2; //card
    //Wallet will still come in - 3
  } else {
    $rd = $dbo->Config['Core'] . "general/Slip.php?folder=Payment&ItemNo=" . $int['Ref'] . "&paper=A4&orientation=P&MT=4&MB=30&SubDir=" . urlencode($dbo->Config['SubDir']) . "&BankPre=" . $BankPre;
  }
  //Error("CE",json_encode(["PayRef"=>$int['Ref'],"Amount"=>$int['Amt'],"Redirect"=>$rd,"PayOption"=>$paytypeid]));
  return ["PayRef" => $int['Ref'], "Amount" => $int['Amt'], "Redirect" => $rd, "PayOption" => $paytypeid];
}

//Get the next payment
function GetNextLSS($Param)
{

  $Lvl = isset($Param['LevelID']) ? (int)$Param['LevelID'] : 1;
  $Sem = isset($Param['SemesterID']) ? (int)$Param['SemesterID'] : 0; //0 represent unset
  $SemNum = isset($Param['SemesterNum']) ? (int)$Param['SemesterNum'] : 1; //1 represent unset - First Semester
  $SemPart = isset($Param['SemesterPartID']) ? (int)$Param['SemesterPartID'] : 0;
  $highsemnum  = isset($Param['HighestSemesterNumber']) ? (int)$Param['HighestSemesterNumber'] : 0;
  if ($highsemnum == 0) {
    $hs = HighestSemester();
    $highsemnum = $hs['Num'];
  }
  $PartPay = isset($Param['PartPay']) ? $Param['PartPay'] : "FALSE";
  $Part = isset($Param['PartPayShare']) && $PartPay !== "FALSE" ? $Param['PartPayShare'] : "FULL"; //GET the school part payment share
  //GET the school part payment share

  //*************************************************************************** */
  //Note: This script handles payment on semester bases only, i.e full session payment not process (A new field is required in both order_tb and payhistory_tb to hold the Real Semster - 1 or 2, while the pay Sem - 1 or 2 or 3:payed all session)
  /****************************************************************************** */

  /****************************************************************************** */
  //determine if payment will allow full only, both, part only
  /****************************************************************************** */


  //$studLSS = GetStudentLevelSemester([]);
  $NLSS = CalculateNextLSS($Lvl, $Sem, $SemNum, $SemPart, $Part, $highsemnum, $PartPay);

  //get level 
  $NLvl = $NLSS[0]["LevelID"];
  if ($Param['PartPayRestrict'] != "-1") {
    $partpresarr = explode("~", $Param['PartPayRestrict']);
    if (in_array($NLvl . "", $partpresarr)) { //the derived level is restricted to be FULL Payment
      $NLSS = CalculateNextLSS($Lvl, $Sem, $SemNum, $SemPart, "FULL", $highsemnum);
    }
  }

  return $NLSS;
}

//Internal
function CalculateNextLSS($Lvl, $Sem, $SemNum, $SemPart, $Part, $highsemnum, $PartPay = "")
{
  $NLSS = [];
  //$FullRestrict = false;
  if ($Part == "QUATER") {
    if ($Sem == 0) $Sem = 1;
    //if($SemPart == 0)$Sem=1;
    //increament sempart
    $SemPart++;
    if ($SemPart > 2) {
      $SemPart = 1;
      $Sem++;
      if ($Sem > $highsemnum) {
        $Sem = 1;
        $SemNum = 1;
        $Lvl++;
      }
    }
    $NLSS[] = ["LevelID" => $Lvl, "SemesterID" => $Sem, "SemesterPartID" => $SemPart, "SemesterNum" => $SemNum];
    //if SemPart is 1 meanin new sem, include option of paying full
    if ($SemPart == 1) {
      $NLSS[] = ["LevelID" => $Lvl, "SemesterID" => $Sem, "SemesterPartID" => 3, "SemesterNum" => $SemNum];
    }
    if ($Sem == 1 && $PartPay != "STRICT") {
      $NLSS[] = ["LevelID" => $Lvl, "SemesterID" => ($highsemnum + 1), "SemesterPartID" => 3, "SemesterNum" => $SemNum];
    }
    return $NLSS;
  } elseif ($Part == "HALF") {
    //if($Sem == 0)$Sem=1;
    //check if last payment is QUATER
    if ($SemPart == 1) {
      return CalculateNextLSS($Lvl, $Sem, $SemNum, $SemPart, "QUATER", $highsemnum, $PartPay);
    }
    $SemPart = 3;
    $Sem++;
    if ($Sem > $highsemnum) {
      $Sem = 1;
      $SemNum = 1;
      $Lvl++;
    }
    $NLSS[] = ["LevelID" => $Lvl, "SemesterID" => $Sem, "SemesterPartID" => $SemPart, "SemesterNum" => $SemNum];
    if ($Sem == 1 && $PartPay != "STRICT") {
      $NLSS[] = ["LevelID" => $Lvl, "SemesterID" => ($highsemnum + 1), "SemesterPartID" => 3, "SemesterNum" => $SemNum];
    }
    return $NLSS;
  } else {

    if ($Sem == 1) {
      return CalculateNextLSS($Lvl, $Sem, $SemNum, $SemPart, "HALF", $highsemnum, $PartPay);
    }
    $SemPart = 3;
    $Sem = $highsemnum + 1;
    $SemNum = 1; //you can only make full payment once in a session and such payment will be expected to be paid in the first semester
    // if($SemNum > )
    $Lvl++;
    $NLSS[] = ["LevelID" => $Lvl, "SemesterID" => $Sem, "SemesterPartID" => $SemPart, "SemesterNum" => $SemNum, "kkk" => $highsemnum];
    return $NLSS;
  }
}


//update student payment info
function PatchStudentInfo($orderDet, $tb = "order_tb")
{
  global $dbo;
  $payidf = $tb == "order_tb" ? "ItemID" : "PayID";
  $studpatch = StudPatchDet($orderDet["RegNo"], $orderDet[$payidf], $orderDet["Lvl"]);
  if (trim($studpatch) != "") {
    $OtherDet = json_decode($studpatch, true);
    if (is_null($OtherDet)) return false;
    //update Info in order_tb
    $uporder = $dbo->Update($tb, ["Info" => $studpatch], "ID=" . $orderDet["ID"]);
    if (!is_array($uporder)) return $uporder;
    return $OtherDet;
  } else {
    //  Error(59);
    return "No Student Details Patch (SDP) found for the Payment Record";
  }
}



//verify payment - R009
function VerifyPayment($Param)
{
  session_start();

  Underscored($Param);
  MapData($Param);
  if (isset($Param["UpdateFromWallet"]) && (int)$Param["UpdateFromWallet"] == 1) {
    $waldebit = PerformWalletTrans($Param);
    if ($waldebit["Status"] == 0) Error(64); //error updating payment via wallet
  }

  global $dbo;
  global $__Root__;
  if (!isset($Param['PayRef']) || trim($Param['PayRef']) == "") Error(11, "jkk");
  //print data
  $ardata = "{Src:'{$__Root__}general/Slip.php?ItemNo=" . urlencode($Param['PayRef']) . "&folder=Payment&SubDir=" . urlencode($dbo->Config['SubDir']) . "',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:4}";


  //get the order details
  $orderDet = $dbo->SelectFirstRow("order_tb o LEFT JOIN payhistory_tb p ON o.TransNum = p.TransID", "o.*,COALESCE(p.Bank,o.Channel) as Bank", "o.TransNum='" . $dbo->SqlSafe($Param['PayRef']) . "'");
  if (!is_array($orderDet)) Error(4, ", Invalid Payment Reference");
  $RegNo = $orderDet['RegNo'];
  if (isset($Param['RegNo']) && strtolower($Param['RegNo']) != strtolower($RegNo)) Error(27);
  $PayID = $orderDet['ItemID'];
  if ($Param['PayID'] != $PayID) Error(14, "In-Param=> " . $Param['PayID'] . " , In-Order=> $PayID");
  $paydet = HasPaidRef($Param['PayRef']);
  //return ["Status"=>"Paid"];
  if ($paydet[0] != 1) { //payment not made
    if (isset($Param['VerifyScope']) && $Param['VerifyScope'] == "Student") {
      //get the student details
      //get the level
      $OtherDet = json_decode($orderDet["Info"], true);
      if (is_null($OtherDet)) {
        $OtherDet = PatchStudentInfo($orderDet, "order_tb");
        if (!is_array($OtherDet)) Error(47, "");
      }
      $StudyID = $OtherDet['StudyID'];
      $LevelID = $orderDet["Lvl"];
      $SemID = $orderDet["Sem"];
      $LevelName = LevelName($LevelID, $StudyID);
      $SemName = SemesterDescription($SemID);
      if ($SemName == "UNKNOWN") $SemName = "FULL";
      $Channel = $orderDet['Bank'];
      return ["Status" => "Payment Failed", "PayRef" => $Param['PayRef'], "RegNo" => $RegNo, "PayID" => $PayID, "Prog" => $OtherDet['ProgName'], "RegLevel" => 6, "ImageErr" => "notpaid.png", "LevelName" => $LevelName, "SemesterName" => $SemName, "FAmt" => number_format($orderDet["Amt"], 2), "ItemName" => $orderDet["ItemName"], "PrintData" => $ardata, "AutoReg" => [], "Channel" => $Channel, "StatusCode" => 0];
      /*} else{
             Error(47," : ".$paydet[5]);
           } */
    } else {
      Error(13, " : " . $paydet[5]);
    }
  } else {
    //put details in session for further use
    //$_SESSION['LRegNo'] = $RegNo;
    //$_SESSION['LoginName'] = $RegNo;
    $_SESSION['LPayID'] = $PayID;
    $_SESSION['LPayRef'] = $Param['PayRef'];

    if (!isset($Param['NextPageNum'])) $Param['NextPageNum'] = 0;

    if (isset($Param['VerifyScope']) && $Param['VerifyScope'] == "Student") {
      $OtherDet = json_decode($orderDet["Info"], true);
      if (is_null($OtherDet)) {
        //fix the result info as required in info field of order_tb
        $OtherDet = PatchStudentInfo($orderDet, "order_tb");
        if (!is_array($OtherDet)) Error(59, ": " . $OtherDet);
      }
      $StudyID = $OtherDet['StudyID'];
      $LevelID = $orderDet["Lvl"];
      $SemID = $orderDet["Sem"];
      $LevelName = LevelName($LevelID, $StudyID);
      $SemName = SemesterDescription($SemID);
      if ($SemName == "UNKNOWN") $SemName = "FULL";
      $Channel = $orderDet['Bank'];
      return ["Status" => "Payment Successfull", "PayRef" => $Param['PayRef'], "RegNo" => $RegNo, "PayID" => $PayID, "Prog" => $OtherDet['ProgName'], "RegLevel" => 6, "ImageErr" => "paid.png", "LevelName" => $LevelName, "SemesterName" => $SemName, "FAmt" => number_format($orderDet["Amt"], 2), "ItemName" => $orderDet["ItemName"], "PrintData" => $ardata, "AutoReg" => [], "Channel" => $Channel, "StatusCode" => 1];
    } else {
      //To Tempoarily make the work uploadable
      $candet = GetCandidate(["RegNo" => $RegNo]);
      //set the payment ref and user regno in session
      return ["Status" => "Paid", "PayRef" => $_SESSION['LPayRef'], "RegNo" => $RegNo, "PayID" => $PayID, "Prog" => $candet["ProgrammeName"], "RegLevel" => (int)$candet["RegLevel"], "NextPageNum" => $Param['NextPageNum'], "StatusCode" => 1];
    }
  }
}

//check payment status
function CheckPayStatus($Param)
{
  session_start();
  global $dbo;
  if (!isset($Param['PayID']) || (int)$Param['PayID'] == 0) Error(11);
  if (!isset($Param['LevelID']) || (int)$Param['LevelID'] == 0) $Param['LevelID'] = 1;
  if (!isset($Param['SemesterID']) || (int)$Param['SemesterID'] == 0) $Param['SemesterID'] = 1;
  if (!isset($Param['SemesterPartID']) || (int)$Param['SemesterPartID'] == 0) $Param['SemesterPartID'] = 3;
  if (!isset($Param['PayDate']) || trim($Param['PayDate']) == "") $Param['PayDate'] = NULL;
  if (!isset($Param['Deep']) || (is_string($Param['Deep']) && trim($Param['Deep']) == "")) $Param['Deep'] = true;


  $studdet = [];
  if (!isset($Param['LoginName']) || trim($Param['LoginName']) == "") {
    //Error(5); 
    if (isset($_SESSION['LoginName']) && trim($_SESSION['LoginName']) != "") {
      $Param['LoginName'] = $_SESSION['LoginName'];
    } else {
      // Error(5);
    }
  }

  if (isset($Param['LoginName']) && trim($Param['LoginName']) != "") {
    if (!isset($Param['ProgID']) || (int)$Param['ProgID'] == 0) $Param['ProgID'] = GetStudentProgIDForPay($Param['LoginName']);
    $getses = GetSchoolSession();

    //get the student progID
    // $progID = $dbo->SelectFirstRow("studentinfo_tb","ProgID","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' OR JambNo='".$dbo->SqlSafe($Param['LoginName'])."'",MYSQLI_ASSOC);

    //$progID = !is_array($progID)?0:$progID['ProgID'];

    //query payhistory
    $payst = $dbo->SelectFirstRow("payhistory_tb", "TransID,Amt", "RegNo='" . $dbo->SqlSafe($Param['LoginName']) . "' AND Lvl=" . $Param['LevelID'] . " AND ((Sem = " . $Param['SemesterID'] . " AND SemPart >= " . $Param['SemesterPartID'] . ") OR (Sem > " . $Param['SemesterID'] . ")) AND PayID=" . $Param['PayID'] . " AND ProgID=" . $Param['ProgID']);
    //$payst = $dbo->SelectFirstRow("payhistory_tb","TransID","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' AND Lvl=".$Param['LevelID']." AND ((Sem = ".$Param['SemesterID']." AND SemPart >= ".$Param['SemesterPartID'].") OR (Sem > ".$Param['SemesterID'].")) AND Ses = ".$getses['SesID'] . " AND PayID=".$Param['PayID']);

    if (is_array($payst)) { //paid

      return ["Status" => "Paid", "PayRef" => $payst['TransID'], "Amount" => $payst['Amt'], "FAmount" => number_format($payst['Amt'], 2)];
    } else {

      //check if exist in order
      // $ordst = $dbo->SelectFirstRow("order_tb","TransNum","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' AND Lvl=".$Param['LevelID']." AND (Sem = ".$Param['SemesterID']." AND SemPart = ".$Param['SemesterPartID'].") AND Ses = ".$getses['SesID'] . " AND ItemID=".$Param['PayID']);
      if ($Param['Deep']) { //if deep verification - check gatway
        // Error(2,"Is Deep ".$Param['Deep'] );
        $ordst = $dbo->SelectFirstRow("order_tb", "TransNum", "RegNo='" . $dbo->SqlSafe($Param['LoginName']) . "' AND Lvl=" . $Param['LevelID'] . " AND (Sem = " . $Param['SemesterID'] . " AND SemPart = " . $Param['SemesterPartID'] . ")  AND ItemID=" . $Param['PayID'] . " AND ProgID=" . $Param['ProgID']);


        if (!is_array($ordst)) return ["Status" => "NotPaid", "PayRef" => ""];


        $Ref = $ordst['TransNum'];
        // if($Param['cnt'] == 3){
        //  $paydet = HasPaidRef2($Ref);
        // Error("CE",json_encode($paydet)); 
        // }else{
        $paydet = HasPaidRef($Ref);
        // }


        //return ["Status"=>"Paid"];
        if ($paydet[0] != 1) { //payment not made
          //Error(4,json_encode($paydet));
          return ["Status" => "NotPaid", "PayRef" => $Ref];
        } else {

          return ["Status" => "Paid", "PayRef" => $Ref];
        }
      } else {
        return ["Status" => "NotPaid", "PayRef" => ""];
      }
    }
  }
}


//R038
function LoadPaymentHistory($Param)
{
  global $dbo;
  global $__Root__;
  //session_start();
  HasLogin($Param);

  $studDet = $dbo->SelectFirstRow("studentinfo_tb", "", "RegNo='{$Param['LoginName']}' OR JambNo='{$Param['LoginName']}' LIMIT 1");
  if (!is_array($studDet)) Error(8);
  $Param['LoginName'] = (is_null($studDet['RegNo']) || trim($studDet['RegNo']) == "") ? $studDet['JambNo'] : $studDet['RegNo'];
  //get all student payment history
  $payhist = $dbo->Select("payhistory_tb p, item_tb i", "p.*, i.ItemName", "p.RegNo='{$Param['LoginName']}' AND p.PayID = i.ID and p.PayScope != 'w' ORDER BY PayDate DESC, Lvl DESC, ID DESC, Sem DESC, SemPart DESC", MYSQLI_ASSOC);
  if (!is_array($payhist)) Error(4);
  if ($payhist[1] < 1) Error(39);
  //payment history exist

  //loop and form the history array
  $HistArr = [];
  //for speed and optimization do an internal cache
  $LevelName = [];
  $SemesterName = [];
  $SessionName = [];
  $SemesterPartName = [1 => "PART", 2 => "BALANCE", 3 => "FULL"];
  while ($paydeti = $payhist[0]->fetch_assoc()) {
    //get the course RegDetails
    if (!isset($LevelName[$paydeti['Lvl']])) { //if not in cache
      //get it
      $LevelName[$paydeti['Lvl']] = GetStudentLevelName($paydeti['Lvl'], $studDet['StudyID'],$studDet['ProgID']);
    }
    if (!isset($SemesterName[$paydeti['Sem']])) { //if not in cache
      //get it
      $SemesterName[$paydeti['Sem']] = GetStudentSemesterName($paydeti['Sem']);
    }
    if (!isset($SessionName[$paydeti['SesID']])) { //if not in cache
      //get it
      $SessionName[$paydeti['Ses']] = GetSessionName($paydeti['Ses']);
    }

    /* {"Name":"Yomi Aniedi Ekanem","ProgID":"16","ProgName":"Agricultural Engineering ","DeptID":"16","DeptName":"Agricultural Engineering","FacID":"2","FacName":"Vocational & Technical Education","StartSes":"10","ModeOfEntry":"1","StudyID":"5","RegID":"1","PayName":"AKSCOE ACCEPTANCE FEE"} */
    //get the school settings
    $sch = GetSchool("SchStrucContr");
    $schstuc = json_decode($sch['SchStrucContr'], true);
    $dispst = true;
    $disprog = true;
    /* {"StudyID":{"SilentMode":false,"Name":"School"},"FacID":{"SilentMode":false,"Name":"Faculty"},"DeptID":{"SilentMode":false,"Name":"Department"},"ProgID":{"SilentMode":false,"Name":"Programme"},"SchID":{"Name":"School Group"},"FacGrpID":{"Name":"Faculty Group"},"ClassID":{"Name":"Class Group","SilentMode":false}} */
    if (is_array($schstuc)) { // if it is valid
      $dispst = !$schstuc['StudyID']['SilentMode'];
      $disprog = !$schstuc['ProgID']['SilentMode'];
    }

    $payinfo = json_decode($paydeti['Info'], true);
    $studschooldet = [];
    if (is_array($payinfo) && $dispst) {
      if (isset($payinfo['StudyName'])) {
        $studschooldet[] = $payinfo['StudyName'];
      }

      if (isset($payinfo['ProgName']) && $disprog) {
        $studschooldet[] =  $payinfo['ProgName'];
      }
    }
    $studschdetstr = implode(" / ", $studschooldet);

    $PayDate = date('d, M Y', strtotime($paydeti['PayDate']));;
    //$paydis = $paydate->format();
    $HistArr[] = ["SessionName" => $SessionName[$paydeti['Ses']], "LevelName" => $LevelName[$paydeti['Lvl']], "SemesterName" => $SemesterName[$paydeti['Sem']], "SemesterPartName" => $SemesterPartName[$paydeti['SemPart']], "Amt" => number_format($paydeti['Amt'], 2), "PayRef" => $paydeti['TransID'], "ItemName" => $paydeti['ItemName'], "PayID" => $paydeti['PayID'], "PayDate" => $PayDate, "PaySchDet" => $studschdetstr, "Redirect" => $__Root__ . "general/Slip.php?folder=Payment&ItemNo=" . $paydeti['TransID'] . "&paper=A4&orientation=P&MT=4&MB=30&SubDir=" . urlencode($dbo->Config['SubDir'])];
  }
  return $HistArr;
}

//R040
function WalletDetails($Param)
{

  HasLogin($Param);
  global $dbo;
  if(isset($Param['LoginName'])){
    //get the student details
//get the student programme details 
$studdet = GetBasicInfo($Param['LoginName'], "", "a", 1, MYSQLI_ASSOC);
if (!is_array($studdet)) Error(8," ".$studdet);
$studlevSemDet = GetStudLvlSemDetails($Param['LoginName']);

$studLevel = isset($studlevSemDet['Level'])?$studlevSemDet['Level']:1;
$studSem = isset($studlevSemDet['Num'])?$studlevSemDet['Num']:1;
//get all the wallet payment type
$payIds = $dbo->Select("item_tb", "", "studType='w'", MYSQLI_ASSOC);

  //payment items exist
  if (is_array($payIds) && $payIds[1] > 0) {
    //loop through to get wallet payment item best suit the student
    while ($paydet = $payIds[0]->fetch_assoc()) {
      $paybrd = PaymentBreakDown($paydet['PayBrkDn'], $studLevel, $studSem, $studdet, 3);
      if (!is_array($paybrd)) continue;
      if($paybrd[0] > 0){
        $walc = $dbo->SelectFirstRow("walletcontrol_tb");
        if (!is_array($walc)) Error(41);
        $walc['PayID'] = $paydet['ID'];
        $walc = array_merge($walc,$paydet);
        break;
      }
      //return ["Amount" => $paybrd[0], "FAmount" => $paybrd[1], "StudentDetails" => $studdet, "PayDetails" => $paydet];
    }
  }
    //get payamount
   // $PayAmount = GetPaymentAmt($Param);
    //if ((float)$PayAmount['Amount'] <= 0) continue; //if amount is zero, meaning it is not a valid payment
    
  }
  
  if(!isset($walc)){
    $walc = $dbo->SelectFirstRow("walletcontrol_tb w, item_tb i", "", "w.PayID=i.ID LIMIT 1");
    if (!is_array($walc)) Error(41);
  }
  
  
  if (!isset($Param['nopreamt']) || (int)$Param['nopreamt'] == 0) {
    $amts = trim($walc['Amts']);
    $amtdescr = trim($walc['AmtDescr']);
    if ($amts == "") Error(41);
    $amtsobj = json_decode($amts, true);
    $amtDobj = json_decode($amtdescr, true);
    if (is_null($amtsobj)) Error(41);
  }

  //get the control details
  $cntrdet = $dbo->SelectFirstRow($walc['ControlTable'], "", "ID={$walc['ControlTableID']} LIMIT 1");
  if (!is_array($cntrdet)) Error(41);
  //check status
  if ($cntrdet['Status'] == "CLOSED") Error(42);
  $bal = '0.00';
  //get the student last balance
  $lasttrans = $dbo->SelectFirstRow("wallet_tb", "", "RegNo='" . $dbo->SqlSafe($Param['LoginName']) . "' ORDER BY ID DESC LIMIT 1");
  if (is_array($lasttrans)) { //if transaction exist
    $bal = number_format($lasttrans['Balance'], 2);
  }
  $rtn = [];
  if (!isset($Param['nopreamt']) || (int)$Param['nopreamt'] == 0) {
    $Curency = $dbo->SelectFirstRow("currency_tb");
    //check if other exist
    //$order = $dbo->SelectFirstRow("order_tb","","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' ORDER BY ID DESC LIMIT 1");
    foreach ($amtsobj as $k=>$indamt) {
      $rdescr = isset($amtDobj[$k]) && trim($amtDobj[$k]) != ""?$amtDobj[$k]:"";
      $rtn[] = ["FAmount" => number_format($indamt, 2), "Amount" => $indamt, "Descr" => strtoupper($rdescr/* ==""?"Wallet":$rdescr */), "Currency" => $Curency['Abbr'], "Readonly"=>trim($rdescr) != ""?"readonly":"", "Type"=>strtoupper($rdescr ==""?"Wallet":$rdescr)];
      // $rtn[] = ["FAmount" => number_format($indamt, 2), "Amount" => $indamt, "Descr" => $Curency['Abbr'], "Currency" => $Curency['Abbr']];
    }
  }

  //if((int)$walc['DynamicAmt'] == 1)$rtn[] = ["FAmount" => "Custom Amount", "Amount" => "-1", "Descr" => "", "Currency" => $Curency['Abbr']];
  

  $wallmenus = [];

  //if wallet portal menus are also needed
  if (isset($Param['walletportalmenus']) && (int)$Param['walletportalmenus'] == 1) {
    $MenuID = (int)$walc['MenuID'];
    if ($MenuID > 0) {
      $menus = $dbo->Select("new_apply_tb a, new_apply_group_tb ag", "a.ID,a.Name,a.Descr,a.GroupID,a.Logo,a.Color,a.Placeholder,ag.Logo as GroupLogo", "a.GroupID=" . $MenuID . " AND a.Enable=1 AND a.GroupID = ag.ID");
      if (is_array($menus) && $menus[1] > 0) {
        while ($indmenu = $menus[0]->fetch_assoc()) {
          $wallmenus[] = $indmenu;
        }
      }
    }
  }

  return ["DynamicAmt"=>(int)$walc['DynamicAmt'] == 1?[1]:[],"PreAmount" => $rtn, "PayID" => $walc['PayID'], "Balance" => $bal, "RBalance" => $lasttrans['Balance'], "MinBalance" => $walc['MinBalance'], "WalletMenus" => $wallmenus];
}

//PaymentBreakDown (#R055)
function PaymentAnalysis($param)
{
  global $_;
  //Error(59,":".$param['PayRef']);
  //"SemesterID":1,"LevelID":1,"SemesterPartID":3,"PayID":7,"RegNo":"AD917401" "LoginName":"AD917401"
  if (!isset($param['PayRef']) || trim($param['PayRef']) == "") Error(57);
  //get the payment details
  $paydet = $_->SelectFirstRow("order_tb", "TransNum,ID,Paid,BrkDwn,ItemName,Amt", "TransNum='" . $_->SqlSafe($param['PayRef']) . "'", MYSQLI_ASSOC);
  if (!is_array($paydet)) Error(58, " - " . $param['PayRef']);
  //check if Paid
  if ((int)$paydet['Paid'] == 1) Error(59, ":" . $param['PayRef']);
  //get the preakdown
  $BreakDown = $paydet['BrkDwn'];
  $Preakdarr = [];
  if (trim($BreakDown) == "") {
    $Amt = (float)$paydet['Amt'];
    $Preakdarr[] = ["AItemName" => $paydet['ItemName'], "AAmt" => $Amt, "AFAmt" => number_format($Amt, 2), "AItemID" => 0, "ADisabled" => "disabled"];
  } else {
    $BreakDownarr = explode("***", $BreakDown);
    foreach ($BreakDownarr as $indbrdwn) {
      //Tuition Fee~25000~1
      $indbrdwnarr = explode("~", $indbrdwn);
      if (count($indbrdwnarr) < 3) continue;
      //check if item is optional
      //$optional = (isset($indbrdwnarr[3]) && trim($indbrdwnarr[3]) != "1")?"disabled":"";
      $unselect = (isset($indbrdwnarr[4]) && trim($indbrdwnarr[4]) != "1") ? "checked" : "";
      $optional = "";

      //if not optional
      if (isset($indbrdwnarr[3]) && trim($indbrdwnarr[3]) != "1") {
        $optional = "disabled";
      } else {
        $unselect = ""; //uncheck it
      }

      $Preakdarr[] = ["AItemName" => strtoupper($indbrdwnarr[0]), "AAmt" => (float)$indbrdwnarr[1], "AFAmt" => number_format((float)$indbrdwnarr[1], 2), "AItemID" => $indbrdwnarr[2], "ADisabled" => $optional, "AChecked" => $unselect];
    }
  }
  if (count($Preakdarr) < 1) {
    $Amt = (float)$paydet['Amt'];
    $Preakdarr[] = ["AItemName" => $paydet['ItemName'], "AAmt" => $Amt, "AFAmt" => number_format($Amt, 2), "AItemID" => 0, "ADisabled" => "disabled"];
  }
  //Error("CE",json_encode(array_merge($paydet,["Analysis"=>$Preakdarr,"FAmtMain"=>number_format((float)$paydet['Amt'],2)])));
  return array_merge($paydet, ["Analysis" => $Preakdarr, "FAmtMain" => number_format((float)$paydet['Amt'], 2)]);
}

function formReturnPayOption($payOption){
  $optarr = explode("-",$payOption);
  $rst = [
    "CARD"=>[1],
    "BANK"=>[1],
    "WALLET"=>[1]
  ];
  if($payOption != "ALL"){
    foreach($rst as $opt=>$en){
      if(!in_array($opt,$optarr))$rst[$opt] = [];
    }
  }
  return $rst;
}

//UpdateOrderDet R056
function UpdateOrderDet($param)
{

  global $_;
  if (!isset($param['PayRef']) || trim($param['PayRef']) == "") Error(57);
  if (!isset($param['PayItems']) || count($param['PayItems']) < 1) Error(60);
  //get the order details
  $paydet = $_->SelectFirstRow("order_tb o, item_tb i", "o.TransNum,o.ID,o.Paid,o.BrkDwn,o.ItemName,o.Amt,o.ItemID as PayID,i.PayOption", "o.TransNum='" . $_->SqlSafe($param['PayRef']) . "' AND o.ItemID = i.ID", MYSQLI_ASSOC);
  if (!is_array($paydet)) Error(58);

  //payoption display array
  $PayOptionDisplay = formReturnPayOption($paydet['PayOption']);

  //check if Paid
  if ((int)$paydet['Paid'] == 1) Error(59);

  //prepare current breakdown
  $BreakDown = $paydet['BrkDwn'];
  $Preakdarr = [];
  $totAmt = 0;
  if (trim($BreakDown) == "") {
    $Amt = (float)$paydet['Amt'];
    $Preakdarr[0] = [$paydet['ItemName'], $Amt, 0, 0, 0];
    $totAmt = $Amt;
  } else {
    $BreakDownarr = explode("***", $BreakDown);
    foreach ($BreakDownarr as $indbrdwn) {
      //Tuition Fee~25000~1
      $indbrdwnarr = explode("~", $indbrdwn);
      if (count($indbrdwnarr) < 3) continue;
      //check if item is optional
      $Preakdarr[$indbrdwnarr[2]] = $indbrdwnarr;
      $totAmt += (float)$indbrdwnarr[1];
    }
  }
  if (count($Preakdarr) < 1) {
    $Amt = (float)$paydet['Amt'];
    $Preakdarr[0] = [$paydet['ItemName'], $Amt, 0, 0, 0];
    $totAmt = $Amt;
  }


  //get new total and reform the payment items
  /* "PayItems":[{"type":"checkbox","id":"pitemid-1","state":1,"marker":"\u20a6 25,000.00","value":"1"},{"type":"checkbox","id":"pitemid-13","state":1,"marker":"\u20a6 2,500.00","value":"13"},{"type":"checkbox","id":"pitemid-10","state":1,"marker":"\u20a6 3,000.00","value":"10"},{"type":"checkbox","id":"pitemid-15","state":1,"marker":"\u20a6 14,500.00","value":"15"},{"type":"checkbox","id":"pitemid-8","state":0,"marker":"\u20a6 23,000.00","value":"8"}] */
  foreach ($param['PayItems'] as $newbrkdwn) {
    $iid = (int)$newbrkdwn['value'];
    if (!isset($Preakdarr[$iid])) continue;
    $selected = (int)$newbrkdwn['state'];
    if ($selected == 0) {
      $Preakdarr[$iid][4] = 1;
    } else {
      $Preakdarr[$iid][4] = 0;
    }
  }

  $NewBrkDwn = "";
  $NewTotal = 0;
  //form new break down and total
  foreach ($Preakdarr as $indItem) {
    if ((int)$indItem[4] < 1) { //if is selected
      $NewTotal += (float)$indItem[1];
    }
    $NewBrkDwn .= implode("~", $indItem) . "***";
  }

  $NewBrkDwn = rtrim($NewBrkDwn, "***");
  //Error("CE",$NewTotal." - ".json_encode($param['PayItems']));
  //update the new breakdown and amount
  $updorder = $_->Update("order_tb", ["Amt" => $NewTotal, "BrkDwn" => $NewBrkDwn], "TransNum='" . $_->SqlSafe($param['PayRef']) . "'");
  if (!is_array($updorder)) Error(61);

  return array_merge(["PayRef" => $param['PayRef'], "Amt" => $NewTotal, "FAmt" => number_format($NewTotal, 2), "ItemName" => $paydet['ItemName'], "PayID" => $paydet['PayID']],$PayOptionDisplay);

  //Error("CE",$NewBrkDwn." => ".$NewTotal);
}


//R061
function PayWithWallet($param = [])
{
  global $dbo;
  //Error(57);
  if (!isset($param['PayRef'])) Error(57);
  //get the order details
  $int = $dbo->SelectFirstRow("order_tb", "TransNum,Amt,FORMAT(Amt,2) as FAmt,ItemName,ItemID", "TransNum='" . $dbo->SqlSafe($param['PayRef']) . "'", MYSQLI_ASSOC);
  if (!is_array($int)) Error(4, ", Invalid Payment Reference");
  //get wallet balance
  $Walet = WalletDetails($param);
  $amtToPay = (float)$int['Amt'];
  if ($amtToPay <= 0) Error(62);
  $Balance = (float)$Walet['RBalance'];
  $MinBalance = (float)$Walet['MinBalance'];

  //check if insufitient fund
  if ($amtToPay > ($Balance - $MinBalance)) Error(63);
  //$Walet['PayID'] = $int['PayID'];
  return array_merge($int, $Walet, ["PayID" => $int['ItemID']]);
}


//R062
function PerformWalletTrans($Param)
{
  //insert into the payhistory
  global $dbo;
  global $__Root__;
  if (!isset($Param['PayRef']) || trim($Param['PayRef']) == "") Error(11);
  //print data
  //get the order details
  $orderDet = $dbo->SelectFirstRow("order_tb", "", "TransNum='" . $dbo->SqlSafe($Param['PayRef']) . "'");
  if (!is_array($orderDet)) Error(4, ", Invalid Payment Reference");
  //dispay getting preamount
  $Param['nopreamt'] = 1;
  //get the wallet details
  $Walet = WalletDetails($Param);
  $amtToPay = (float)$orderDet['Amt'];
  if ($amtToPay <= 0) Error(62);
  $Balance = (float)$Walet['RBalance'];
  $MinBalance = (float)$Walet['MinBalance'];

  //check if insufitient fund
  if ($amtToPay > ($Balance - $MinBalance)) Error(63);

  //Update Payment details
  $updatepay = MakePaidByRef($Param['PayRef'], $orderDet, ["Bank" => "WALLET", "Branch" => "WALLET"], 1);
  return ["PayRef" => $Param['PayRef'], "Status" => $updatepay[0]];
}

//R063
function OrderDetailsByRef($Param = [])
{
  global $dbo;
  global $__Root__;
  //Error(57);
  if (!isset($Param['PayRef'])) Error(57);
  //get the order details
  $int = $dbo->SelectFirstRow("order_tb", "RegNo,TransNum,Amt,FORMAT(Amt,2) as FAmt,ItemName,ItemID", "TransNum='" . $dbo->SqlSafe($Param['PayRef']) . "' OR ExpiredRef LIKE '%:" . $dbo->SqlSafe($Param['PayRef']) . ":%'", MYSQLI_ASSOC);
  if (!is_array($int)) {
    //check in expired orders
    $int = $dbo->SelectFirstRow("order_ex_tb", "RegNo,TransNum,Amt,FORMAT(Amt,2) as FAmt,ItemName,ItemID", "TransNum='" . $dbo->SqlSafe($Param['PayRef']) . "'", MYSQLI_ASSOC);
    if (!is_array($int)) {
      Error(4, ", Invalid Payment Reference");
    }
  }
  if ($Param['LoginName'] != $int['RegNo']) Error(65);
  $Param['PayID'] = $int['ItemID'];
  $Param['VerifyScope'] = 'Student';
  //$Param['PayRef'] = $int['TransNum'];
  $verpay = VerifyPayment($Param);
  if ($verpay['StatusCode'] == 1) {
    $verpay['NextPageNum'] = 3;
    return $verpay;
  } else {
    return ["PayRef" => $Param['PayRef'], "PayID" => $int['ItemID'], "Amt" => $int['Amt'], "FAmt" => $int['FAmt']];
  }

  //
}

//R071
function GetOrderDetailsByRef($Param = [])
{
  global $dbo;
  global $__Root__;
  
  //Error(57);
  if (!isset($Param['PayRef']) && !isset($Param['OrderID'])) Error(8);
  //get all student unpaid order
  $int = $dbo->SelectFirstRow("order_tb ord, semester_tb sem", "ord.ID,ord.RegNo,ord.TransNum,ord.Amt,FORMAT(ord.Amt,2) as FAmt,ord.ItemName,ord.ItemID,ord.ExpiredRef,ord.ProgID,ord.RegDate,DATE_FORMAT(ord.RegDate, '%D, %b %Y') as PayDate,ord.Info,sem.Descr as SemesterName", isset($Param['PayRef'])?"ord.TransNum='" . $dbo->SqlSafe($Param['PayRef'])."' AND ord.Sem = sem.Num":"ord.ID='" . $dbo->SqlSafe($Param['OrderID'])."' AND ord.SchSem = sem.Num");
  if(!is_array($int))Error(72, $int);
  $payeeDet = json_decode($int['Info'],true);
  $int = array_merge($int,$payeeDet);
  $allTransNumber = [["Ref"=>$int['TransNum'],"Status"=>"checked"]];
  $ExpiredRef = trim($int['ExpiredRef']);
      if($ExpiredRef != ""){
        $exparr = explode("::",trim($ExpiredRef,":"));
        foreach($exparr as $ExpRef){
          $allTransNumber[] = ["Ref"=>$ExpRef,"Status"=>""];
        }
        //$allTransNumber = array_merge($allTransNumber,);
      }
      $int["TransIDs"] = $allTransNumber;
      return $int;
}

//R070
function GetUnPaidOrderByReg($Param=[]){
  global $dbo;
  global $__Root__;
  
  //Error(57);
  if(!isset($Param['PayReg']) && isset($Param['LoginName']) && trim($Param['LoginName']) != "")$Param['PayReg'] = $Param['LoginName'];
  if (!isset($Param['PayReg'])) Error(8);
  //get all student unpaid order
  $int = $dbo->Select("order_tb ord, semester_tb sem", "ord.ID,ord.RegNo,ord.TransNum,ord.Amt,FORMAT(ord.Amt,2) as FAmt,ord.ItemName,ord.ItemID,ord.ExpiredRef,ord.ProgID,ord.RegDate,DATE_FORMAT(ord.RegDate, '%D, %b %Y') as PayDate,ord.Info,sem.Descr as SemesterName", "(ord.RegNo='" . $dbo->SqlSafe($Param['PayReg']) . "' OR ord.TransNum='" . $dbo->SqlSafe($Param['PayReg'])."') AND ord.Paid=0 AND ord.SchSem = sem.Num ORDER BY RegDate DESC");
  if(!is_array($int) || $int[1] < 1)Error(72);
  
  $rtnRec = [];
   $def = ["Name"=>"","ProgID"=>0,"ProgName"=>"","DeptID"=>0,"DeptName"=>"","FacID"=>0,"FacName"=>"","StartSes"=>0,"ModeOfEntry"=>"1","StudyID"=>"4","RegID"=>"1","ClassName"=>"-","LevelName"=>"-","PayName"=>""];
  $Name = "";
  while($indorder = $int[0]->fetch_assoc()){
    // if((int)$indorder['ProgID'] < 1){
      $payeeDet = json_decode($indorder['Info'],true);
      if(trim($Name) == "" && isset($payeeDet['Name']) && trim($payeeDet['Name']) != "")$Name = $payeeDet['Name'];
      //get the total expired transaction
      $TotalExpired = 'N/A';
      $ExpiredRef = trim($indorder['ExpiredRef']);
      if($ExpiredRef != ""){
        $TotalExpired = count(explode("::",$ExpiredRef));
      }
      $rtnRec[] = array_merge($indorder,$def,$payeeDet,["TotalExpired"=>$TotalExpired]);
    // }
  }
return ["Orders"=>$rtnRec, "Name"=>$Name];
}

//R072
function RestoreTransactionID($Param=[]){
  global $dbo;
 
  if (!isset($Param['PayRef']) || !isset($Param['OrderID'])) Error(8);
  $order = $dbo->SelectFirstRow("order_tb","","ID=".$Param['OrderID'],MYSQLI_ASSOC);
  
  if(is_array($order)){
    $info = trim($order['Info']) == ""?[]:json_decode($order['Info'],true);
    $Neworder = array_merge($order,$info,["PayRef"=>$Param['PayRef'],"PayID"=>$order['ItemID']]);
    $PayRef = $order['TransNum'];
    $ExpiredRefs =  trim($order['ExpiredRef']) == ""?[]:explode("::",trim($order['ExpiredRef'],":"));
    //Error(8,$Neworder);
    if($PayRef == $Param['PayRef'] || !in_array($Param['PayRef'],$ExpiredRefs)) return $Neworder;
    
    //if expired remove from expired and add current to xpired
    $order['ExpiredRef'] = str_replace(":".$Param['PayRef'].":","",$order['ExpiredRef']).":".$order['TransNum'].":";
    $order['TransNum'] = $Param['PayRef'];
    //update the order
    $updorder = $dbo->Update('order_tb',$order,"ID=".$order['ID']);
    if(!is_array($updorder))Error(61);
    return array_merge($Neworder,$order);
  }else{
    Error(65);
  }
}