<?php

class OrderProcessHelper {

    /**
     * insert new process step for order
     * @param  INT $idOrder   id for order
     * @param  INT $idProcess id for process
     * @return INT            first step id or 0 on failure
     */
    private function insertProcessStepsForOrder($idOrder, $idProcess){
        global $database;

        $sqlInsert = "INSERT IGNORE INTO ".TABLES['rel_order_process_step']."
                                    (idProcessStep, idOrder, status)
                                    VALUES ";

        $sql = "SELECT rps.id AS idProcessStep,
                    rps.idParent,
                   $idOrder as idOrder,
                   CASE WHEN rps.idParent=0 THEN 'in-progress' ELSE 'inactive' END AS status
               FROM ".TABLES['rel_process_steps']." rps
               INNER JOIN
               (
                   SELECT
                       rps_last.idProcess,
                       MAX(rps_last.processInstance) as lastInstace
                   FROM ".TABLES['rel_process_steps']." rps_last
                   WHERE rps_last.idProcess=$idProcess
                   GROUP BY rps_last.idProcess
               ) last_inst
                   ON last_inst.idProcess=rps.idProcess AND last_inst.lastInstace=rps.processInstance
               INNER JOIN ".TABLES['process_step']." ps
                    ON ps.id=rps.idStep
               WHERE rps.idProcess=$idProcess";

       $query = $database->query($sql);
       while($row = $database->fetchArray($query)){
           $sqlInsert .= "(
                    ".$row['idProcessStep'].",
                    ".$row['idOrder'].",
                    '".$row['status']."'),";
            if(intval($row['idParent']) === 0){
                $firstProcessStepId = $row['idProcessStep'];
            }
       }
       $sqlInsert = rtrim($sqlInsert, ',');
       $queryIns = $database->query($sqlInsert);

