<?php

class PurchaseRequestDirect extends MY_Controller
{
    var $db;

    public function index()
    {
        echo "Purchase Request/Requester API";
    }

    public function __construct()
    {
        parent::__construct();
    }

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

            $payload = $this->sys_input;
            $userId = $this->sys_user["M_UserID"];

            $query = "SELECT prd.*, mu.M_UserFullName as M_RequesterFullName,
                      S_RegionalID,
                      S_RegionalName,
                      M_BranchID,
                      M_BranchCode,
                      M_BranchName
                      FROM purchase_request_direct as prd
                      JOIN m_user as mu ON prd.PurchaseRequestCreatedUserID = mu.M_UserID
                      LEFT JOIN s_regional ON S_RegionalID = PurchaseRequestDirectS_RegionalID
                      LEFT JOIN m_branch ON M_BranchCode = PurchaseRequestDirectM_BranchCode
                      WHERE PurchaseRequestDirectIsActive = 'Y' 
                      AND PurchaseRequestCreatedUserID = {$userId}
                      AND PurchaseRequestDirectNumber LIKE '%" . $payload["search"] . "%'";
            $queryCount = "SELECT count(*) as total
                           FROM purchase_request_direct as prd
                           JOIN m_user as mu ON prd.PurchaseRequestCreatedUserID = mu.M_UserID
                           WHERE PurchaseRequestDirectIsActive = 'Y' 
                           AND PurchaseRequestCreatedUserID = {$userId}
                           AND PurchaseRequestDirectNumber LIKE '%" . $payload["search"] . "%'";

            if ((isset($payload["startDate"]) && isset($payload["endDate"])) && (trim($payload["startDate"]) !== "" && trim($payload["endDate"]) !== "")) {
                $query .= " AND (PurchaseRequestDirectDate BETWEEN '{$payload["startDate"]} 00:00:00' AND '{$payload["endDate"]} 23:59:59' OR PurchaseRequestDirectDateUse BETWEEN '{$payload["startDate"]} 00:00:00' AND '{$payload["endDate"]} 23:59:59')";
                $queryCount .= " AND (PurchaseRequestDirectDate BETWEEN '{$payload["startDate"]} 00:00:00' AND '{$payload["endDate"]} 23:59:59' OR PurchaseRequestDirectDateUse BETWEEN '{$payload["startDate"]} 00:00:00' AND '{$payload["endDate"]} 23:59:59')";
            }

            if ($payload["status"]) {
                $query .= " AND PurchaseRequestDirectStatus = {$payload["status"]}";
                $queryCount .= " AND PurchaseRequestDirectStatus = {$payload["status"]}";
            }

            $exec = $this->db->query($queryCount, []);

            $numberLimit = 20;
            $numberOffset = 0;
            if ($payload["currentPage"] > 0) {
                $numberOffset = ($payload["currentPage"] - 1) * $numberLimit;
            }

            $totalCount = 0;
            $totalPage = 0;

            if ($exec) {
                $totalCount = $exec->result_array()[0]["total"];
                $totalPage = ceil($totalCount / $numberLimit);
            } else {
                $this->db->trans_rollback();
                $this->sys_error_db("select purchase request", $this->db);;
                exit;
            }

            $query .= " ORDER BY PurchaseRequestDirectNumber DESC 
                        LIMIT {$numberLimit} OFFSET {$numberOffset}";
            $exec = $this->db->query($query, []);

            if ($exec) {
                $rows = $exec->result_array();
            } else {
                $this->db->trans_rollback();
                $this->sys_error_db("select purchase request", $this->db);
                exit;
            }

            $result = array(
                "total" => $totalPage,
                "totalFilter" => $totalCount,
                "records" => $rows,
                "sql" => $this->db->last_query()
            );

            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $payload = $this->sys_input;

            $queryCount = "SELECT count(*) as total
                           FROM purchase_request_direct_detail
                           LEFT JOIN itemunit ON PurchaseRequestDirectDetailItemUnitID = ItemUnitID
                           WHERE PurchaseRequestDirectDetailIsActive = 'Y' 
                           AND PurchaseRequestDirectDetailPurchaseRequestDirectID = {$payload['PRID']}";
            $exec = $this->db->query($queryCount, []);

            $totalCount = 0;

            if ($exec) {
                $totalCount = $exec->result_array()[0]["total"];
            } else {
                $this->db->trans_rollback();
                $this->sys_error_db("select purchase request detail", $this->db);;
                exit;
            }

            $query = "SELECT *, 
                      ItemUnitID,
                      ItemUnitName,
                      PurchaseDirectCategoryCode,
                      PurchaseDirectCategoryName,
                      ROW_NUMBER() OVER(ORDER BY PurchaseRequestDirectDetailID) RowNumber,
                      '' as isAttachemnt,
                      '' as dataAttachment
                      FROM purchase_request_direct_detail 
                      JOIN purchase_direct_category ON PurchaseDirectCategoryID = PurchaseRequestDirectDetailPurchaseRequestDirectCategoryID 
                      LEFT JOIN itemunit ON PurchaseRequestDirectDetailItemUnitID = ItemUnitID
                      WHERE PurchaseRequestDirectDetailIsActive = 'Y' 
                      AND PurchaseRequestDirectDetailPurchaseRequestDirectID = {$payload['PRID']}
                      ORDER BY PurchaseRequestDirectDetailStatus ASC, 
                      PurchaseRequestDirectDetailID ASC";
            $exec = $this->db->query($query, []);

