<?php

class InstallationScheduling {
    const ID_ADDITONAL_TYPE = 3;
    const CUSTOMER_ACCEPTANCE_DAYS_INTERVAL = 15;
    const ID_INSTALLATION_CATEGORY = 2;

    /**
     * get installation dates for each package in order
     * @param  INT $idOrder       id for the order
     * @param  INT $idPackage     id for the package
     * @return Array                array of installation dates
     */
    public function getInstallationDates($idOrder, $idPackage = 0){
        global $database, $user;
        $data = [];
        $idOrder = $database->escapeValue($idOrder);
        $idPackage = $database->escapeValue($idPackage);
        $extraWhere = '';

        if($idPackage) {
            $extraWhere = "AND ics.idPackage = $idPackage";
            $data[$idOrder . '-' . $idPackage] = [];
        }

        $sql = "
                SELECT
                  ics.idPackage,
                  isd.date,
                  isd.status,
                  isd.idUser,
                  isd.currentDate,
                  u.username,
                  ut.type AS userType
                FROM
                  ".TABLES['installation_schedule_dates']." isd
                  INNER JOIN ".TABLES['installation_company_selections']." ics
                    ON isd.idCompanySelection = ics.id
                  INNER JOIN ".TABLES['users']." u
                    ON u.id = isd.idUser
                  INNER JOIN ".TABLES['rel_user_type']." rut
                    ON rut.idUser = u.id
                  INNER JOIN ".TABLES['user_types']." ut
                    ON ut.id = rut.idType
                WHERE ics.idOrder = $idOrder
                   $extraWhere
                   AND ics.isActive = 1
                ORDER BY isd.date, isd.currentDate
        ";
        $result = $database->query($sql);
        while($row = $database->fetchArray($result)) {
            $orderPackagePair = $idOrder . '-' . $row['idPackage'];
            $data[$orderPackagePair][$row['date']]['isProposedByMe'] = intval($row['idUser']) === intval($user->getUserId());
            unset($row['idUser']);
            $data[$orderPackagePair][$row['date']]['details'][] = $row;
            $data[$orderPackagePair][$row['date']]['lastStatus'] = $row['status'];
        }

        return ['confirmationDates' => $data];
    }

