<?php

class Purchaserequestkacab extends MY_Controller
{
    var $db;
    public function index()
    {
        echo "COA API";
        // $cek = $this->db->query("select database() as current_db")->result();
        // print_r($cek);
    }
    public function __construct()
    {
        parent::__construct();
    }

    public function search()
    {
        if (! $this->isLogin) {
            $this->sys_error("Invalid Token");
            exit;
        }
        $prm = $this->sys_input;
        $search = '%' . $prm['search'] . '%';

        $startDate = $prm['startDate'];
        $endDate = $prm['endDate'];
        $status = $prm['status'];
        $page = $prm['page'];
        $flag = $prm['flag'];
        $user = $this->sys_user;
        $regionalID = $user['S_RegionalID'];
        $branchCode = $user['M_BranchCode'];
        $loginType = $user['M_UserLocationFlag'];
        $userID = $user['M_UserID'];
        $approveLevelID = $user['M_UserM_ApproveLevelID'];

        $sqlBranch = '';
        if ($loginType == 'B' || $loginType == 'RB') {
            $sqlBranch = "AND PurchaseRequestM_BranchCode = '{$branchCode}'";
        }
        $sqlStatus = '';
        if ($status != 'All') {
            $sqlStatus = "AND PurchaseRequestStatus = '{$status}'";
        }
        $number_limit = 20;
        $number_offset = 0;
        if ($page > 0) {
            $number_offset = ($prm['page'] - 1) * $number_limit;
        }

        if ($approveLevelID == '1') {
            if ($flag == 'G') {
                $sqlStockRequest = " AND (PurchaseRequestVerifiedBy = 0 OR PurchaseRequestVerifiedBy IS NULL) ";
            }
        } else if ($approveLevelID == '2') {
            if ($flag == 'G') {
                $sqlStockRequest = " AND PurchaseRequestApprovedBy IS NULL";
            }
        }


        $sql = "SELECT m_approve_level.* FROM m_user
                JOIN m_approve_level
                ON M_UserM_ApproveLevelID = M_ApproveLevelID
                WHERE M_UserID = ?;";
        $qry = $this->db->query($sql, [$userID]);
        if (!$qry) {
            $this->sys_error_db("Error cek approval level");
            exit;
        }
        $approvalLevel = $qry->result_array();
        if (count($approvalLevel) == 0) {
            $result = array(
                'total' => 0,
                'records' => []
            );
            $this->sys_ok($result);
            exit;
        }

        $totalStart = $approvalLevel[0]['M_ApproveLevelStartTotal'];
        $totalEnd = $approvalLevel[0]['M_ApproveLevelEndTotal'];

        $sql = "SELECT
                COUNT(PurchaseRequestID) total
                FROM purchase_request
                JOIN s_regional
                ON PurchaseRequestS_RegionalID = S_RegionalID
                AND S_RegionalIsActive = 'Y'
                JOIN item_category 
                ON PurchaseRequestItemCategoryID  = ItemCategoryID
                AND ItemCategoryIsActive = 'Y'
                JOIN m_user b
                ON PurchaseRequestRequestedBy = b.M_UserID
                AND b.M_UserIsActive = 'Y'
                AND S_RegionalIsActive = 'Y'
                LEFT JOIN m_user a
                ON PurchaseRequestApprovedBy = a.M_UserID
                AND a.M_UserIsActive = 'Y'
                LEFT JOIN 
                m_branch
                ON PurchaseRequestM_BranchCode = M_BranchCode
                WHERE PurchaseRequestIsActive = 'Y' AND PurchaseRequestItemCategoryID = 1
                AND (PurchaseRequestNumber LIKE ? OR PurchaseRequestRefNumber LIKE ? OR  PurchaseRequestRequestedBy LIKE ?)
                AND (PurchaseRequestDate BETWEEN ? AND ?) AND PurchaseRequestS_RegionalID = ?
                $sqlStockRequest
                $sqlBranch
                $sqlStatus";
        $qry = $this->db->query($sql, [$search, $search, $search, $startDate, $endDate, $regionalID]);
        if (!$qry) {
            $this->sys_error_db("Error searching");
            exit;
        }
        $total = $qry->row_array()['total'];
        $tot_page = ceil($total / $number_limit);
        $params = [$search, $search, $search, $startDate, $endDate, $regionalID];

        $params[] = $number_limit;
        $params[] = $number_offset;
        $sql = "SELECT
                PurchaseRequestID prID,
                DATE_FORMAT(PurchaseRequestDate, '%d-%m-%Y') prDate,
                PurchaseRequestNumber prNumber,
                PurchaseRequestRefNumber prRefNumber,
                PurchaseRequestNote prNote,
                PurchaseRequestTotal prTotal,
                PurchaseRequestItemCategoryID prItemType,
                ItemCategoryName prItemTypeName,
                PurchaseRequestStatus prStatus,
                IFNULL(PurchaseRequestVerifiedBy, 0) AS PurchaseRequestVerifiedBy,
                DATE_FORMAT(PurchaseRequestApprovedDate, '%d-%m-%Y %H:%i') prApprovedDate,
                a.M_userUserName prApprovedBy,
                b.M_UserID prRequestedByID,
                b.M_userUserName prRequestedBy,
                b.M_UserM_BranchID prRequestedByFromBranch,
                S_RegionalName prRegionalName,
                M_BranchName prBranchName,
                IFNULL(`fn_getitemnamebyprid`(PurchaseRequestID), '') prItemName
                FROM purchase_request
                JOIN s_regional
                ON PurchaseRequestS_RegionalID = S_RegionalID
                AND S_RegionalIsActive = 'Y'
                JOIN item_category 
                ON PurchaseRequestItemCategoryID  = ItemCategoryID
                AND ItemCategoryIsActive = 'Y'
                JOIN m_user b
                ON PurchaseRequestRequestedBy = b.M_UserID
                AND b.M_UserIsActive = 'Y'
                LEFT JOIN m_user a
                ON PurchaseRequestApprovedBy = a.M_UserID
                AND a.M_UserIsActive = 'Y'
                LEFT JOIN 
                m_branch
                ON PurchaseRequestM_BranchCode = M_BranchCode
                WHERE PurchaseRequestIsActive = 'Y' AND PurchaseRequestItemCategoryID = 1
                AND (PurchaseRequestNumber LIKE ? OR PurchaseRequestRefNumber LIKE ? OR  PurchaseRequestRequestedBy LIKE ?)
                AND (PurchaseRequestDate BETWEEN ? AND ?) AND PurchaseRequestS_RegionalID = ?
                $sqlStockRequest
                $sqlBranch
                $sqlStatus
                ORDER BY prDate,prNumber
                DESC
                LIMIT ? OFFSET ?
                ";
        $qry = $this->db->query($sql, $params);
        if (!$qry) {
            $this->sys_error_db("Error searching");
            exit;
        }
        //echo $this->db->last_query();
        //exit;
        $data = $qry->result_array();

        $result = array(
            'total' => $tot_page,
            'records' => $data,
            // "qry" => $this->db->last_query()
        );

        $this->sys_ok($result);
    }