            if ($exec) {
                $rows = $exec->result_array();
            } else {
                $this->db->trans_rollback();
                $this->sys_error_db("select purchase request detail", $this->db);
                exit;
            }

            foreach ($rows as $key => $value) {
                if ($value['PurchaseDirectCategoryName'] !== "BBM") {
                    $rows[$key]['PurchaseRequestDirectDetailAmountRequest'] = intval($value['PurchaseRequestDirectDetailAmountRequest']);
                    $rows[$key]['PurchaseRequestDirectDetailEstimationPrice'] = intval($value['PurchaseRequestDirectDetailEstimationPrice']);
                    $rows[$key]['PurchaseRequestDirectDetailTotalEstimationPrice'] = intval($value['PurchaseRequestDirectDetailTotalEstimationPrice']);
                }

                $sql = "SELECT PurchaseDirectAttachmentID,
                            PurchaseDirectAttachmentPurchaseRequestDirectDetailID,
                            PurchaseDirectAttachmentName
                            FROM purchase_direct_attachment
                            WHERE PurchaseDirectAttachmentIsActive = 'Y'
                            AND PurchaseDirectAttachmentPurchaseRequestDirectDetailID = ?";
                $qry = $this->db->query($sql, [$value['PurchaseRequestDirectDetailID']]);
                if (!$qry) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("select purchase_direct_attachment", $this->db);
                    exit;
                }
                // echo $this->db->last_query();
                // exit;

                $rowsdata = $qry->result_array();