    /**
     * get all installation companies for the order selected
     * @param  Int $idOrder   id of the order
     * @return Array          array with all the installation companies
     */
    public function getInstallCompaniesForOrder($idOrder) {
        global $database, $user;

        $idOrder = $database->escapeValue($idOrder);
        $availableCompanies = [];
        $installationSelectedArray = [];
        $installationSelected = [];
        $isMyInstallationCompany = [];
        $extraWhere = '';
        $extraJoin = '';

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

        if($user->getUserType() === USER_TYPES['SUPPLIER']) {
            $extraWhere = "AND u.id = ".$user->getUserId();
            $extraJoin = "INNER JOIN ".TABLES['installation_company_selections']." ics
                            ON ics.idProduct = rpp.idProduct
                            AND ics.idPackage = rpp.idPackage
                            AND ics.idOrder = rop.idOrder
                            AND ics.isActive = 1";
        }

        $sql = "
                SELECT
                  os.idPackage,
                  scp.idProduct AS id,
                  scp.idSupplier,
                  scp.productName AS name
                FROM
                  ".TABLES['order_selections']." os
                  INNER JOIN ".TABLES['suppliers_countries_products']." scp
                    ON scp.idProduct = os.idProduct
                  INNER JOIN ".TABLES['suppliers']." s
                    ON s.id = scp.idSupplier
                  INNER JOIN ".TABLES['users']." u
                    ON u.id = s.idUser
                WHERE os.idOrder = $idOrder
                  AND os.selectionFor = 'installation'
                  $extraWhere
        ";
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)) {
            $installationSelectedArray[$idOrder . '-' . $row['idPackage']][] = $row;
        }

        foreach ($installationSelectedArray as $orderPackagePair => $installInfo) {
            if(count($installInfo) > 0) {
                $installationSelected[$orderPackagePair] = $installInfo[0];
                $isMyInstallationCompany[$orderPackagePair] = true;
            } else {
                $isMyInstallationCompany[$orderPackagePair] = false;
            }
        }

        $sql = "
                SELECT
                  rpp.idPackage,
                  scp.idProduct AS id,
                  scp.idSupplier,
                  scp.productName AS name
                FROM
                  ".TABLES['rel_package_products']." rpp
                  INNER JOIN ".TABLES['rel_order_packages']." rop
                    ON rop.idPackage = rpp.idPackage
                    AND rpp.packageInstance = rop.packageInstance
                  INNER JOIN ".TABLES['suppliers_countries_products']." scp
                    ON scp.idProduct = rpp.idProduct
                  INNER JOIN ".TABLES['product_categories']." pc
                    ON pc.id = scp.idProductCategory
                  INNER JOIN ".TABLES['product_types']." pt
                    ON pt.id = pc.idType
                  INNER JOIN ".TABLES['suppliers']." s
                    ON s.id = scp.idSupplier
                  INNER JOIN ".TABLES['users']." u
                    ON u.id = s.idUser
                    $extraJoin
                WHERE pt.type = 'installation'
                    AND rop.idOrder = $idOrder
                    $extraWhere
        ";
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)) {
            $availableCompanies[$idOrder . '-' . $row['idPackage']][] = $row;
        }

        foreach ($availableCompanies as $orderPackagePair => $installInfo) {
            if(count($availableCompanies[$orderPackagePair]) === 1) {
                $installationSelected[$orderPackagePair] = $availableCompanies[$orderPackagePair][0];
                $message = self::changeInstallationCompany($idOrder, $installationSelected[$orderPackagePair]['idPackage'], $installationSelected[$orderPackagePair]['id']);
                if(array_key_exists($orderPackagePair, $isMyInstallationCompany) && !$isMyInstallationCompany[$orderPackagePair]) {
                    $isMyInstallationCompany[$orderPackagePair] = true;
                }
            } else {
                $isMyInstallationCompany[$orderPackagePair] = false;
            }
        }

        return [
            'available' => $availableCompanies,
            'selected' => $installationSelected,
            'isMyInstallationCompany' => $isMyInstallationCompany
        ];
    }

    /**
     * Update the estimation date for the installation
     * @param  Int $idOrder        Id of the order to be modified
     * @param  Int $idPackage      id of the package to be modified
     * @param  String $newDate     the date set by the user for the installation
     * @param  String $status      the status of the date to be added
     * @return array                 response message for the update
     */
    public function updateInstallationDate($idOrder, $idPackage, $newDate, $status) {
        global $database, $user;
        $idOrder = $database->escapeValue($idOrder);
        $idPackage = $database->escapeValue($idPackage);
        $newDate = $database->escapeValue($newDate);
        $status = $database->escapeValue($status);
        $data = [];
        $userType = $user->getUserType();
        $mailTitle = '';
        $templateUrl = '';
        $idOrderPackagePair = $idOrder . '-' . $idPackage;
        $ordersExtraActions = new orderExtraActions();

        if(!$status) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'STATUS_NOT_SET'
            ];

            return $data;
        }

        if($status === 'accept') {
            $status = 'accepted';
        } else if($status === 'decline'){
            $status = 'declined';
        }

        if(!$newDate) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'INSTALLATION_DATE_EMPTY'
            ];

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

            return $data;
        }

        $earliestInstallationDate = $this->getInstallationScheduleEID($idOrder);
        if(!$earliestInstallationDate[$idOrder]) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'EID_NOT_SET'
            ];

            return $data;
        }

        $idCompanySelection = $this->getActiveInstallationCompanyId($idOrder, $idPackage);
        if(!$idCompanySelection) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'RELATION_NOT_FOUND'
            ];

            return $data;
        }

        if($userType === USER_TYPES['CUSTOMER']) {
            $brokerMails = (array) UtilsModel::getBrokersMail();
            $supplierMail = (array) self::getSupplierMail($idCompanySelection);
            $mail = array_merge($brokerMails, $supplierMail);
        } else if($userType === USER_TYPES['SUPPLIER']){
            $mail = self::getCustomerMail($idOrder);
        } else {
            $customerMail = (array) self::getCustomerMail($idOrder);
            $supplierMail = (array) self::getSupplierMail($idCompanySelection);
            $mail = array_merge($customerMail, $supplierMail);
        }

        $mailDetails = [
            'idOrder' => $idOrder,
            'idCompanySelection' => $idCompanySelection,
            'orderNumber' => UtilsModel::getOrderNumberById($idOrder),
            'acceptedDate' => $newDate,
            'proposedDate' => $newDate,
            'actionDoneBy' => $user->getUserFullName(),
            'mail' => $mail
        ];

        if($status === 'proposed') {
            $mailTitle = 'New installation date proposed';
            $templateUrl = 'installationProposedTemplate.php';

            if($newDate < $earliestInstallationDate[$idOrder]) {
                $data['messages'][] = [
                    'code' => 'error',
                    'message' => 'PAST_DATE',
                    'key' => $earliestInstallationDate[$idOrder]
                ];

                return $data;
            }

            $sql = "
                    SELECT id
                        FROM ".TABLES['installation_schedule_dates']."
                    WHERE idCompanySelection = $idCompanySelection
                        AND date='$newDate' AND status='proposed'";
            $result = $database->query($sql);
            if($database->numRows($result) === 1) {
                $data['messages'][] = [
                    'code' => 'error',
                    'message' => 'PROPOSED_DATE_EXISTS'
                ];

                return $data;
            }

            if($userType === USER_TYPES['BROKER']) {
                $earliestInstallationDate = new DateTime($earliestInstallationDate);
                $maxSLAInstallDate = $earliestInstallationDate->add(new DateInterval('P'.ADDITIONAL_MAX_INSTALL_DAYS.'D'));
                $maxSLAInstallDate = $maxSLAInstallDate->format('Y-m-d');
                if($maxSLAInstallDate < $newDate) {
                    $data['messages'][] = [
                        'code' => 'warning',
                        'message' => 'MAX_SLA_EXCEEDED',
                        'key' => $maxSLAInstallDate
                    ];
                }
            }
        }

        $lastStatuses = $this->getInstallationDateLastStatus($idCompanySelection);

        if($status === 'accepted') {
            $mailTitle = 'Installation date accepted';
            $templateUrl = 'installationAcceptedTemplate.php';
            $isinstallationAccepted = $this->installationDateIsAlreadyAccepted($lastStatuses, $newDate, $idCompanySelection);

            if($isinstallationAccepted) {
                $message = [
                    'code' => 'success',
                    'message' => 'INSTALLATION_ALREADY_ACCEPTED'
                ];
            }

            $sql = "UPDATE ".TABLES['orders']."
                    SET acceptanceDueDate=DATE_ADD('$newDate', INTERVAL ".self::CUSTOMER_ACCEPTANCE_DAYS_INTERVAL." DAY)
                    WHERE id=$idOrder";
            $query = $database->query($sql);
        }

        $database->beginTransaction();
        $sql = "
            INSERT INTO ".TABLES['installation_schedule_dates']." (
                idCompanySelection,
                idUser,
                date,
                status
                )
            VALUES(
                    $idCompanySelection,
                    ".$user->getUserId().",
                    '$newDate',
                    '$status'
            )";
        $query = $database->query($sql);
        if($query){
            $database->commit();
            $message = [
                'code' => 'success',
                'message' => 'INSTALLATION_DATE_UPDATED'
            ];
        }else{
            $database->rollback();
            $message = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
        }
        $data['messages'][] = $message;

       if($status === 'declined') {
           $confirmationDates = $this->getInstallationDates($idOrder, $idPackage)['confirmationDates'][$idOrderPackagePair];

           if($confirmationDates) {
               if(count($confirmationDates) > 0) {
                  $allDatesDeclined = true;

                  forEach($confirmationDates as $date => $details) {
                      if($details['lastStatus'] !== 'declined') {
                          $allDatesDeclined = false;
                      }
                  }

                  if($allDatesDeclined) {
                      $mailTitle = 'Installation dates declined';
                      $templateUrl = 'installationDeclinedTemplate.php';
                  }
              }
          }
       }

       if($mailTitle && $templateUrl) {
           $data['messages'][] = self::sendInstallationSchedulingMail($mailDetails, $mailTitle, $templateUrl);
       }

        return $data;
    }

    /**
     * checks if an installation date is already accepted, and puts it in canceled state if so
     * @param  Array $lastStatuses        the last status for each date
     * @param  String $newDate            the date to be updated
     * @param  Int $idCompanySelected     id of the installation company selected
     * @return Boolean                    true or false if the installation date is accepted for the order package
     */
    private function installationDateIsAlreadyAccepted($lastStatuses, $newDate, $idCompanySelected) {
        global $database, $user;
        $dateCanceled = 0;

        foreach($lastStatuses as $installationDate => $lastStatus) {
            if($installationDate !== $newDate && $lastStatus === 'accepted') {
                $sql = "INSERT INTO ".TABLES['installation_schedule_dates']."
                        (idCompanySelection, idUser, date, status)
                        VALUES (
                            $idCompanySelected,
                            ".$user->getUserId().",
                            '$installationDate',
                            'canceled'
                            )
                ";
                $result = $database->query($sql);

                if($database->affectedRows()) {
                    $dateCanceled++;
                }
            }
        }

        return false;
    }

    /**
     * gets the lastest status of the earliest installation date for an order
     * @param  Int $idCompanySelected     the id of the insatllation company selected
     * @return String                     the latest status or empty string
     */
    private function getInstallationDateLastStatus($idCompanySelected) {
        global $database;
        $data = [];

        $sql = "
                SELECT
                  isd.date AS installationDate,
                  isd.status AS lastStatus
                FROM
                  ".TABLES['installation_schedule_dates']." isd
                  INNER JOIN
                    (SELECT
                      isdd.date AS installationDate,
                      MAX(isdd.currentDate) AS maxDate
                    FROM
                     ".TABLES['installation_schedule_dates']." isdd
                    WHERE isdd.idCompanySelection = $idCompanySelected
                    GROUP BY isdd.date) installations_max_dates
                    ON installations_max_dates.installationDate = isd.date
                    AND installations_max_dates.maxDate = isd.currentDate
                WHERE isd.idCompanySelection = $idCompanySelected
                ORDER BY isd.date";
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)) {
            $data[$row['installationDate']] = $row['lastStatus'];
        }

        return $data;
    }

    /**
     * returns the id of the installation company active for order and package
     * @param  Int $idOrder   id of the order
     * @param  Int $idPackage id of the package
     * @return Int            id of the relation
     */
    private function getActiveInstallationCompanyId($idOrder, $idPackage) {
        global $database;

        $sql = "
            SELECT
              ics.id AS selectionId
            FROM
              ".TABLES['installation_company_selections']." ics
            WHERE ics.idOrder = $idOrder AND ics.idPackage = $idPackage AND ics.isActive = 1";
        $data = $database->fetchResultArray($sql);

        if($data && $data[0]['selectionId']) {
            return $data[0]['selectionId'];
        }

        return 0;
    }

    /**
     * checks if all dates for the package are declined and sends a mail
     * @param  Int $idOrder             id of the order
     * @param  Int $idPackage           id of the package
     * @param  Int $idCompanySelection  id of the combination bwtween the order, package and installation company selected
     * @return Array                    confirmation message
     */
    private function checkIfAllDatesAreDeclined($idOrder, $idPackage, $idCompanySelection) {
        global $database;
        $idOrderPackage = $idOrder . '-' . $idPackage;
        $allDatesDeclined = true;

        $confirmationDates = $this->getInstallationDates($idOrder, $idPackage)['confirmationDates'];

        if($confirmationDates && array_key_exists($idOrderPackage, $confirmationDates)) {
            if(count($confirmationDates[$idOrderPackage]) === 0) {
                return;
            }

           forEach($confirmationDates[$idOrderPackage] as $date => $details) {
               if($details['lastStatus'] !== 'declined' && $details['lastStatus'] !== 'canceled') {
                   $allDatesDeclined = false;
               }
           }

           if($allDatesDeclined) {
               $mailTitle = APPLICATION_NAME.' installation dates declined';
               $templateUrl = 'installationDeclinedTemplate.php';

               $info = [
                   'idOrder' => $idOrder,
                   'idCompanySelection' => $idCompanySelection,
                   'orderNumber' => UtilsModel::getOrderNumberById($idOrder)
               ];

               return self::sendInstallationSchedulingMail($info, $mailTitle, $templateUrl);
           }
        }

        return;
    }

    /**
     * remove the date from the order package
     * @param  Int $idOrder          id of the order
     * @param  Int $idPackage        id of the package
     * @param  String $installationDate the installation date to be removed
     * @return Array                  confirmation messages
     */
    public function removeMyDate($idOrder, $idPackage, $installationDate) {
        global $database;
        $idOrder = $database->escapeValue($idOrder);
        $idPackage = $database->escapeValue($idPackage);
        $installationDate = $database->escapeValue($installationDate);

        if(!$installationDate) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'INSTALLATION_DATE_EMPTY'
            ];

            return $data;
        }
        $idCompanySelection = $this->getActiveInstallationCompanyId($idOrder, $idPackage);
        if(!$idCompanySelection) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'RELATION_NOT_FOUND'
            ];

            return $data;
        }
         $lastStatus = $this->getInstallationDateLastStatus($idCompanySelection);
         if($lastStatus[$installationDate] !== 'proposed') {
             $data['messages'][] = [
                 'code' => 'error',
                 'message' => 'INSTALLATION_DATE_NOT_REMOVED'
             ];

             return $data;
         }

         $sql = "
                 DELETE
                 FROM
                   ".TABLES['installation_schedule_dates']."
                 WHERE idCompanySelection = $idCompanySelection
                   AND date = '$installationDate'";

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

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

         return $data;
     }

     /**
      * send mail for installation scheduling functionality
      * @param  Array $info          array with all neccessary data about the order
      * @param  String $mailTitle    the title of the mail
      * @param  String $templateUrl the mail template to be sent
      * @return Array                update message
      */
     public function sendInstallationSchedulingMail($info, $mailTitle, $templateUrl) {
         global $user;
         $userType = $user->getUserType();
         $idOrder = array_key_exists('idOrder', $info) ? $info['idOrder'] : 0;
         $idCompanySelection = array_key_exists('idCompanySelection', $info) ? $info['idCompanySelection'] : 0;
         $orderNumber = array_key_exists('orderNumber', $info) ? $info['orderNumber'] : 0;
         $acceptedDate = array_key_exists('acceptedDate', $info) ? $info['acceptedDate'] : '';
         $proposedDate = array_key_exists('proposedDate', $info) ? $info['proposedDate'] : '';
         $actionDoneBy = array_key_exists('actionDoneBy', $info) ? $info['actionDoneBy'] : '-';

         if(array_key_exists('orderUrl', $info)) {
             $orderUrl = $info['orderUrl'];
         } else {
             $orderUrl = $userType === USER_TYPES['CUSTOMER'] ? WIAAS_URL.'/api-wiaas/orders?subModule=orders_steps&idOrder='.$idOrder.'&orderNumber='.$orderNumber : WIAAS_URL.'/'.$idOrder;
         }

         if(array_key_exists('mail', $info)) {
             $mail = $info['mail'];
         } else {
             if($userType === USER_TYPES['CUSTOMER']) {
                 $brokerMails = (array) self::getBrokersMail();
                 $supplierMail = (array) self::getSupplierMail($idCompanySelection);
                 $mail = array_merge($brokerMails, $supplierMail);
             } else {
                 $mail = self::getCustomerMail($idOrder);
             }
         }

         if($acceptedDate && $proposedDate) {
             $acceptedDate = new DateTime($acceptedDate);
             $acceptedDate = $acceptedDate->format('jS M, Y');
             $proposedDate = new DateTime($proposedDate);
             $proposedDate = $proposedDate->format('jS M, Y');
         }

         $params = [
             'wiaas' => $userType === USER_TYPES['CUSTOMER'] ? WIAAS_URL : WIAAS_URL.'/api-wiaas',
             'ordersUrl' => $orderUrl,
             'orderNumber' => $orderNumber,
             'acceptedDate' => $acceptedDate,
             'proposedDate' => $proposedDate,
             'actionDoneBy' => $actionDoneBy
         ];

         $response = Mail::sendMail($mail, $mailTitle, $templateUrl, $params);
         if($response){
             $message = [
                 'code' => 'success',
                 'message' => 'INSTALLATION_MAIL_SENT'
             ];
         } else {
             $message = [
                 'code' => 'error',
                 'message' => 'ERROR_MAIL_SENT'
             ];
         }

         return $message;
     }

     /**
      * get all installation data for order
      * @param  Int $idOrder      id of the order
      * @param  Array $stepIds    actions id of the steps between which the step should be enabled
      * @param  String $fileType  the type of the documents needed - Order Questionaire or Installation protocol
      * @return Array             array with all data needed for the installation scheduling
      */
     public function getAllDataForInstallation($idOrder, $stepIds, $fileType) {
         $data = [];
         $idPackage = 0;
         if(!$idOrder) {
             $data['messages'][] = [
                 'code' => 'error',
                 'message' => 'ID_ORDER_NOT_SET'
             ];

             return $data;
         }

         $data['installCompanies'] = $this->getInstallCompaniesForOrder($idOrder);
         $data['earliestInstallationDate'] = $this->getInstallationScheduleEID($idOrder);
         $data['isNextStepWanted'] = $this->checkIfIsNextStepWanted($idOrder, $idPackage, $stepIds);
         $data['installationDates'] = $this->getInstallationDates($idOrder, $idPackage);
         $data['areAllShippingDatesConfirmed'] = $this->checkIfAllShippingDatesConfirmed($idOrder);

         return $data;
     }

     /**
      * returns the id of the installation info
      * @param  Int $idOrder   id of the order
      * @param  Int $idPackage id of the package
      * @return Array or Int   error messages or id of the package
      */
     public function getInstallationScheduleEID($idOrder, $idPackage = 0) {
         global $database;
         $idOrder = $database->escapeValue($idOrder);
         $eid = '';
         $extraWhere = '';

         if(!$idOrder) {
             $eid['messages'][] = [
                 'code' => 'error',
                 'message' => 'ORDER_NOT_SET'
             ];

             return $eid;
         }

         $sql = "
                 SELECT
                 MAX(
                    IFNULL(earliestInstallationDate, '-')
                 ) AS earliestInstallationDate
                 FROM
                   ".TABLES['rel_order_packages']."
                 WHERE idOrder = $idOrder";

         $query = $database->query($sql);
         $eid[$idOrder] = $database->fetchArray($query)['earliestInstallationDate'];

        return $eid;
     }

     /**
     * checks if the next step is the one needed for enabling the component
     * @param  Int $idOrder   id of the order
     * @param  Int $idPackage id of the package
     * @param  Array $stepIds actions id of the steps between which the step should be enabled
     * @return bool           true if the next step should enable the component
     */
     public function checkIfIsNextStepWanted($idOrder, $idPackage, $stepIds = []) {
         global $database;
         $idOrder = $database->escapeValue($idOrder);
         $idPackage = $database->escapeValue($idPackage);
         $stepIds = (array) $stepIds;
         if(count($stepIds) === 0) {
             $stepIds = [
                 'firstStepEnabled' => 5,
                 'lastStepEnabled' => 6
             ];
         }
         $firstStepEnabled = $database->escapeValue($stepIds['firstStepEnabled']);
         $lastStepEnabled = $database->escapeValue($stepIds['lastStepEnabled']);
         $extraWhere = '';
         $data = [];
         $wantedPackageIds = [];

         if($idPackage) {
           $extraWhere = "AND rops.idPackage = $idPackage";
         }

         $sql = "
               SELECT
                 rops.idProcessStep
               FROM
                 ".TABLES['rel_order_process_step']." rops
                 INNER JOIN ".TABLES['rel_process_steps']." rps
                   ON rps.id = rops.idProcessStep
                 INNER JOIN ".TABLES['process_step']." ps
                   ON ps.id = rps.idStep
                   AND ps.idActionCode=$firstStepEnabled
               WHERE rops.idOrder = $idOrder
                 $extraWhere
                 AND rops.status = 'inactive'
               UNION ALL
               SELECT
                 rops.idProcessStep
               FROM
                 ".TABLES['rel_order_process_step']." rops
                 INNER JOIN ".TABLES['rel_process_steps']." rps
                   ON rps.id = rops.idProcessStep
                 INNER JOIN ".TABLES['process_step']." ps
                   ON ps.id = rps.idStep
                   AND ps.idActionCode=$lastStepEnabled
               WHERE rops.idOrder = $idOrder
                 $extraWhere
                 AND (
                   rops.status = 'in-progress'
                   OR rops.status = 'done'
                 )";
         $query = $database->query($sql);
         $data[$idOrder] = $database->numRows($query) > 0;

         return $data;
     }

     /**
      * check if all the delivery dates are confirmed
      * @param  Int $idOrder     the id of the order
      * @return Array            array with info if the shipping dates are confirmed or not
      */
     public function checkIfAllShippingDatesConfirmed($idOrder) {
         global $database;
         $idOrder = $database->escapeValue($idOrder);
         $data = [];

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

             return $data;
         }

         $sql = "SELECT
                  SUM(IF(rope.confirmedDate IS NULL, 0, 1)) AS nbOfDatesConfirmed,
                  COUNT(*) AS totalNbOfDates
                FROM
                  ".TABLES['rel_order_supplier_estimations']." rope
                WHERE rope.idOrder = $idOrder";
        $result = $database->query($sql);

        while($row = $database->fetchArray($result)) {
            $data[$idOrder] = $row['nbOfDatesConfirmed'] === $row['totalNbOfDates'];
        }

        return $data;
     }

     /**
      * return the mail of the supplier of the installation company
      * @param   Int     $idCompanySelection the id of the company selection (install company-order-package)
      * @return  Array   the email of the supplier for th installation company per order package
      */
     public function getSupplierMail($idCompanySelection) {
         global $database;

         $sql = "
                 SELECT
                   u.mail
                 FROM
                   ".TABLES['users']." u
                   INNER JOIN ".TABLES['suppliers']." s
                     ON s.idUser = u.id
                   INNER JOIN ".TABLES['suppliers_countries_products']." scp
                     ON scp.idSupplier = s.id
                   INNER JOIN ".TABLES['installation_company_selections']." ics
                     ON ics.idProduct = scp.idProduct
                     AND ics.id = $idCompanySelection";
         $mail = $database->fetchResultArray($sql);

         return count($mail) ? $mail[0]['mail'] : '';
     }

     /**
      * returns the customer mail for the order selected
      * @param  Int $idOrder  id of the order
      * @return Array
      */
     public function getCustomerMail($idOrder) {
         global $database;

         $sql = "
                 SELECT
                   u.mail
                 FROM
                   ".TABLES['users']." u
                   INNER JOIN ".TABLES['customers']." c
                     ON c.idUser = u.id
                   INNER JOIN ".TABLES['rel_commercial_lead_customers']." rclc
                     ON rclc.idCustomer = c.id
                   INNER JOIN ".TABLES['orders']." o
                     ON o.idCustomerInstance = rclc.id
                     AND o.id = $idOrder";
         $mail = $database->fetchResultArray($sql);

         return count($mail) ? $mail[0]['mail'] : '';
     }

     /**
      * send mail if scheduling is enabled for customer
      * @param  Int $idOrder      id of the order
      * @param  Int $idPackage    id of the package
      * @return Array
      */
     // the function is prepared for the future when we will have the other user types with the new interface as well
     public function checkIfSchedulingEnabledForCustomer($idOrder, $idPackage) {
         global $database;
         $idOrderPackagePair = $idOrder . '-' . $idPackage;
         $orderExtraActions = new orderExtraActions();
         $data = [];

         $installCompanySelected = $orderExtraActions->getInstallCompaniesForOrder($idOrder)['selected'];
         $earliestInstallationDate = $orderExtraActions->getInstallationScheduleEID($idOrder);
         $isNextStepWanted = $orderExtraActions->checkIfIsNextStepWanted($idOrder, $idPackage);

         if($earliestInstallationDate && $earliestInstallationDate[$idOrder] !== '-' &&
            $isNextStepWanted && array_key_exists($idOrderPackagePair, $isNextStepWanted) && $isNextStepWanted[$idOrderPackagePair] === false &&
            $installCompanySelected && array_key_exists($idOrderPackagePair, $installCompanySelected) && count($installCompanySelected[$idOrderPackagePair]) > 0) {

            $customerInfo = self::getDataForMailToCustomer($idOrder);

            $sqlPackageInfo = "
                             SELECT
                                 p.name AS packageName,
                                 s.name AS supplierName
                             FROM ".TABLES['packages']." p
                             INNER JOIN ".TABLES['rel_order_packages']." rop
                                 ON rop.idPackage = p.id
                                 AND rop.idOrder = $idOrder
                                 AND rop.idPackage = $idPackage
                             INNER JOIN ".TABLES['installation_company_selections']." ics
                                 ON ics.idOrder = rop.idOrder
                             INNER JOIN ".TABLES['suppliers_countries_products']." scp
                                 ON scp.idProduct = ics.idProduct
                             INNER JOIN ".TABLES['suppliers']." s
                                 ON s.id = scp.idSupplier";
            $query = $database->query($sqlPackageInfo);
            $packageInfo = $database->fetchArray($query);
            $params = [
                'wiaas' => WIAAS_URL,
                'ordersUrl' => WIAAS_URL.'/orders/'.$idOrder,
                'orderNumber' => $customerInfo['orderNumber'],
                'packageName' => $packageInfo['packageName'],
                'supplierName' => $packageInfo['supplierName']
            ];
            $response = Mail::sendMail($customerInfo['mail'], 'Schedule installation function is now enabled', 'customerScheduleInstallationEnabled.php', $params);

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

         return $data;
     }

     /**
      * change the installation company for the order and package selected
      * @param  Int $idOrder               id of the order
      * @param  Int $idPackage             id of the package
      * @param  Int $idInstallationCompany id of the installation company product
      * @return Array                      update messages
      */
     public function changeInstallationCompany($idOrder, $idPackage, $idInstallationCompany) {
         global $database;

         $idOrder = $database->escapeValue($idOrder);
         $idPackage = $database->escapeValue($idPackage);
         $idInstallationCompany = $database->escapeValue($idInstallationCompany);
         $rowsAffected = 0;

         $sqlSelectProduct = "
                 SELECT
                   ics.id AS idCompany
                 FROM
                   ".TABLES['installation_company_selections']." ics
                 WHERE ics.idOrder = $idOrder AND ics.idPackage = $idPackage";

         $data = $database->fetchResultArray($sqlSelectProduct);
         if(count($data)) {
             $idScheduleInfo = $data[0]['idCompany'];
             $sqlUpdateCompanyStatus = "
                     UPDATE
                       ".TABLES['installation_company_selections']."
                     SET
                       isActive = 0
                     WHERE idOrder = $idOrder AND idPackage = $idPackage";
             $query = $database->query($sqlUpdateCompanyStatus);
         }

         $sqlInsertUpdateCompany = "
                 INSERT INTO
                   ".TABLES['installation_company_selections']." (
                   idProduct,
                   idOrder,
                   idPackage
                 )
                 VALUES
                     ($idInstallationCompany, $idOrder, $idPackage)
                 ON DUPLICATE KEY UPDATE
                     isActive = 1";
         $result = $database->query($sqlInsertUpdateCompany);
         $rowsAffected += $database->affectedRows();

         if($rowsAffected) {
             return [
                 'code' => 'success',
                 'message' => 'INSTALLATION_SAVED'
             ];
         }

         return [
             'code' => 'error',
             'message' => 'INSTALLATION_NOT_SAVED'
         ];
     }

     /**
      * send mail if scheduling is enabled for customer
      * @param  Int $idOrder      id of the order
      * @param  Int $idPackage    id of the package
      * @return Array
      */
     public function sendMailIfSchedulingEnabledForCustomer($idOrder, $idPackage) {
         global $database;
         $data = [];
         $idOrderPackagePair = $idOrder . '-' . $idPackage;
         $stepsName = json_encode([
             'firstStepEnabled' => 5,
             'lastStepEnabled' => 6
         ]);
         $orderExtraActions = new orderExtraActions();
         $installationScheduling = new InstallationScheduling();

         $isSchedulingAlreadyEnabled = self::checkIfSchedulingAlreadyEnabledForCustomer($idOrder, $idPackage);
         if(!intval($isSchedulingAlreadyEnabled)) {
             $installCompanySelected = $installationScheduling->getInstallCompaniesForPackage($idOrder, $idPackage)['selected'];
             $earliestInstallationDate = self::getInstallationScheduleEID($idOrder);
             $isNextStepWanted = $orderExtraActions->checkIfIsNextStepWanted($idOrder, $idPackage, $stepsName);

             if($installCompanySelected && count($installCompanySelected) > 0 &&
                $earliestInstallationDate[$idOrder] &&
                $isNextStepWanted === false) {

                $message = self::setSchedulingFlagForCustomer($idOrder, $idPackage, 1);
                if($message['code'] === 'warning') {
                    return;
                }

                $customerInfo = self::getDataForMailToCustomer($idOrder);

                $sqlPackageInfo = "
                                 SELECT
                                     p.name AS packageName,
                                     s.name AS supplierName
                                 FROM ".TABLES['packages']." p
                                 INNER JOIN ".TABLES['rel_order_packages']." rop
                                     ON rop.idPackage = p.id
                                     AND rop.idOrder = $idOrder
                                     AND rop.idPackage = $idPackage
                                 INNER JOIN ".TABLES['installation_company_selections']." ics
                                     ON ics.idOrder = rop.idOrder
                                 INNER JOIN ".TABLES['suppliers_countries_products']." scp
                                     ON scp.idProduct = ics.idProduct
                                 INNER JOIN ".TABLES['suppliers']." s
                                     ON s.id = scp.idSupplier";
                $query = $database->query($sqlPackageInfo);
                $packageInfo = $database->fetchArray($query);
                $params = [
                    'wiaas' => WIAAS_URL,
                    'ordersUrl' => WIAAS_URL.'/orders/'.$idOrder,
                    'orderNumber' => $customerInfo['orderNumber'],
                    'packageName' => $packageInfo['packageName'],
                    'supplierName' => $packageInfo['supplierName']
                ];
                $response = Mail::sendMail($customerInfo['mail'], 'Schedule installation function is now enabled', 'customerScheduleInstallationEnabled.php', $params);

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

         return $data;
     }

     /**
      * check if the scheduling is already available for customer
      * @param  INT $idOrder    id of the order
      * @param  INT $idPackage  id of the package
      * @return Bool            1 if the scheduling is already enabled
      */
     public function checkIfSchedulingAlreadyEnabledForCustomer($idOrder, $idPackage) {
         global $database;
         $extraWhere = '';
         if($idPackage) {
             $extraWhere = " AND rop.idPackage = $idPackage";
         }

         $sql = "SELECT
                   rop.isSchedulingEnabledForCustomer
                 FROM
                   ".TABLES['rel_order_packages']." rop
                 WHERE rop.idOrder = $idOrder
                    $extraWhere";
         $result = $database->fetchResultArray($sql);

         return $result ? $result[0]['isSchedulingEnabledForCustomer'] : 0;
     }

     /**
      * sets the scheduling available or not available for customer
      * @param  INT $idOrder    id of the order
      * @param  INT $idPackage  id of the package
      * @return Bool            1 if the scheduling is already enabled
      */
     public function setSchedulingFlagForCustomer($idOrder, $idPackage, $flag) {
         global $database;
         $flag = intval($database->escapeValue($flag));
         $extraWhere = '';

         if($flag !== 0 && $flag !== 1) {
             return [
                 'code' => 'error',
                 'message' => 'FLAG_NOT_AVAILABLE'
             ];
         }

         if($idPackage) {
             $extraWhere = " AND idPackage = $idPackage";
         }

         $sql = "UPDATE
                   ".TABLES['rel_order_packages']."
                 SET
                   isSchedulingEnabledForCustomer = $flag
                 WHERE idOrder = $idOrder
                   $extraWhere";

         $result = $database->query($sql);
         $affectedRows = $database->affectedRows();

         if($affectedRows > 0) {
             return [
                 'code' => 'success',
                 'key' => $flag ? 'enabled' : 'disabled',
                 'message' => 'SCHEDULE_FLAG_UPDATED'
             ];
         }

         return [
             'code' => 'warning',
             'message' => 'SCHEDULE_FLAG_NO_UPDATE'
         ];
     }

 }