    function getDetail()
    {
        if (! $this->isLogin) {
            $this->sys_error("Invalid Token");
            exit;
        }
        $prm = $this->sys_input;
        $id = $prm['id'];

        $sql = "SELECT
            PurchaseRequestID as prDetailPrID,
            PurchaseRequestDetailID as prDetailID,
            PurchaseRequestDetailM_ItemID as prDetailItemID,
            M_ItemDesc as prDetailItemName,
            M_ItemCode as prDetailItemCode,
            PurchaseRequestDetailQty as prDetailItemQty,
            PurchaseRequestDetailPrice as prDetailItemPrice,
            PurchaseRequestDetailItemUnitID,
            ItemUnitName as prDetailItemUnitName,
            SUM(StockQty) AS CurrentStockQty
        FROM purchase_request
        JOIN purchase_request_detail ON PurchaseRequestDetailPurchaseRequestID = PurchaseRequestID 
            AND PurchaseRequestDetailIsActive = 'Y'
        JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID
        JOIN itemunit ON ItemUnitID = PurchaseRequestDetailItemUnitID
        LEFT JOIN m_branch ON M_BranchCode = PurchaseRequestM_BranchCode
        JOIN warehouse ON WarehouseS_RegionalID = PurchaseRequestS_RegionalID 
            AND WarehouseM_BranchID = COALESCE(M_BranchID, 0)
            AND WarehouseIsTransit = 'N'
        LEFT JOIN stock ON StockWarehouseID = WarehouseID 
            AND StockItemID = PurchaseRequestDetailM_ItemID
            AND StockItemUnitID = PurchaseRequestDetailItemUnitID
        WHERE PurchaseRequestID = ?
        GROUP BY
            PurchaseRequestDetailID,
            PurchaseRequestDetailM_ItemID, 
            PurchaseRequestDetailItemUnitID,
            M_ItemDesc,
            M_ItemCode,
            ItemUnitName";
        $qry = $this->db->query($sql, [$id]);
        if (!$qry) {
            $this->sys_error_db("Error get detail");

            exit;
        }
        $data = $qry->result_array();
        $this->sys_ok($data);
    }