                if (count($rowsdata) > 0) {
                    $rows[$key]['isAttachemnt'] = true;
                    $rows[$key]['dataAttachment'] = $rowsdata;
                } else {
                    $rows[$key]['isAttachemnt'] = false;
                    $rows[$key]['dataAttachment'] = [];
                }
            }

            $result = array(
                "totalFilter" => $totalCount,
                "records" => $rows,
                "sql" => $this->db->last_query()
            );

            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    function getRegionalBranchByUser()
    {
        try {
            $userId = $this->sys_user["M_UserID"];

            $query = "SELECT DISTINCT
                      M_BranchCode,
                      M_BranchName
                      FROM m_branch
                      WHERE M_BranchIsActive = 'Y'
                      ORDER BY M_BranchName ASC";
            $exec = $this->db->query($query, []);
            if ($exec) {
                $rows = $exec->result_array();
            } else {
                $this->db->trans_rollback();
                $this->sys_error_db("select branch", $this->db);
                exit;
            }

            $result = array(
                "records" => $rows,
                "sql" => $this->db->last_query()
            );

            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    function getBranch()
    {
        try {
            $query = "SELECT DISTINCT
                      M_BranchCode,
                      M_BranchName
                      FROM m_branch
                      WHERE M_BranchIsActive = 'Y'
                      ORDER BY M_BranchName ASC";
            $exec = $this->db->query($query, []);
            if ($exec) {
                $rows = $exec->result_array();
            } else {
                $this->db->trans_rollback();
                $this->sys_error_db("select branch", $this->db);
                exit;
            }

            $result = array(
                "records" => $rows,
                "sql" => $this->db->last_query()
            );

            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $this->db->trans_begin();

            $payload = $this->sys_input;
            $user = $this->sys_user;
            $userId = $this->sys_user["M_UserID"];

            // $pdSql = "SELECT `fn_numbering`('PD') AS PD";
            // $exec = $this->db->query($pdSql, []);
            // $pd = "";
            $dateNow = date('Y-m-d');

            // if (!$exec) {
            //     $this->db->trans_rollback();
            //     $this->sys_error_db("purchase request insert error", $this->db);
            //     exit;
            // } else {
            //     $pd = $exec->result_array()[0]["PD"];
            // }

            $areaid = $user['M_BranchID'];
            $areatype = 'B';
            if ($user['loginLevel'] == 'regional') {
                $areaid = $user['S_RegionalID'];
                $areatype = 'R';
            }

            $sqlusrdivisi = "SELECT M_UserDivisionDivisionID FROM m_userdivision 
                WHERE M_UserDivisionM_UserID = ? AND M_UserDivisionIsActive = 'Y'";
            $queusrdivisi = $this->db->query($sqlusrdivisi, [$userId]);
            if (!$queusrdivisi) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] get user divisi", $this->db);
                exit;
            }
            $userDivID = $queusrdivisi->row_array()['M_UserDivisionDivisionID'];

            if (!$userDivID) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] divisi user tidak ditemukan", $this->db);
                exit;
            }

            $sqlnum = "SELECT `fn_penomoran`(?, ?, ?, ?, ?, ?) AS numpd;";
            $quenum = $this->db->query($sqlnum, ['PD', $userDivID, $areatype, $areaid, 'SM', 'Y']);
            if (!$quenum) {
                $this->db->trans_rollback();
                $this->sys_error_db("[Error] generate number doc", $this->db);
                exit;
            }
            $numpd = $quenum->row_array()['numpd'];

            $sql = "INSERT INTO purchase_request_direct(
                    PurchaseRequestDirectNumber,
                    PurchaseRequestDirectDate,
                    PurchaseRequestDirectDateUse,
                    PurchaseRequestDirectS_RegionalID,
                    PurchaseRequestDirectM_BranchCode,
                    PurchaseRequestDirectDescription,
                    PurchaseRequestDirectNote,
                    PurchaseRequestDirectTotalEstimation,
                    PurchaseRequestDirectTotalPaid,
                    PurchaseRequestDirectTotalRealitation,
                    PurchaseRequestDirectStatus,
                    PurchaseRequestDirectApprovedDate,
                    PurchaseRequestDirectApprovedBy,
                    PurchaseRequestConfirmedDate,
                    PurchaseRequestConfirmedBy,
                    PurchaseRequestPaidDate,
                    PurchaseRequestPaidBy,
                    PurchaseRequestDirectIsActive,
                    PurchaseRequestCreated,
                    PurchaseRequestLastUpdated,
                    PurchaseRequestDeleted,
                    PurchaseRequestCreatedUserID,
                    PurchaseRequestLastUpdatedUserID,
                    PurchaseRequestDeletedUserID
                    ) VALUES ('{$numpd}', '{$dateNow}', '{$payload['PRDateUse']}', '{$payload['PRRegional']}', '{$payload['PRBranch']}', '{$payload['PRDescription']}', NULL, 0, 0, 0, 'Draft', NULL, NULL, NULL, NULL, NULL, NULL, 'Y', NOW(), NULL, NULL, {$userId}, NULL, NULL)";
            $exec = $this->db->query($sql, []);

            if (!$exec) {
                $this->db->trans_rollback();
                $this->sys_error_db("purchase request insert error", $this->db);
                exit;
            }

            $prId = $this->db->insert_id();

            $this->db->trans_commit();

            $newInsert = "SELECT * FROM purchase_request_direct WHERE PurchaseRequestDirectID = '{$prId}' AND PurchaseRequestDirectIsActive = 'Y'";
            $records = $this->db->query($newInsert, [])->result_array();

            $sql = "SELECT * FROM purchase_request_direct
                    JOIN m_user ON M_UserID = PurchaseRequestCreatedUserID
                    WHERE PurchaseRequestDirectID = ?";
            $query = $this->db->query($sql, [$prId]);
            $row = $query->row_array();
            $data = array("header" => $row);
            $message = "Nomor PRD: " . $row["PurchaseRequestDirectNumber"] . " berhasil dibuat oleh " . $row["M_UserUsername"];
            $this->insert_act_log("PRD", "NEW", $message, $prId, $this->safeJsonEncode($data), $userId);

            $result = array("total" => 1, "records" => $records);
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $this->db->trans_begin();
            $messages_log = [];
            $datas_log = [];
            $payload = $this->sys_input;
            $userId = $this->sys_user["M_UserID"];
            $prDateUse = isset($payload["PRDateUse"]) ? $payload["PRDateUse"] : "";
            $prId = isset($payload["PRID"]) ? $payload["PRID"] : "";
            $prDateUse = date("Y-m-d", strtotime($prDateUse));
            if ($prDateUse == "" || $prDateUse == null) {
                $this->sys_error("Invalid PR Date Use");
                exit;
            }
            $prDescription = isset($payload["PRDescription"]) ? $payload["PRDescription"] : "";
            $PRBranch = isset($payload["PRBranch"]) ? $payload["PRBranch"] : "";
            $sql = "SELECT *
                    FROM purchase_request_direct 
                    WHERE PurchaseRequestDirectID = ? AND PurchaseRequestDirectIsActive = 'Y'";
            $query = $this->db->query($sql, [$prId]);
            if (!$query) {
                $this->db->trans_rollback();
                $this->sys_error_db("purchase request direct", $this->db);
                exit;
            }
            $row = $query->row_array();


            $datas_log['header'] = $row;

            if ($row["PurchaseRequestDirectDateUse"] != $prDateUse) {
                $messages_log[] = "Perubahan tanggal PR: " . $row["PurchaseRequestDirectDateUse"] . " menjadi " . $prDateUse;
            }
            if ($row["PurchaseRequestDirectDescription"] != $prDescription) {
                $messages_log[] = "Perubahan keterangan PR: " . $row["PurchaseRequestDirectDescription"] . " menjadi " . $prDescription;
            }
            if ($row["PurchaseRequestDirectM_BranchCode"] != $PRBranch) {
                $messages_log[] = "Perubahan kode cabang PR: " . $row["PurchaseRequestDirectM_BranchCode"] . " menjadi " . $PRBranch;
            }


            $sql = "UPDATE purchase_request_direct SET
                    PurchaseRequestDirectDateUse = '{$payload['PRDateUse']}',
                    PurchaseRequestDirectM_BranchCode = '{$payload['PRBranch']}',
                    PurchaseRequestDirectDescription = '{$payload['PRDescription']}',
                    PurchaseRequestLastUpdated = NOW(),
                    PurchaseRequestLastUpdatedUserID = {$userId}
                    WHERE PurchaseRequestDirectID = {$payload['PRID']}";
            $exec = $this->db->query($sql, []);

            if (!$exec) {
                $this->db->trans_rollback();
                $this->sys_error_db("purchase request update error", $this->db);
                exit;
            }

            $this->db->trans_commit();

            $newUpdate = "SELECT * FROM purchase_request_direct WHERE PurchaseRequestDirectID = {$payload['PRID']} AND PurchaseRequestDirectIsActive = 'Y'";
            $records = $this->db->query($newUpdate, [])->result_array();

            if (count($messages_log) > 0) {
                $message = "Perubahan PR Pembelian Langsung: " . $prNumber . "\n";
                $message .= implode("\n", $messages_log);
            } else {
                $message = "PR  Pembelian Langsung: " . $prNumber . " tanpa perubahan";
            }

            $datas_log = $this->convertNumericValuesToStrings($datas_log);
            $this->insert_act_log("PRNP", "Update", $message, $prId, $this->safeJsonEncode($datas_log), $userId);

            $result = array("total" => 1, "records" => $records);
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $this->db->trans_begin();

            $payload = $this->sys_input;
            $userId = $this->sys_user["M_UserID"];

            $prId = $payload['PRID'];

            $datas_log = array();
            $sql = "SELECT * FROM purchase_request_direct WHERE PurchaseRequestDirectID = ? AND PurchaseRequestDirectIsActive = 'Y'";
            $query = $this->db->query($sql, [$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_direct_detail 
                    JOIN itemunit ON ItemUnitID = PurchaseRequestDirectDetailItemUnitID
                    WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = ? AND PurchaseRequestDirectDetailIsActive = 'Y'";
            $query = $this->db->query($sql, [$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;

            $sql = "UPDATE purchase_request_direct SET
                    PurchaseRequestDeleted = NOW(),
                    PurchaseRequestDeletedUserID = {$userId},
                    PurchaseRequestDirectIsActive = 'N'
                    WHERE PurchaseRequestDirectID = {$payload['PRID']}";
            $exec = $this->db->query($sql, []);

            if (!$exec) {
                $this->db->trans_rollback();
                $this->sys_error_db("purchase request delete error", $this->db);
                exit;
            }

            $sql = "UPDATE purchase_request_direct_detail SET
                    PurchaseRequestDirectDetailDeleted = NOW(),
                    PurchaseRequestDirectDetailDeletedUserID = {$userId},
                    PurchaseRequestDirectDetailIsActive = 'N'
                    WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = {$payload['PRID']}";
            $exec = $this->db->query($sql, []);

            if (!$exec) {
                $this->db->trans_rollback();
                $this->sys_error_db("purchase request detail delete error", $this->db);
                exit;
            }

            $messages = "Purchase Request Pembelian langsung dengan kode " . $header["PurchaseRequestDirectNumber"] . " sudah dihapus";
            $this->insert_act_log("PRNP", "Delete", $messages, $prId, $this->safeJsonEncode($datas_log), $userId);

            $this->db->trans_commit();
            $result = array("total" => 1, "records" => array("xId" => 0));
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $this->db->trans_begin();

            $payload = $this->sys_input;
            $userId = $this->sys_user["M_UserID"];
            // $PRDTotalPrice = intval($payload['PRDAmountRequest']) * intval($payload['PRDEstimationPrice']);
            $PRDTotalPrice = $payload['PRDTotalPrice'];

            $query = "SELECT COUNT(*) as exist 
                      FROM purchase_request_direct_detail 
                      WHERE PurchaseRequestDirectDetailIsActive = 'Y' 
                      AND PurchaseRequestDirectDescription = '{$payload['PRDDescriptionDetail']}' 
                      AND PurchaseRequestDirectDetailPurchaseRequestDirectID = {$payload['PRID']}";
            $exist = $this->db->query($query, []);
            if ($exist) {
                $row = $exist->row()->exist;
            } else {
                $this->sys_error_db("exist error", $this->db);
                exit;
            }

            if ($row == 0) {
                $sql = "INSERT INTO purchase_request_direct_detail(
                        PurchaseRequestDirectDetailPurchaseRequestDirectID,
                        PurchaseRequestDirectDetailPurchaseRequestDirectCategoryID,
                        PurchaseRequestDirectDetailItemUnitID,
                        PurchaseRequestDirectDescription,
                        PurchaseRequestDirectDetailAmountRequest,
                        PurchaseRequestDirectDetailAmount,
                        PurchaseRequestDirectDetailEstimationPrice,
                        PurchaseRequestDirectDetailTotalEstimationPrice,
                        PurchaseRequestDirectDetailTotalRealitationPrice,
                        PurchaseRequestDirectDetailStatus,
                        PurchaseRequestDirectDetailIsActive,
                        PurchaseRequestDirectDetailCreated,
                        PurchaseRequestDirectDetailLastUpdated,
                        PurchaseRequestDirectDetailDeleted,
                        PurchaseRequestDirectDetailCreatedUserID,
                        PurchaseRequestDirectDetailLastUpdatedUserID,
                        PurchaseRequestDirectDetailDeletedUserID
                        ) VALUES ({$payload['PRID']}, ?, {$payload['PRDItemUnitID']}, '{$payload['PRDDescriptionDetail']}', {$payload['PRDAmountRequest']}, NULL, {$payload['PRDEstimationPrice']}, {$PRDTotalPrice}, NULL, 'Pending', 'Y', NOW(), NULL, NULL, {$userId}, NULL, NULL)";
                $exec = $this->db->query($sql, [$payload['PRDCategoryID']]);

                if (!$exec) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("request insert error", $this->db);
                    exit;
                } else {
                    $sqlTotalPrice = "SELECT SUM(PurchaseRequestDirectDetailTotalEstimationPrice) AS Total
                                      FROM purchase_request_direct_detail
                                      WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = {$payload['PRID']}
                                      AND PurchaseRequestDirectDetailIsActive = 'Y'";
                    $exec = $this->db->query($sqlTotalPrice, []);
                    $total = 0;

                    if (!$exec) {
                        $this->db->trans_rollback();
                        $this->sys_error_db("order purchase request error", $this->db);
                        exit;
                    } else {
                        $total = $exec->result_array()[0]["Total"];
                    }

                    $sql = "UPDATE purchase_request_direct SET
                    PurchaseRequestDirectTotalEstimation = {$total},
                    PurchaseRequestLastUpdated = NOW(),
                    PurchaseRequestLastUpdatedUserID = {$userId}
                    WHERE PurchaseRequestDirectID = {$payload['PRID']}
                    AND PurchaseRequestDirectIsActive = 'Y'";
                    $exec = $this->db->query($sql, []);
                }
                $prId = $payload['PRID'];
                $sql = "SELECT * FROM purchase_request_direct
                JOIN m_user ON M_UserID = PurchaseRequestCreatedUserID
                WHERE PurchaseRequestDirectID = ?";
                $query = $this->db->query($sql, [$prId]);
                $row = $query->row_array();

                $sql = "SELECT * FROM purchase_request_direct_detail
                WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = ?";
                $query = $this->db->query($sql, [$prId]);
                $rows = $query->row_array();

                $data = array(
                    "header" => $row,
                    "details" => $rows
                );
                $message = "Penambahan Item Nomor PRD: " . $row["PurchaseRequestDirectNumber"] . "  oleh " . $row["M_UserUsername"]
                    . " Item : " . $payload['PRDDescriptionDetail'] . " jumlah : " . $payload['PRDAmountRequest'] . "harga : " . $payload['PRDAmountRequest'];
                $this->insert_act_log("PRD", "NEW", $message, $prId, $this->safeJsonEncode($data), $userId);

                $this->db->trans_commit();

                $result = array("total" => 1, "records" => array("xId" => 0));
                $this->sys_ok($result);
            } else {
                $errors = array();
                if ($row != 0) {
                    array_push($errors, array('msg' => 'Data sudah ada'));
                }

                $result = array("total" => -1, "errors" => $errors, "records" => array('status' => 'ERROR'));
                $this->sys_ok($result);
            }
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $this->db->trans_begin();

            $payload = $this->sys_input;
            $userId = $this->sys_user["M_UserID"];
            // $PRDTotalPrice = intval($payload["PRDAmountRequest"]) * intval($payload["PRDEstimationPrice"]);
            $PRDTotalPrice = $payload['PRDTotalPrice'];

            $sql = "UPDATE purchase_request_direct_detail SET 
                    PurchaseRequestDirectDetailPurchaseRequestDirectCategoryID = ?,
                    PurchaseRequestDirectDetailItemUnitID = {$payload["PRDItemUnitID"]},
                    PurchaseRequestDirectDescription = '{$payload["PRDDescriptionDetail"]}',
                    PurchaseRequestDirectDetailAmountRequest = {$payload["PRDAmountRequest"]},
                    PurchaseRequestDirectDetailEstimationPrice = {$payload["PRDEstimationPrice"]},
                    PurchaseRequestDirectDetailTotalEstimationPrice = {$PRDTotalPrice},
                    PurchaseRequestDirectDetailLastUpdated = NOW(),
                    PurchaseRequestDirectDetailLastUpdatedUserID = {$userId}
                    WHERE PurchaseRequestDirectDetailID = {$payload["PRDID"]}";
            $exec = $this->db->query($sql, [$payload['PRDCategoryID']]);

            if (!$exec) {
                $this->db->trans_rollback();
                $this->sys_error_db("request update error", $this->db);
                exit;
            } else {
                $sqlTotalPrice = "SELECT SUM(PurchaseRequestDirectDetailTotalEstimationPrice) AS Total
                                  FROM purchase_request_direct_detail
                                  WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = {$payload["PRID"]}
                                  AND PurchaseRequestDirectDetailIsActive = 'Y'";
                $exec = $this->db->query($sqlTotalPrice, []);
                $total = 0;

                if (!$exec) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("order purchase request error", $this->db);
                    exit;
                } else {
                    $total = $exec->result_array()[0]["Total"];
                }

                $sql = "UPDATE purchase_request_direct SET
                        PurchaseRequestDirectTotalEstimation = {$total},
                        PurchaseRequestLastUpdated = NOW(),
                        PurchaseRequestLastUpdatedUserID = {$userId}
                        WHERE PurchaseRequestDirectID = {$payload["PRID"]}
                        AND PurchaseRequestDirectIsActive = 'Y'";
                $exec = $this->db->query($sql, []);
            }

            $this->db->trans_commit();

            $result = array("total" => 1, "records" => array("xId" => $payload["PRDID"]));
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $this->db->trans_begin();

            $payload = $this->sys_input;
            $userId = $this->sys_user["M_UserID"];

            $sql = "UPDATE purchase_request_direct_detail SET
                    PurchaseRequestDirectDetailDeleted = NOW(),
                    PurchaseRequestDirectDetailDeletedUserID = {$userId},
                    PurchaseRequestDirectDetailIsActive = 'N'
                    WHERE PurchaseRequestDirectDetailID = {$payload["PRDID"]}";
            $exec = $this->db->query($sql, []);

            if (!$exec) {
                $this->db->trans_rollback();
                $this->sys_error_db("request delete error", $this->db);
                exit;
            } else {
                $sqlTotalPrice = "SELECT SUM(PurchaseRequestDirectDetailTotalEstimationPrice) AS Total
                                  FROM purchase_request_direct_detail
                                  WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = {$payload["PRID"]}
                                  AND PurchaseRequestDirectDetailIsActive = 'Y'";
                $exec = $this->db->query($sqlTotalPrice, []);
                $total = 0;

                if (!$exec) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("order purchase request error", $this->db);
                    exit;
                } else {
                    $total = $exec->result_array()[0]["Total"] ?? 0;
                }

                $sql = "UPDATE purchase_request_direct SET
                        PurchaseRequestDirectTotalEstimation = {$total},
                        PurchaseRequestLastUpdated = NOW(),
                        PurchaseRequestLastUpdatedUserID = {$userId}
                        WHERE PurchaseRequestDirectID = {$payload["PRID"]}
                        AND PurchaseRequestDirectIsActive = 'Y'";
                $exec = $this->db->query($sql, []);
            }

            $this->db->trans_commit();
            $result = array("total" => 1, "records" => array("xId" => 0));
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $this->db->trans_begin();

            $payload = $this->sys_input;
            $userId = $this->sys_user["M_UserID"];
            $branchId   = $this->sys_user['M_BranchID'];
            $regionalId = $this->sys_user['S_RegionalID'];

            $date = date('d-m-Y');

            $sqlDetail = "UPDATE purchase_request_direct_detail SET
                          PurchaseRequestDirectDetailLastUpdated = NOW(),
                          PurchaseRequestDirectDetailLastUpdatedUserID = {$userId}
                          WHERE PurchaseRequestDirectDetailPurchaseRequestDirectID = {$payload["PRID"]}
                          AND PurchaseRequestDirectDetailIsActive = 'Y'
                          AND PurchaseRequestDirectDetailStatus = 'Pending'";
            $exec = $this->db->query($sqlDetail, []);

            if (!$exec) {
                $this->db->trans_rollback();
                $this->sys_error_db("order purchase request error", $this->db);
                exit;
            }

            $sql = "UPDATE purchase_request_direct SET
                PurchaseRequestDirectStatus = 'Pending',
                PurchaseRequestLastUpdated = NOW(),
                PurchaseRequestLastUpdatedUserID = {$userId}
                WHERE PurchaseRequestDirectID = {$payload["PRID"]}
                AND PurchaseRequestDirectIsActive = 'Y'";
            $exec = $this->db->query($sql, []);

            if (!$exec) {
                $this->db->trans_rollback();
                $this->sys_error_db("order purchase request error", $this->db);
                exit;
            }

            $this->db->trans_commit();

            $sql = "SELECT *, 
                    ROW_NUMBER() OVER(ORDER BY PurchaseRequestDirectNumber) RowNumber 
                    FROM purchase_request_direct 
                    WHERE PurchaseRequestDirectIsActive = 'Y' 
                    AND PurchaseRequestCreatedUserID = {$userId}
                    AND PurchaseRequestDirectID = {$payload["PRID"]}";
            $exec = $this->db->query($sql, []);

            $row = [];
            if (!$exec) {
                $this->db->trans_rollback();
                $this->sys_error_db("order purchase request error", $this->db);
                exit;
            } else {
                $row = $exec->result_array();
            }

            $number = $row[0]["PurchaseRequestDirectNumber"];
            $totalEstimation = $row[0]["PurchaseRequestDirectTotalEstimation"];

            // notifications
            $this->saveNotification($userId, $date, $number, $payload["PRID"], $totalEstimation, $branchId, $regionalId);

            $result = array("total" => 1, "records" => $row);
            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

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

            $prm = $this->sys_input;
            $search = isset($prm["search"]) ? $prm["search"] : "";

            $sql = "SELECT 
                    ItemUnitID,
                    ItemUnitCode,
                    ItemUnitName,
                    ItemUnitCreated,
                    ItemUnitLastUpdated,
                    ItemUnitIsActive,
                    ItemUnitUserID
                FROM itemunit 
                WHERE ItemUnitIsActive = 'Y'
                AND ItemUnitName LIKE '%$search%'
                ORDER BY ItemUnitName ASC";

            $query = $this->db->query($sql);

            if (!$query) {
                $this->sys_error_db("item unit list", $this->db);
                exit;
            }

            $rows = $query->result_array();

            $result = array(
                "records" => $rows,
                "sql" => $this->db->last_query()
            );

            $this->sys_ok($result);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    function PurchaseDirectCategory()
    {
        try {
            if (!$this->isLogin) {
                $this->sys_error("Invalid Token");
                exit;
            }
            $param = $this->sys_input;

            $name = '%';
            if ($param['name'] != '') {
                $name = $param['name'];
            }

            $sql = "SELECT 
                PurchaseDirectCategoryID,
                PurchaseDirectCategoryCode,  
                PurchaseDirectCategoryName 
            FROM purchase_direct_category 
            WHERE PurchaseDirectCategoryIsActive = 'Y' 
                AND PurchaseDirectCategoryName LIKE ?";
            $que = $this->db->query($sql, [$name]);
            if (!$que) {
                $this->sys_error_db('[Error] get PR direct category');
                exit;
            }

            $category = $que->result_array();

            $this->sys_ok($category);
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }

    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;
    }

    function saveFiles()
    {
        $prm = $this->sys_input;
        // $userId = $this->sys_user["M_UserID"];

        $path = "/home/one/project/accone/one-media/cashier/";
        $config['upload_path'] = $path;
        $config['allowed_types'] = 'jpg|jpeg|png|gif';
        $config['max_size'] = '10000';
        $count = count($_FILES['files']['name']);
        $this->load->library('upload', $config);
        // $images_odoo = [];
        // $images_odoo_url = [];

        $error = [];
        if ($count != 0) {

            for ($i = 0; $i < $count; $i++) {

                if (!empty($_FILES['files']['name'][$i])) {
                    $_FILES['file']['name'] = $_FILES['files']['name'][$i];

                    $_FILES['file']['type'] = $_FILES['files']['type'][$i];

                    $_FILES['file']['tmp_name'] = $_FILES['files']['tmp_name'][$i];

                    $_FILES['file']['error'] = $_FILES['files']['error'][$i];

                    $_FILES['file']['size'] = $_FILES['files']['size'][$i];

                    // $namex = $_FILES['files']['name'][$i];

                    $ext = pathinfo($_FILES['name'][$i], PATHINFO_EXTENSION);
                    $random_str = bin2hex(random_bytes(4)); // atau uniqid()
                    $new_filename = 'D' . $random_str . '_' . $prm['directNumber'] . $ext;

                    $config['file_name'] = $new_filename;
                    $this->upload->initialize($config);


                    if ($this->upload->do_upload('file')) {
                        $uploadData = $this->upload->data();

                        $filename = $uploadData['file_name'];
                        $target_path = $path . $filename;
                        $type = pathinfo($target_path, PATHINFO_EXTENSION);
                        $data = file_get_contents($target_path);
                        $base64 = 'data:image/' . $type . ';base64,' . base64_encode($data);
                        // array_push($images_odoo, $base64);
                        $sql = "INSERT INTO purchase_direct_attachment(
                            PurchaseDirectAttachmentPurchaseRequestDirectDetailID,
                            PurchaseDirectAttachmentName,
                            PurchaseDirectAttachmentCreated,
                            PurchaseDirectAttachmentUserID) VALUES(
                            {$prm['PRDID']},'{$filename}',NOW(),{$prm['userId']})";

                        $qry = $this->db->query($sql);
                        $last_qry = $this->db->last_query();
                        if (!$qry) {
                            $this->db->trans_rollback();
                            $error = array(
                                "message" => $this->db->error()["message"],
                                "sql" => $last_qry
                            );
                            $this->sys_error_db($error, $this->db);
                            exit;
                        }
                    } else {
                        $error = array('error' => $this->upload->display_errors());
                        exit;
                    }
                }
            }

            $sql_update = "UPDATE purchase_request_direct SET
                PurchaseRequestDirectNotaStatus = 'Pending'
                WHERE PurchaseRequestDirectID = ?";
            $qry_update = $this->db->query($sql_update, [$prm["PRID"]]);
            if (!$qry_update) {
                $this->db->trans_rollback();
                $this->sys_error_db("update purchase nota error", $this->db);
                exit;
            }

            $this->sys_ok("Berhasil upload");
        } else {
            $this->sys_error("Data file kosong");
            exit;
        }
    }

    // notifications
    function saveNotification(
        $userId,
        $dateRequest,
        $number,
        $refID,
        $totalEstimation,
        $branchId,
        $regionalId
    ) {
        try {
            $this->db->trans_begin();

            $xdate = date('d-m-Y');

            $sql_user = "SELECT M_UserID, M_UserUsername
                FROM m_user
                WHERE M_UserIsActive = 'Y'
                AND M_UserID = ?";
            $qry_user = $this->db->query($sql_user, [$userId]);
            if ($qry_user) {
                $username = $qry_user->row_array();
            } else {
                $this->sys_error_db("select user error", $this->db);
                exit;
            }

            $description = "Pembuatan <strong>Purchase Request Direct</strong> pada tanggal <strong>" . $xdate . "</strong> oleh <strong>" . $username['M_UserUsername'] . "</strong> dengan nomor <strong>" . $number . "</strong>";

            $sql_menu = "SELECT S_MenuID,
                S_MenuName,
                S_MenuUrl,
                S_MenuLevel
                FROM s_menu
                WHERE S_MenuID = 18";
            $qry_menu = $this->db->query($sql_menu, []);
            if ($qry_menu) {
                $rowurl = $qry_menu->row_array();
            } else {
                $this->sys_error_db("select menu error", $this->db);
                exit;
            }

            $url = $rowurl['S_MenuUrl'] . "?flag=N&status=Pending&startdate=" . $dateRequest . "&search=" . $number;

            // cari user penerima notifikasi
            if ($branchId != 0) {
                // user cabang
                $sql_receive_user = "SELECT M_UserID, 
                        M_UserUsername,
                        M_ApproveLevelName,
                        M_ApproveLevelStartTotal,
                        M_ApproveLevelEndTotal,
                        M_UserM_ApproveLevelID
                FROM m_approve_level  
                JOIN m_user  ON M_UserM_ApproveLevelID = M_ApproveLevelID
                    AND M_UserIsActive = 'Y'
                JOIN m_branch ON  M_UserM_BranchID = M_BranchID
                    AND M_BranchIsActive = 'Y'
                AND M_BranchID = ?
                    WHERE ? BETWEEN M_ApproveLevelStartTotal AND M_ApproveLevelEndTotal
                AND M_ApproveLevelIsActive = 'Y'";
                $qry_receive_user = $this->db->query($sql_receive_user, [$branchId, $totalEstimation]);
                if ($qry_receive_user) {
                    $rowsuser = $qry_receive_user->result_array();
                } else {
                    $this->sys_error_db("select receive user error", $this->db);
                    exit;
                }
            } else if ($branchId == 0) {
                // user regional
                $sql_receive_user = "SELECT M_UserID, 
                        M_UserUsername,
                        M_ApproveLevelName,
                        M_ApproveLevelStartTotal,
                        M_ApproveLevelEndTotal,
                        M_UserM_ApproveLevelID
                    FROM m_approve_level  
                    JOIN m_user ON M_UserM_ApproveLevelID = M_ApproveLevelID
                        AND M_UserIsActive = 'Y'
                        AND M_UserM_BranchID = 0
                    JOIN s_regional ON M_UserS_RegionalID = S_RegionalID
                        AND S_RegionalIsActive = 'Y'
                        AND S_RegionalID = ?
                    WHERE ? BETWEEN M_ApproveLevelStartTotal AND M_ApproveLevelEndTotal
                    AND M_ApproveLevelIsActive = 'Y'";
                $qry_receive_user = $this->db->query($sql_receive_user, [$regionalId, $totalEstimation]);
                if ($qry_receive_user) {
                    $rowsuser = $qry_receive_user->result_array();
                } else {
                    $this->sys_error_db("select receive user error", $this->db);
                    exit;
                }
            }

            $sql = "INSERT INTO notification(
                NotificationRefID,
                NotificationType,
                NotificationDescription,
                NotificationUrl,
                NotificationUserID,
                NotificationCreated) VALUES(?,?,?,?,?,NOW())";
            $qry = $this->db->query($sql, [
                $refID,
                'Purchase Request Direct',
                $description,
                $url,
                $userId
            ]);
            if (!$qry) {
                $this->db->trans_rollback();
                $this->sys_error_db("insert notification error", $this->db);
                exit;
            }

            $lastid = $this->db->insert_id();

            // insert ke detail notification
            foreach ($rowsuser as $row) {
                $sql_detail = "INSERT INTO notification_detail(
                    NotificationDetailNotificationID,
                    NotificationDetailM_UserID,
                    NotificationDetailM_ApproveLevelID,
                    NotificationDetailStatus,
                    NotificationDetailCreated,
                    NotificationDetailUserID) VALUES(?,?,?,?,NOW(),?)";
                $qry_detail = $this->db->query($sql_detail, [
                    $lastid,
                    $row['M_UserID'], // user penerima notifikasi
                    $row['M_UserM_ApproveLevelID'],
                    'unread',
                    $userId
                ]);
                if (!$qry_detail) {
                    $this->db->trans_rollback();
                    $this->sys_error_db("insert notification detail error", $this->db);
                    exit;
                }
            }

            $this->db->trans_commit();
        } catch (Exception $exc) {
            $message = $exc->getMessage();
            $this->sys_error($message);
        }
    }
}