       return $database->affectedRows() > 0 ? $firstProcessStepId : 0;
    }

    /**
     * select a process for an order
     * @param INT $idOrder   id for the order
     * @param INT $idProcess id for process
     * @return Array update message
     */
    public function setProcessForOrder($idOrder, $idProcess, $ordersDetailsMail){
        global $database;

        $data = [];
        $actionsList = [];
        $idOrder = $database->escapeValue($idOrder);
        $idProcess = $database->escapeValue($idProcess);
        $ordersDetailsMail = (array) json_decode($ordersDetailsMail);
        $ordersDetailsMail['idProcess'] = $idProcess;
        $orderActions = new OrderActions();

        $firstStep = $this->insertProcessStepsForOrder($idOrder, $idProcess);
        if($firstStep > 0){
            $stepUpdated = $orderActions->executeAutomatedStep($idOrder, $firstStep);

            if($stepUpdated > 0){
                $data['messages'][] = [
                    'code' => 'success',
                    'message' => 'AUTOMATED_STEPS_EXECUTED'
                ];

                $orderStatusUpdated =  $this->updateOrderStatus($idOrder);

                if($orderStatusUpdated['orderUpdated'] > 0) {
                    $message = [
                        'code' => 'success',
                        'message' => 'ORDER_UPDATED'
                    ];
                    $data['messages'][] = $message;
                    $data['order'] = $orderStatusUpdated['orderUpdated'];

                    $ordersDetailsMail['status'] = $orderStatusUpdated['status'];
                    $data['messages'][] = $this->sendConfirmationMail('orderStatusChanged', $ordersDetailsMail);
                }

                $data['messages'][] = [
                    'code' => 'success',
                    'message' => 'PROCESS_SET'
                ];

                $data['messages'][] = $this->sendConfirmationMail('processAssigned', $ordersDetailsMail);
            }else{
                $data['messages'][] = [
                    'code' => 'error',
                    'message' => 'AUTOMATED_STEPS_FAILED'
                ];
            }

        }else{
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'PROCESS_ADD_ERROR'
            ];
        }

        return $data;
    }

    /**
     * get the order status
     * @param  HashArray $packageStatuses statuses for packages in order
     * @return String                     order status
     */
    private function getOrderStatusBasedOnPackages($packageStatuses){
        $delivered = intval($packageStatuses['endOfLife']) + intval($packageStatuses['production']);
        if($packageStatuses['endOfLife'] === $packageStatuses['totalPackages']){
            return 'end-of-life';
        }else if($delivered === intval($packageStatuses['totalPackages'])){
            return 'production';
        }else if($packageStatuses['processing'] > 0){
            return 'in-progress';
        }

        return 'none';
    }

    /**
     * update order status
     * @param  INT $idOrder id for order
     * @return HashArray        updated object
     */
    public function updateOrderStatus($idOrder){
        global $database;

        $orderUpdated = 0;

        $sqlStatuses = "SELECT
                            SUM(IF(rop.status = 'end-of-life', 1, 0)) as endOfLife,
                            SUM(IF(rop.status = 'processing', 1, 0)) as processing,
                            SUM(IF(rop.status ='production', 1, 0)) as production,
                            COUNT(rop.idPackage) as totalPackages
                        FROM ".TABLES['rel_order_packages']." rop
                        WHERE rop.idOrder=$idOrder
                        GROUP BY rop.idOrder";
        $queryStatuses = $database->query($sqlStatuses);
        $packageStatuses = $database->fetchArray($queryStatuses);
        $status = $this->getOrderStatusBasedOnPackages($packageStatuses);

        if($status === 'in-progress'){
            $sqlUpdateOrder = "UPDATE ".TABLES['orders']."
                            SET status='$status'
                            WHERE id=$idOrder";
            $query = $database->query($sqlUpdateOrder);
            $orderUpdated = $database->affectedRows();
        }else if($status === 'production' || $status === 'end-of-life'){
            $deliveryDate = date("Y-m-d H:i:s");
            $sqlUpdateOrder = "UPDATE ".TABLES['orders']."
                            SET status='$status',
                            deliveryDate=CASE WHEN deliveryDate IS NULL THEN '$deliveryDate' ELSE deliveryDate END
                            WHERE id=$idOrder";
            $query = $database->query($sqlUpdateOrder);
            $orderUpdated = $database->affectedRows();
        }

        return [
            'orderUpdated' => $orderUpdated,
            'status' => $status
        ];
    }

    /**
     * get package and process names
     * @param  Int $idProcess the id of the process
     * @param  Int $idPackage the id of the package
     * @return Array          package and process names
     */
    private function getProcessAndPackageName($idProcess, $idPackage) {
        global $database;

		if(!$idPackage){
			return [];
		}

        $sql = "
                SELECT
                  pack.name AS packageName,
                  proc.name AS processName
                FROM
                  ".TABLES['packages']." pack
                  INNER JOIN ".TABLES['processes']." proc
                    ON proc.id = $idProcess
                WHERE pack.id = $idPackage";

        return $database->fetchResultArray($sql)[0];
    }

    /**
     * returns the previous and current process step for given order and package
     * @param  Int $idProcess id of the process
     * @param  Int $idPackage id of the package
     * @param  Int $idOrder   id of the order
     * @return Array          array with current and previous steps of the order
     */
    private function getPreviousAndCurrentSteps($idProcess, $idOrder) {
        global $database;
        $data = [
            'currentStep' => '',
            'prevStep' => ''
        ];

        $sql = "
                SELECT
                  ps.shortDesc,
                  rops.status
                FROM
                  ".TABLES['process_step']." ps
                  INNER JOIN ".TABLES['rel_process_steps']." rps
                    ON rps.idStep = ps.id
                  INNER JOIN
                    (SELECT
                      MAX(processInstance) AS processInstance
                    FROM
                      ".TABLES['rel_process_steps']."
                    WHERE idProcess = $idProcess) max_instance
                    ON rps.processInstance = max_instance.processInstance
                  INNER JOIN ".TABLES['rel_order_process_step']." rops
                    ON rops.idProcessStep = rps.id
                    AND rops.idOrder = $idOrder
                    AND rops.status = 'in-progress'
                WHERE ps.isVisibleForCustomer = 1
                UNION
                SELECT
                  ps.shortDesc,
                  rops.status
                FROM
                  ".TABLES['process_step']." ps
                  INNER JOIN ".TABLES['rel_process_steps']." rps
                    ON rps.idStep = ps.id
                  INNER JOIN
                    (SELECT
                      MAX(processInstance) AS processInstance
                    FROM
                      ".TABLES['rel_process_steps']."
                    WHERE idProcess = $idProcess) max_instance
                    ON rps.processInstance = max_instance.processInstance
                  INNER JOIN ".TABLES['rel_order_process_step']." rops
                    ON rops.idProcessStep = rps.id
                    AND rops.idOrder = $idOrder
                    AND rops.status = 'done'
                  INNER JOIN
                    (SELECT
                      idParent
                    FROM
                      ".TABLES['rel_process_steps']." rps_progress
                      INNER JOIN ".TABLES['rel_order_process_step']." rops_progress
                        ON rops_progress.idProcessStep = rps_progress.id
                        AND rops_progress.idOrder = $idOrder
                        AND rops_progress.status = 'in-progress') progress_parent
                    ON progress_parent.idParent = rps.id
                WHERE ps.isVisibleForCustomer = 1
        ";
        $result = $database->fetchResultArray($sql);

        if(count($result) > 0) {
			foreach($result as $stepDetails) {
				if($stepDetails['status'] === 'in-progress') {
					$data['currentStep'] = $stepDetails['shortDesc'];
				}
				if($stepDetails['status'] === 'done') {
					$data['prevStep'] = $stepDetails['shortDesc'];
				}
			}
        }

        return $data;
    }

    /**
     * returns the last process step for given order and package
     * @param  Int $idProcess id of the process
     * @param  Int $idOrder   id of the order
     * @return Array          array with last step completed of the order
     */
    private function getLastStepOrderCompleted($idProcess, $idOrder) {
        global $database;
        $data = [];

        $sql = "
                SELECT
                  ps.shortDesc AS shortDesc,
                  rops.status AS status,
                  ps.isVisibleForCustomer AS isVisibleForCustomer
                FROM
                  ".TABLES['process_step']." ps
                  INNER JOIN ".TABLES['rel_process_steps']." rps
                    ON rps.idStep = ps.id
                  INNER JOIN
                    (SELECT
                      MAX(processInstance) AS processInstance,
                      MAX(id) AS id
                    FROM
                      ".TABLES['rel_process_steps']."
                    WHERE idProcess = $idProcess) max_instance
                    ON rps.processInstance = max_instance.processInstance
                    AND rps.id = max_instance.id
                  INNER JOIN ".TABLES['rel_order_process_step']." rops
                    ON rops.idProcessStep = rps.id
                    AND rops.idOrder = $idOrder
                    AND rops.status = 'done'
        ";

        $result = $database->fetchResultArray($sql);

        if(count($result) > 0) {
            $data['prevStep'] = [
                'description' => $result[0]['shortDesc'],
                'isVisibleForCustomer' => $result[0]['isVisibleForCustomer']
            ];
        }

        return $data;
    }

    /**
     * checks parameters and sends mail based on the action made
     * @param  String $mailType            the action for which to send the mail
     * @param  Json string $orderData      the details regarding the order for which to send the mail
     * @return Array                       confirmation message
     */
    public function sendConfirmationMail($mailType, $orderData) {
        global $database, $user;
        $mailType = $database->escapeValue($mailType);
        $orderHelper = new OrderHelper();

        $commentMessage = array_key_exists('commentMessage', $orderData) ? $orderData['commentMessage'] : '';
        foreach($orderData as $orderKey => $orderDetail) {
            $orderData[$orderKey] = $database->escapeValue($orderDetail);
        }

        $data = [];
        $idOrder = array_key_exists('idOrder', $orderData) ? $orderData['idOrder'] : 0;
        $orderNumber = array_key_exists('orderNumber', $orderData) ? $orderData['orderNumber'] : $orderHelper->getOrderNumberById($idOrder);

        if(!$mailType) {
            return [
                'code' => 'error',
                'message' => 'ACTION_NOT_SET'
            ];
        }

        if(count($orderData) < 1) {
            return [
                'code' => 'error',
                'message' => 'ORDER_DATA_NOT_SET'
            ];
        }

        if(!$idOrder) {
            return [
                'code' => 'error',
                'message' => 'ID_ORDER_NOT_SET'
            ];
        }

        if(!$orderNumber) {
            return [
                'code' => 'error',
                'message' => 'ORDER_NUMBER_NOT_SET'
            ];
        }

        if(!array_key_exists('customer', $orderData) || !array_key_exists('commercialLead', $orderData)) {
            $customerCLNames = $orderHelper->getCustomerAndCLNamesFromOrder($idOrder);
            $orderData['customer'] = $customerCLNames['customerName'];
            $orderData['commercialLead'] = $customerCLNames['commercialLeadName'];
        }

        $idPackage = array_key_exists('idPackage', $orderData) ? $orderData['idPackage'] : 0;
        $idProcess = array_key_exists('idProcess', $orderData) && $orderData['idProcess'] ? $orderData['idProcess'] : $orderHelper->getIdProcessSelectedForPackageOrder($idOrder, $idPackage);
        $orderData['orderNumber'] = $orderNumber;

		$names = $this->getProcessAndPackageName($idProcess, $idPackage);
		$orderData['processName'] = array_key_exists('processName', $names) ? $names['processName'] : '';
		$orderData['packageName'] = array_key_exists('packageName', $names) ? $names['packageName'] : '';

        $currentDate = new DateTime();
        $currentDate = $currentDate->format('d-m-Y H:i');

         $params = [
             'apiOrderUrl' => WIAAS_URL.'/api-wiaas/orders?subModule=orders_steps&idOrder='.$idOrder.'&orderNumber='.$orderNumber,
             'orderUrl' => WIAAS_URL.'/orders/'.$idOrder,
             'mailType' => $mailType,
             'currentDate' => $currentDate,
             'idOrder' => $idOrder,
             'orderNumber' => $orderNumber,
             'processName' => $orderData['processName'],
             'packageName' => $orderData['packageName']
         ];

         $mailAddresses = $orderHelper->getCLAndCustomerMails($orderData['customer'], $orderData['commercialLead']);

        switch($mailType) {
            case 'processAssigned':
                $mailTitle = "Process assigned for order $orderNumber ($currentDate)";
                break;
            case 'orderStepUpdated':
                $mailTitle = "Order $orderNumber updated ($currentDate)";
                $steps = $this->getPreviousAndCurrentSteps($idProcess, $idOrder);
                $params['currentStepMessage'] = $steps['currentStep'] ?
                                                "<b>".$steps['currentStep']."</b> is currently in progress.<br />" :
                                                '';
                $params['prevStepMessage'] = $steps['prevStep'] ?
                                            "The step <b>".$steps['prevStep']."</b> has been completed successfully.<br />" :
                                            '';
                break;
            case 'lastStepCompleted':
                $mailTitle = "Order $orderNumber is successfully completed ($currentDate)";
                $lastStep = $this->getLastStepOrderCompleted($idProcess, $idOrder);
                $params['prevStepMessage'] = $lastStep['prevStep']['isVisibleForCustomer'] === '1' ?
                                                "The step <b>".$lastStep['prevStep']['description']."</b> has been done.<br />" :
                                                '';
                break;
            case 'packageStatusChanged':
                $mailTitle = "Order's $orderNumber package status updated ($currentDate)";
                $params['status'] = $orderData['status'];
				$params['deliveryEstimationDateMessage'] =  array_key_exists('estimatedDate', $orderData) ?
                                                            "The estimated date to complete the step is <b>".$orderData['estimatedDate']."</b>. <br />" :
                                                            '';
                break;
            case 'scheduleMeeting':
                $mailTitle = "Follow-up meeting date updated for order $orderNumber ($currentDate)";
                $mailAddresses = $orderHelper->getCLAndCustomerMails($orderData['customer'], $orderData['commercialLead'], 1);
                $params['estimatedDateMessage'] =  array_key_exists('estimatedMeetingDate', $orderData) ?
                                                    "The estimated date set for the follow-up meeting is <b>".$orderData['estimatedMeetingDate']."</b>. <br />" :
                                                    '';
                $params['confirmedDateMessage'] =  array_key_exists('confirmedMeetingDate', $orderData) ?
                                                    "The confimed date set for the follow-up meeting is <b>".$orderData['confirmedMeetingDate']."</b>. <br />" :
                                                    '';
                break;
            case 'orderStatusChanged':
                $mailTitle = "Order $orderNumber changed it's status to ".$orderData['status']. " ($currentDate)";
                $params['status'] = $orderData['status'];
                $params['deliveryEstimationDateMessage'] =  array_key_exists('estimatedDate', $orderData) ?
                                                            "The estimated delivery date for the order is <b>".$orderData['estimatedDate']."</b>. <br />" :
                                                            '';
                break;
            case 'orderCommentAdded':
                if(array_key_exists('isStepComment', $orderData)) {
                    $mailTitle = "New comment for step in order $orderNumber ($currentDate)";
                    $mailAddresses = $orderHelper->getCLAndCustomerMails('', $orderData['commercialLead'], 1);
                } else {
                    $mailTitle = "New comment for order $orderNumber ($currentDate)";
                    $mailAddresses = $orderHelper->getCLAndCustomerMails($orderData['customer'], $orderData['commercialLead'], 1);
                }
                $params['commentMessage'] = $commentMessage;
                $params['userLoggedIn'] = $user->getUserFullName();
                break;
            default:
                return $data;
        }

        return UtilsModel::sendOrderUpdateMail($mailType, $params, $mailTitle, $mailAddresses);
    }

    /**
     * get comments for all oreder steps
     * @param  INT $idOrder id of the order
     * @return Array          list of comments for an order grouped by idPackage and idProcessStep
     */
    private function getStepsComments($idOrder){
        global $database, $user;

        $extraFields = '';
        $whereSql = '';
        $userType = $user->getUserType();
        if($userType === USER_TYPES['BROKER']){
            $extraFields = ",rsc.isVisible ";
        }else{
            $whereSql = " AND rsc.isVisible=1";
        }

        $sql = "SELECT rsc.id, rsc.idProcessStep,
                    rsc.comment,
                    rsc.addDate,
                    u.username as user
                    $extraFields
                FROM ".TABLES['rel_step_comments']." rsc
                INNER JOIN ".TABLES['users']." u
                    ON u.id=rsc.idUser
                WHERE rsc.idOrder=$idOrder
                    AND rsc.type = 'stepComment'
                    $whereSql";
        $comments = [];
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $idProcessStep = $row['idProcessStep'];
            unset($row['idProcessStep']);
            $comments[$idProcessStep][] = $row;
        }

        return $comments;
    }

    /**
     * get all steps for an order
     * @param  INT $idOrder id of the order
     * @return Array        list of steps for an order grouped by process and package
     */
    public function getOrderSteps($idOrder){
        global $database, $user;
        $userType = $user->getUserType();
        $extraWhereClause = '';
        $extraJoin = '';
        $orderHelper = new OrderHelper();

        if(!$orderHelper->checkOrderOwner($idOrder)){
            return [];
        }

        if($userType === USER_TYPES['CUSTOMER']) {
            $extraWhereClause = " AND ps.isVisibleForCustomer = 1";
        }

        if($userType === USER_TYPES['SUPPLIER']) {
            $extraJoin = " INNER JOIN(
                            SELECT DISTINCT rop.idOrder, rop.idPackage
                                FROM ".TABLES['rel_order_packages']." rop
                            INNER JOIN ".TABLES['rel_package_products']." rpp
                                ON rpp.idPackage=rop.idPackage and rpp.packageInstance=rpp.packageInstance
                            INNER JOIN ".TABLES['suppliers_countries_products']." scp
                                ON scp.idProduct=rpp.idProduct
                            INNER JOIN ".TABLES['suppliers']." s
                                ON s.id=scp.idSupplier
                            WHERE s.idUSer=".$user->getUserId()." AND rop.idOrder=$idOrder
                            ) supplierPkg
                            ON rops.idOrder=supplierPkg.idOrder AND rops.idPackage=supplierPkg.idPackage";
        }

        $comments = $this->getStepsComments($idOrder);

        $sql = "SELECT o.id AS idOrder,
                    ps.shortDesc,
                    ps.fullDesc,
                    ps.isVisibleForCustomer,
                    psa.actionCode,
                    psa.stepType,
                    rops.idProcessStep,
                    rops.status,
                    rops.actualDate,
                    rps.idProcess,
                    p.name AS processName
                FROM ".TABLES['rel_order_process_step']." rops
                INNER JOIN ".TABLES['orders']." o
                    ON o.id=rops.idOrder
                INNER JOIN ".TABLES['rel_process_steps']." rps
                    ON rps.id=rops.idProcessStep
                INNER JOIN ".TABLES['processes']." p
                    ON p.id=rps.idProcess
                INNER JOIN ".TABLES['process_step']." ps
                    ON ps.id=rps.idStep
                INNER JOIN ".TABLES['process_step_actions']." psa
                    ON psa.id=ps.idActionCode
                $extraJoin
                WHERE o.id=".$idOrder."
                    $extraWhereClause
                ORDER BY rps.idProcess, rops.idProcessStep
                ";
        $query = $database->query($sql);
        $data = [];
        while($row = $database->fetchArray($query)){
            $idProcess = $row['idProcess'];
            $data[$idProcess]['idProcess'] = $row['idProcess'];
            $data[$idProcess]['processName'] = $row['processName'];
            unset($row['processName']);
            $row['comments'] = isset($comments[$row['idProcessStep']]) ? $comments[$row['idProcessStep']] : [];
            $row['isNewCommentVisible'] = $row['isVisibleForCustomer'];
            $data[$idProcess]['steps'][] = $row;
        }

        return $data;
    }

    /**
     * Update the actual date for an order
     * @param  Int $idOrder        Id of the order to be modified
     * @param  Int $idProcessStep  id of the porcess to be modified
     * @param  String $actualDate new date to be added for an order actual date step completed
     * @return array                 resopnese message for the update
     */
    public function updateStepActualDate($idOrder, $idProcessStep, $actualDate, $ordersDetailsMail) {
        global $database;

        $data = [];
        $idOrder = $database->escapeValue($idOrder);
        $idProcessStep = $database->escapeValue($idProcessStep);
        $actualDate = $database->escapeValue($actualDate);
        $ordersDetailsMail = (array) json_decode($ordersDetailsMail);
        $orderProcessHelper = new OrderProcessHelper();

        $checkDate = $database->invalidDate('ACTUAL_DATE_INCORRECT', $actualDate);
        if($checkDate){
            $data['messages'][] = $checkDate;
            return $data;
        }

        $sql = "UPDATE ".TABLES['rel_order_process_step']."
                SET actualDate='$actualDate'
                WHERE idOrder=$idOrder AND idProcessStep=$idProcessStep
                LIMIT 1";
        $query = $database->query($sql);

        if(!$query){
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;
        }

        if($database->affectedRows() === 1){
            $message = [
                'code' => 'success',
                'message' => 'ORDER_STEP_ACTUAL_DATE_UPDATED'
            ];
            $data['messages'][] = $message;

            $sqlProcessStep = "
                SELECT ps.shortDesc
                    FROM ".TABLES['process_step']." ps
                INNER JOIN ".TABLES['rel_process_steps']." rps
                   ON rps.idStep = ps.id
                   AND rps.id = $idProcessStep
                LIMIT 1
            ";
            $result = $database->fetchResultArray($sqlProcessStep);
            $procStep = $result ? $result[0]['shortDesc'] : '';

            $ordersDetailsMail['status'] = 'actual date set for step "'.$procStep.'"';
            $ordersDetailsMail['actualDate'] = $actualDate;
            $data['messages'][] = $orderProcessHelper->sendConfirmationMail('packageStatusChanged', $ordersDetailsMail);
        }

        return $data;
    }

    /**
     * update commnet for a step
     * @param  int $idOrder       id of the order
     * @param  int $idProcessStep process step id
     * @param  String $comment       comment
     * @return arary               messages array
     */
    public function updateStepComment($idOrder, $idProcessStep, $comment, $isVisible, $ordersDetailsMail) {
        global $database, $user;

        $data = [];
        $idOrder = $database->escapeValue($idOrder);
        $idProcessStep = $database->escapeValue($idProcessStep);
        $comment = $database->escapeValue($comment);
        $isVisible = $database->escapeValue($isVisible);
        $idUser = $user->getUserId();
        $ordersDetailsMail = (array) json_decode($ordersDetailsMail);
        $orderProcessHelper = new OrderProcessHelper();

        $checkMessage = $database->invalidLength('COMMENT_LONG',$comment, 700);
        if($checkMessage){
            $data['messages'][] = $checkMessage;

            return $data;
        }

        $sql = "INSERT INTO ".TABLES['rel_step_comments']."
                (idProcessStep, idOrder, idUser, comment, isVisible)
                VALUES ($idProcessStep, $idOrder, $idUser, '$comment', $isVisible)";
        $query = $database->query($sql);

        if(!$query){
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;
        }

        if($database->affectedRows() === 1){
            $message = [
                'code' => 'success',
                'message' => 'ORDER_STEP_COMMENT_UPDATED'
            ];
            $data['messages'][] = $message;

            if($isVisible) {
                $ordersDetailsMail['commentMessage'] = $comment;
                $ordersDetailsMail['isStepComment'] = true;
                $data['messages'][] = $orderProcessHelper->sendConfirmationMail('orderCommentAdded', $ordersDetailsMail);
            }
        }

        return $data;
    }

    /**
     * update the visibility for a comment
     * @param  INT  $idComment id of the comment
     * @param  boolean $isVisible visibility for the step
     * @return Array             update message
     */
    public function updateStepCommentVisibility($idComment, $isVisible){
        global $database;

        $data = [];
        $idComment = $database->escapeValue($idComment);
        $isVisible = $database->escapeValue($isVisible);

        $sql = "UPDATE ".TABLES['rel_step_comments']."
                SET isVisible=$isVisible
                WHERE id=$idComment
                LIMIT 1";
        $query = $database->query($sql);

        if(!$query){
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;
        }

        if($database->affectedRows() === 1){
            $message = [
                'code' => 'success',
                'message' => 'ORDER_STEP_COMMENT_UPDATED'
            ];
            $data['messages'][] = $message;
        }

        return $data;
    }

    private function updateOrderPackagseStatus($idOrder){
        global $database;

        $packageUpdated = 0;
        $sqlRemaningSteps = "SELECT COUNT(rops.idProcessStep) as remainingSteps
                            FROM ".TABLES['rel_order_process_step']." rops
                            WHERE rops.idOrder=$idOrder and rops.status!='done'";
        $queryRemaining = $database->query($sqlRemaningSteps);
        $rowsRemaining = $database->fetchArray($queryRemaining);

        if(intval($rowsRemaining['remainingSteps']) === 0){
            $sqlPayTerm = "SELECT pt.packagePayPeriod,
                                pt.servicesContractPeriod
                           FROM ".TABLES['payment_types']." pt
                           INNER JOIN ".TABLES['rel_order_packages']." rop
                           ON rop.idPaymentTerm=pt.id
                           WHERE rop.idOrder=$idOrder
                           LIMIT 1";
            $queryPayTerm = $database->query($sqlPayTerm);
            while($payTerm = $database->fetchArray($queryPayTerm)){
                $packagePayTerm = intval($payTerm['packagePayPeriod'], 10);
                $servicesPayTerm = intval($payTerm['servicesContractPeriod'], 10);
                $maxPeriod = max($packagePayTerm, $servicesPayTerm);
                $deliveryDate = date("Y-m-d H:i:s");


                $status = 'production';
                $endOfLife = "DATE_ADD('$deliveryDate', INTERVAL $maxPeriod MONTH)";

                $sql = "UPDATE ".TABLES['rel_order_packages']."
                        SET status='$status', endOfLife=$endOfLife
                        WHERE idOrder=$idOrder";
                $query = $database->query($sql);
                $packageUpdated = $database->affectedRows($query);
            }
        }

        return $packageUpdated;
    }

    public function goToNextStep($idOrder, $idProcessStep, $ordersDetailsMail){
        global $database;

        $idOrder = $database->escapeValue($idOrder);
        $idProcessStep = $database->escapeValue($idProcessStep);
        $ordersDetailsMail = (array) json_decode($ordersDetailsMail);
        $orderProcessHelper = new OrderProcessHelper();
        $orderActions = new OrderActions();

        $err_mes = [
            'code' => 'error',
            'message' => 'SERVER_ERROR'
        ];
        $data['messages'][] = $err_mes;
        $childSteps = $orderActions->getStepChilds($idProcessStep);
        $stepsStatusUpdated = $orderActions->updateActiveStep($idOrder, $idProcessStep, $childSteps);
        //in case automated steps are available code goes here

        if($stepsStatusUpdated > 0){
            $data['messages'][0] = [
                'code' => 'success',
                'message' => 'ACTIVE_STEP_UPDATE'
            ];
            $data['messages'][] = [
                'code' => 'success',
                'message' => 'NEW_STEP_ACTIVATED'
            ];
            $data['updated_active'] = $stepsStatusUpdated;
            if(empty($childSteps)) {
                $data['messages'][] = $orderProcessHelper->sendConfirmationMail('lastStepCompleted', $ordersDetailsMail);
            } else {
                $data['messages'][] = $orderProcessHelper->sendConfirmationMail('orderStepUpdated', $ordersDetailsMail);
            }
        }

        $packageStatusUpdated = $this->updateOrderPackagseStatus($idOrder);
        $orderStatusUpdated =  $orderProcessHelper->updateOrderStatus($idOrder);

        if($orderStatusUpdated['orderUpdated'] > 0) {
            $message = [
                'code' => 'success',
                'message' => 'ORDER_UPDATED'
            ];
            $data['messages'][] = $message;
            $data['order'] = $orderStatusUpdated['orderUpdated'];

            $data['sendMail'] = [
                'message' => 'orderStatusChanged',
                'status' => $orderStatusUpdated['status']
            ];
        }

        return $data;
    }

    /**
     * undo a step
     * @param  INT $idOrder       id for the order
     * @param  INT $idProcessStep id for the process step
     * @return Array              update message
     */
    public function undoStep($idOrder, $idProcessStep){
        $orderActions = new OrderActions();

        $stepsStatusUpdated = $orderActions->undoStep($idOrder, $idProcessStep);

        if($stepsStatusUpdated > 0){
            $data['messages'][0] = [
                'code' => 'success',
                'message' => 'ACTIVE_STEP_UNDONE'
            ];

            $customerInfo = UtilsModel::getDataForMailToCustomer($idOrder);
            $currentDate = new DateTime();
            $currentDate = $currentDate->format('d-m-Y H:i');
            $stepDetails = $this->getProcessStepDetailsById($idProcessStep);
            if(array_key_exists('isVisibleForCustomer', $stepDetails) && intval($stepDetails['isVisibleForCustomer']) === 1) {
                $params = [
                    'orderUrl' => WIAAS_URL.'/orders/'.$idOrder,
                    'orderNumber' => $customerInfo['orderNumber'],
                    'processStepName' => $stepDetails['shortDesc'],
                    'currentDate' => $currentDate
                ];

                $response = Mail::sendMail($customerInfo['mail'], 'Process step reopened', 'undoStepTemplate.php', $params);

                if($response){
                    $data['messages'][] = [
                        'code' => 'success',
                        'message' => 'ORDER_UPDATE_MAIL_SENT'
                    ];
                } else {
                    $data['messages'][] = [
                        'code' => 'error',
                        'message' => 'ERROR_MAIL_SENT'
                    ];
                }
            }
        }else{
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;
        }

        return $data;
    }

    /**
     * get process step name and if is visible to customer based on the id
     * @param  INT $idProcessStep    the id of the process step
     * @return String                the name of the process step
     */
    public function getProcessStepDetailsById($idProcessStep) {
        global $database;

        $sqlProcessStep = "SELECT
                              ps.shortDesc,
                              ps.isVisibleForCustomer
                            FROM
                              ".TABLES['process_step']." ps
                              INNER JOIN ".TABLES['rel_process_steps']." rps
                                ON rps.idStep = ps.id
                              INNER JOIN
                                (SELECT
                                  idParent
                                FROM
                                  ".TABLES['rel_process_steps']."
                                WHERE id = $idProcessStep) parentProcess
                                ON rps.id = parentProcess.idParent
                            LIMIT 1";
        $result = $database->fetchResultArray($sqlProcessStep);

        return $result && $result[0] ? $result[0] : [];
    }
}