    function approve()
    {
        $this->db->trans_begin();
        // $this->db->trans_rollback();
        // $this->db->trans_commit();
        if (! $this->isLogin) {
            $this->sys_error("Invalid Token");
            exit;
        }
        $prm = $this->sys_input;
        $detail = $prm['detail'];
        $user = $this->sys_user;
        $userid = $user["M_UserID"];
        $pr = $prm['pr'];
        $total = $prm['total'];
        $type = $prm['type'];

        // get user level approval 
        $sqlevel = "SELECT M_UserM_ApproveLevelID FROM m_user WHERE M_UserIsActive = 'Y' AND M_UserID = ?";
        $qulevel = $this->db->query($sqlevel, [$userid]);
        if (!$qulevel) {
            $this->sys_error_db("[Error] get approval level user");
            exit;
        }
        $userlevel = $qulevel->row_array()['M_UserM_ApproveLevelID'];

        $datas_log = array();
        $sql = "SELECT * FROM purchase_request WHERE PurchaseRequestID = ? AND PurchaseRequestIsActive = 'Y'";
        $query = $this->db->query($sql, [$pr['prID']]);
        if (!$query) {
            $this->db->trans_rollback();
            $this->sys_error_db("purchase request select", $this->db);
            exit;
        }
        $header = $query->row_array();


        $datas_log['header'] = $header;
        $sql = "SELECT * 
                FROM purchase_request_detail 
                JOIN m_item ON M_ItemID = PurchaseRequestDetailM_ItemID AND M_ItemIsActive = 'Y'
                JOIN itemunit ON ItemUnitID = PurchaseRequestDetailItemUnitID AND ItemUnitIsActive = 'Y'
                WHERE PurchaseRequestDetailPurchaseRequestID = ? AND PurchaseRequestDetailIsActive = 'Y'";
        $query = $this->db->query($sql, [$pr['prID']]);
        if (!$query) {
            $this->db->trans_rollback();
            $this->sys_error_db("purchase request detail select", $this->db);
            exit;
        }
        $details = $query->result_array();
        $datas_log['details'] = $details;

        if ($type == 'A') {
            // verifikasi jika manager
            if ($userlevel == '1') {
                $sql = "UPDATE purchase_request SET 
                        PurchaseRequestVerifiedBy = ?,
                        PurchaseRequestVerifiedDate = NOW()
                        WHERE PurchaseRequestID = ?
                        AND PurchaseRequestStatus = 'Pending'";
                $qry = $this->db->query($sql, [$userid, $pr['prID']]);
                if (!$qry) {
                    $this->sys_error_db("Error verifikasi manager");
                    $this->db->trans_rollback();
                    exit;
                }
                $messages = "Purchase Request dengan kode " . $header['PurchaseRequestNumber'] . " telah di verifikasi";
                $this->insert_act_log("PRP", "Verified", $messages, $pr['prID'], $this->safeJsonEncode($datas_log), $userid);
            }

            // approve jika kepala cabang / regional
            if ($userlevel == '2') {
                // -- PurchaseRequestTotal = ?,
                $sql = "UPDATE purchase_request SET 
                        PurchaseRequestStatus = ?,
                        PurchaseRequestApprovedDate = NOW(),
                        PurchaseRequestApprovedBy = ?
                        WHERE PurchaseRequestID = ?
                        AND PurchaseRequestStatus = 'Pending'";
                $qry = $this->db->query($sql, ['Approved', $userid, $pr['prID']]);
                if (!$qry) {
                    $this->sys_error_db("Error Approve");
                    $this->db->trans_rollback();
                    exit;
                }
                $sql = "UPDATE purchase_request_detail 
                        SET PurchaseRequestDetailStatus = ?
                        WHERE PurchaseRequestDetailPurchaseRequestID = ?";
                $qry = $this->db->query($sql, ['Approved', $pr['prID']]);
                if (!$qry) {
                    $this->sys_error_db("Error update detail");
                    $this->db->trans_rollback();
                    exit;
                }
                $messages = "Purchase Request dengan kode " . $header['PurchaseRequestNumber'] . " telah di approved";
                $this->insert_act_log("PRP", "Approved", $messages, $pr['prID'], $this->safeJsonEncode($datas_log), $userid);
            }
        } else if ($type == 'R') {
            $sql = "UPDATE purchase_request
                    SET 
                    PurchaseRequestStatus = ?,
                    PurchaseRequestApprovedDate = NOW(),
                    PurchaseRequestApprovedBy = ?
                    WHERE PurchaseRequestID = ?
                    AND PurchaseRequestStatus = 'Pending'";
            $qry = $this->db->query($sql, ['Rejected', $userid, $pr['prID']]);
            if (!$qry) {
                $this->sys_error_db("Error Approve");
                $this->db->trans_rollback();
                exit;
            }
            $sql = "UPDATE purchase_request_detail 
                    SET PurchaseRequestDetailStatus = ?
                    WHERE PurchaseRequestDetailPurchaseRequestID = ?";
            $qry = $this->db->query($sql, ['Rejected', $pr['prID']]);
            if (!$qry) {
                $this->sys_error_db("Error update detail");
                $this->db->trans_rollback();
                exit;
            }
            $messages = "Purchase Request dengan kode " . $header['PurchaseRequestNumber'] . " telah di reject";
            $this->insert_act_log("PRP", "Rejected", $messages, $pr['prID'], $this->safeJsonEncode($datas_log), $userid);
        } else if ($type == 'U') {
            // un approve jika kepala cabang / regional
            if ($userlevel == '2') {
                // -- PurchaseRequestTotal = ?,
                $sql = "UPDATE purchase_request SET 
                        PurchaseRequestStatus = ?,
                        PurchaseRequestApprovedDate = NULL,
                        PurchaseRequestApprovedBy = NULL
                        WHERE PurchaseRequestID = ?
                        AND PurchaseRequestStatus = 'Approved'";
                $qry = $this->db->query($sql, ['Pending', $userid, $pr['prID']]);
                if (!$qry) {
                    $this->sys_error_db("Error Approve");
                    $this->db->trans_rollback();
                    exit;
                }
                $sql = "UPDATE purchase_request_detail 
                        SET PurchaseRequestDetailStatus = ?
                        WHERE PurchaseRequestDetailPurchaseRequestID = ?";
                $qry = $this->db->query($sql, ['Pending', $pr['prID']]);
                if (!$qry) {
                    $this->sys_error_db("Error update detail");
                    $this->db->trans_rollback();
                    exit;
                }
                $messages = "Purchase Request dengan kode " . $header['PurchaseRequestNumber'] . " telah di unapproved";
                $this->insert_act_log("PRP", "Unapproved", $messages, $pr['prID'], $this->safeJsonEncode($datas_log), $userid);
            }
        }

        // update notification
        $this->readNotif($type, $userlevel, $userid, $pr['prID']);

        $this->db->trans_commit();

        $this->sys_ok('Berhasil');
    }

    // read notification
    function readNotif($type, $userlevel, $userId, $refID)
    {

        $this->db->trans_begin();

        // cari user penerima notifikasi
        if ($type == "U") {
            $sql_get = "SELECT PurchaseRequestID,
                M_UserID,
                M_UserUsername,
                NotificationID,
                NotificationDetailID,
                NotificationDetailStatus,
                NotificationDetailM_UserID,
                NotificationDetailM_ApproveLevelID
                FROM notification  
                JOIN purchase_request ON NotificationRefID = PurchaseRequestID
                AND PurchaseRequestIsActive = 'Y'
                JOIN notification_detail ON NotificationID = NotificationDetailNotificationID
                JOIN m_user ON NotificationUserID = M_UserID
                WHERE PurchaseRequestID = ?
                AND NotificationDetailStatus = 'read'";
            $qry = $this->db->query($sql_get, [$refID]);
            if (!$qry) {
                $this->sys_error_db("select user notification error", $this->db);
                exit;
            }
            $rowsuser = $qry->result_array();
        } else {
            $sql_get = "SELECT PurchaseRequestID,
                M_UserID,
                M_UserUsername,
                NotificationID,
                NotificationDetailID,
                NotificationDetailStatus,
                NotificationDetailM_UserID,
                NotificationDetailM_ApproveLevelID
                FROM notification  
                JOIN purchase_request ON NotificationRefID = PurchaseRequestID
                AND PurchaseRequestIsActive = 'Y'
                JOIN notification_detail ON NotificationID = NotificationDetailNotificationID
                JOIN m_user ON NotificationUserID = M_UserID
                WHERE PurchaseRequestID = ?
                AND NotificationDetailStatus = 'unread'";
            $qry = $this->db->query($sql_get, [$refID]);
            if (!$qry) {
                $this->sys_error_db("select user notification error", $this->db);
                exit;
            }
            $rowsuser = $qry->result_array();
        }


        foreach ($rowsuser as $user) {

            if ($type == "A") {
                if ($userlevel === '1') {
                    // verifikasi manager
                    $sql = "UPDATE notification_detail SET 
                        NotificationDetailStatus = 'read',
                        NotificationDetailLastUpdated = NOW(),
                        NotificationDetailUserID = ?
                        WHERE NotificationDetailNotificationID = ?
                        AND NotificationDetailM_ApproveLevelID = ?";
                    $qry = $this->db->query($sql, [$userId, $user["NotificationID"], $user["NotificationDetailM_ApproveLevelID"]]);
                    if (!$qry) {
                        $this->sys_error_db("update notification error", $this->db);
                        exit;
                    }
                } else if ($userlevel === '2') {
                    // approve kepala cabang / regional
                    $sql = "UPDATE notification_detail SET 
                        NotificationDetailStatus = 'read',
                        NotificationDetailLastUpdated = NOW(),
                        NotificationDetailUserID = ?
                        WHERE NotificationDetailNotificationID = ?
                        AND NotificationDetailM_ApproveLevelID = ?";
                    $qry = $this->db->query($sql, [$userId, $user["NotificationID"], $user["NotificationDetailM_ApproveLevelID"]]);
                    if (!$qry) {
                        $this->sys_error_db("update notification error", $this->db);
                        exit;
                    }
                }
            } else if ($type == "R") {
                $sql = "UPDATE notification_detail SET 
                        NotificationDetailStatus = 'read',
                        NotificationDetailLastUpdated = NOW(),
                        NotificationDetailUserID = ?
                        WHERE NotificationDetailNotificationID = ?";
                $qry = $this->db->query($sql, [$userId, $user["NotificationID"]]);
                if (!$qry) {
                    $this->sys_error_db("update notification error", $this->db);
                    exit;
                }
            } else if ($type == "U") {
                if ($userlevel === '2') {
                    $sql = "UPDATE notification_detail SET 
                            NotificationDetailStatus = 'unread',
                            NotificationDetailLastUpdated = NOW(),
                            NotificationDetailUserID = ?
                            WHERE NotificationDetailNotificationID = ?
                            AND NotificationDetailM_ApproveLevelID = ?";
                    $qry = $this->db->query($sql, [$userId, $user["NotificationID"], $user["NotificationDetailM_ApproveLevelID"]]);
                    if (!$qry) {
                        $this->sys_error_db("update notification error", $this->db);
                        exit;
                    }
                }
            }
        }

        $this->db->trans_commit();
    }

    function getUserApproveLevel()
    {
        if (!$this->isLogin) {
            $this->sys_error("Invalid Token");
            exit;
        }
        $userId = $this->sys_user["M_UserID"];

        $sqlevel = "SELECT M_UserM_ApproveLevelID FROM m_user WHERE M_UserIsActive = 'Y' AND M_UserID = ?";
        $qulevel = $this->db->query($sqlevel, [$userId]);
        if (!$qulevel) {
            $this->sys_error_db("[Error] get approval level user");
            exit;
        }
        $data = $qulevel->row_array();

        $this->sys_ok($data);
    }

    function updateqty()
    {
        if (!$this->isLogin) {
            $this->sys_error("Invalid Token");
            exit;
        }

        $this->db->trans_begin();
        $userId = $this->sys_user["M_UserID"];
        $prm = $this->sys_input;

        $arrItems = $prm["arrItems"];

        if (count($arrItems) > 0) {
            foreach ($arrItems as $key => $value) {
                $sql = "UPDATE purchase_request_detail SET 
                        PurchaseRequestDetailQty = ?,
                        PurchaseRequestDetailLastUpdated = NOW(),
                        PurchaseRequestDetailLastUpdatedUserID = ?
                        WHERE PurchaseRequestDetailID = ?";
                $qry = $this->db->query($sql, [
                    $value['prDetailItemQty'],
                    $userId,
                    $value['prDetailID']
                ]);
                if (!$qry) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("Failed update qty", $this->db);
                    exit;
                }
            }
        }

        $this->db->trans_commit();
        $this->sys_ok("Berhasil update qty");
    }

    function insert_act_log($code, $status, $description, $refId, $data, $userId)
    {
        $sql = "INSERT INTO user_activity(
                                UserActivityCode,
                                UserActivityStatus,
                                UserActivityDescription,
                                UserActivityRefID,
                                UserActivityData,
                                UserActivityUserID,
                                UserActivityCreated) 
                    VALUES (?,?,?,?,?,?,?)";
        $query = $this->db->query($sql, [$code, $status, $description, $refId, $data, $userId, date("Y-m-d H:i:s")]);
        if (!$query) {
            $this->sys_error_db("user activity", $this->db);
            exit;
        }
    }

    private function safeJsonEncode($data)
    {
        // Coba encode data ke JSON
        $jsonData = json_encode($data);

        // Cek apakah terjadi error saat encode
        if (json_last_error() !== JSON_ERROR_NONE) {
            $errorMsg = json_last_error_msg();
            error_log("JSON encode error: " . $errorMsg);

            // Lakukan sanitasi dan perbaikan data
            $fixedData = $this->fixJsonEncodeIssues($data, $errorMsg);

            // Coba encode lagi setelah diperbaiki
            $jsonData = json_encode($fixedData);

            // Jika masih error, log dan kembalikan objek kosong
            if (json_last_error() !== JSON_ERROR_NONE) {
                error_log("Failed to fix JSON encode issues: " . json_last_error_msg());
                // Kembalikan objek kosong jika masih gagal
                return '{}';
            }
        }

        return $jsonData;
    }

    // Fungsi untuk memperbaiki masalah encoding JSON
    private function fixJsonEncodeIssues($data, $errorMsg)
    {
        // Buat salinan data untuk dimodifikasi
        $fixedData = $data;

        // Tangani berbagai jenis error
        if (strpos($errorMsg, 'Malformed UTF-8') !== false) {
            // Perbaiki masalah karakter UTF-8
            $fixedData = $this->fixUTF8Issues($fixedData);
        } else if (strpos($errorMsg, 'Inf and NaN cannot be JSON encoded') !== false) {
            // Perbaiki masalah nilai Infinity atau NaN
            $fixedData = $this->fixInfNanIssues($fixedData);
        } else {
            // Konversi semua nilai numerik menjadi string untuk menghindari masalah presisi
            $fixedData = $this->convertNumericValuesToStrings($fixedData);

            // Perbaiki masalah referensi recursif
            $fixedData = $this->fixRecursiveReferences($fixedData);
        }

        return $fixedData;
    }

    // Perbaiki masalah karakter UTF-8
    private function fixUTF8Issues($data)
    {
        if (is_string($data)) {
            return mb_convert_encoding($data, 'UTF-8', 'UTF-8');
        } else if (is_array($data)) {
            foreach ($data as $key => $value) {
                $data[$key] = $this->fixUTF8Issues($value);
            }
        }
        return $data;
    }

    // Perbaiki masalah nilai Infinity atau NaN
    private function fixInfNanIssues($data)
    {
        if (is_array($data)) {
            foreach ($data as $key => $value) {
                if (is_float($value) && (is_nan($value) || is_infinite($value))) {
                    $data[$key] = (string)$value; // Konversi ke string
                } else if (is_array($value)) {
                    $data[$key] = $this->fixInfNanIssues($value);
                }
            }
        }
        return $data;
    }

    // Perbaiki masalah referensi recursif
    private function fixRecursiveReferences($data, $depth = 0)
    {
        // Batasi kedalaman rekursi untuk menghindari infinite loop
        if ($depth > 50) {
            return "[MAX_DEPTH_REACHED]";
        }

        if (is_array($data)) {
            $result = [];
            foreach ($data as $key => $value) {
                if (is_array($value)) {
                    $result[$key] = $this->fixRecursiveReferences($value, $depth + 1);
                } else {
                    $result[$key] = $value;
                }
            }
            return $result;
        }

        return $data;
    }

    // Cari dan konversi numerik ke string secara rekursif
    private function convertNumericValuesToStrings($data)
    {
        if (is_array($data)) {
            foreach ($data as $key => $value) {
                if (is_array($value)) {
                    $data[$key] = $this->convertNumericValuesToStrings($value);
                } else if (is_numeric($value)) {
                    $data[$key] = (string)$value;
                } else if (is_bool($value)) {
                    $data[$key] = $value ? "true" : "false";
                }
            }
        }
        return $data;
    }
}
