<?php

class orderExtraActions {
    const DOCUMENT_TYPES = [
        'ID_QUESTIONAIRE_DOC_TYPE' => 2, // 2 => 'orderQuestionaire'
        'ID_CONFIGURATION_DOC_TYPE' => 3, // 3 => 'configuration'
        'ID_ACCEPTANCE_DOC_TYPE' => 5, // 5 => 'customerAcceptance'
        'ID_INSTALLATION_PROTOTCOL_DOC_TYPE' => 10 // 10 => 'installationProtocol'
    ];
    const ID_INSTALLATION_CATEGORY = 2;

    /**
     * upload a new file for configuration
     * @param  INT $idOrder    id for the order
     * @param  INT $idPackage  id for the package
     * @param  INT $idSupplier id for supplier
     * @param  STRING $fileType the type of the file (configuration or installation)
     * @param  FILE $file      file to be uploaded
     * @return Array           upload message
     */
    public function uploadConfigurationDocument($idOrder, $idPackage, $idSupplier, $fileType, $file){
        global $database, $user;

        $idSupplier = $database->escapeValue($idSupplier);
        $fileType = $database->escapeValue($fileType);
        $idDocumentType = self::DOCUMENT_TYPES['ID_CONFIGURATION_DOC_TYPE'];
        $nameSuffix = 'config';
        $maxCount = 1;

        if($fileType === 'installationProtocol') {
            $idDocumentType = self::DOCUMENT_TYPES['ID_INSTALLATION_PROTOTCOL_DOC_TYPE'];
            $nameSuffix = 'install_protocol';
        }

        $sql = "SELECT s.idUser
                FROM ".TABLES['suppliers']." s
                WHERE s.id=$idSupplier";
        $query = $database->query($sql);
        $supplier = $database->fetchArray($query);

        $sql = "SELECT name
                FROM ".TABLES['packages']."
                WHERE id=$idPackage";
        $query = $database->query($sql);
        $package = $database->fetchArray($query);
        $documentName = isset($package['name']) ? str_replace(' ', '_', $package['name']) : '';
        $documentName .= '_'.$idSupplier.'_'.$nameSuffix;

        $sql = "
            SELECT
              d.documentName
            FROM
              ".TABLES['documents']." d
              INNER JOIN ".TABLES['rel_order_documents']." rod
                ON d.id = rod.idDocument
            WHERE rod.idOrder = $idOrder
              AND rod.idPackage = $idPackage
              AND d.idDocumentType = $idDocumentType
            ORDER BY d.id DESC
            LIMIT 1";
        $lastDocName = $database->fetchResultArray($sql);
        if($lastDocName && $lastDocName[0]['documentName']) {
            $count = explode('_', $lastDocName[0]['documentName']);
            $maxCount = intval(end($count)) + 1;
        }
        $documentName .= '_'.$maxCount;

        $fileManager = new FileManager();
        $data = $fileManager->uploadFile($file, $idDocumentType, $documentName, $supplier['idUser']);
        if(isset($data['messages'])){
            return $data;
        }

        $idDocument = $data['idDocument'];

        $sql = "INSERT INTO ".TABLES['rel_order_documents']."
                (idOrder, idPackage, idDocument, validation)
                VALUES($idOrder, $idPackage, $idDocument, 'not-required')";
        $query = $database->query($sql);

        if($database->affectedRows() > 0){
            $data['messages'][] = [
                'code' => 'success',
                'message' => 'FILE_UPLOADED'
            ];
        }else{
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'NOT_UPLOADED'
            ];
        }

        return $data;
    }

    /**
     * get scheduled dates for a step
     * @param  INT $idOrder       id for the order
     * @param  INT $idPackage     id for the package
     * @param  INT $idProcessStep id for the process step
     * @return Array                array of schedueld dates
     */
    public function getScheduledDates($idOrder, $idPackage, $idProcessStep){
        global $database;
        $data = [];
        $confirmations = $this->getUserConfirmationsForSchedules($idOrder, $idPackage, $idProcessStep);

        $sql = "SELECT rosd.id AS idSchedule,
                       rosd.scheduledDate,
                       rosd.isDateConfirmed,
                       rosd.idProcessStep,
                       rosd.idPackage
                FROM ".TABLES['rel_order_scheduled_dates']." rosd
                WHERE rosd.idOrder=$idOrder AND rosd.idPackage=$idPackage AND rosd.idProcessStep=$idProcessStep
                ORDER BY rosd.scheduledDate ASC ";
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $row['confirmations'] = isset($confirmations[$row['idSchedule']]) ? $confirmations[$row['idSchedule']] : [];
            $data[] = $row;
        }

        return $data;
    }

    /**
     * get user confirimations for the scheduled dates
     * @param  INT $idOrder       id for the order
     * @param  INT $idPackage     id for the pakage
     * @param  INT $idProcessStep id for the process step
     * @return Array               list of confirmations
     */
    private function getUserConfirmationsForSchedules($idOrder, $idPackage, $idProcessStep){
        global $database;
        $data = [];

        $sql = "SELECT rosc.idSchedule,
                       rosc.status,
                       u.username,
                       ut.type AS userType
                FROM ".TABLES['rel_order_schedules_confirmations']." rosc
                INNER JOIN ".TABLES['rel_order_scheduled_dates']." rosd
                    ON rosc.idSchedule=rosd.id
                INNER JOIN ".TABLES['users']." u
                    ON u.id=rosc.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 rosd.idOrder=$idOrder AND rosd.idPackage=$idPackage AND rosd.idProcessStep=$idProcessStep";
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $data[$row['idSchedule']][] = $row;
        }

        return $data;
    }

    /**
     * add users that need to confirm the schedule date for installation
     * @param INT $idOrder    id for the order
     * @param INT $idSchedule id for the schedule
     */
    private function addRequiredConfrimationUsers($idOrder, $idSchedule){
        global $database;

        $sql = "INSERT INTO ".TABLES['rel_order_schedules_confirmations']."
                (idSchedule, idUser, status)
                SELECT $idSchedule AS idSchedule,
                    c.idUser AS idUser,
                    'pending' AS status
                FROM ".TABLES['orders']." o
                INNER JOIN ".TABLES['rel_commercial_lead_customers']." rclc
                ON rclc.id=o.idCUstomerInstance
                INNER JOIN ".TABLES['customers']." c
                ON c.id=rclc.idCustomer
                WHERE o.id=$idOrder";
        $query = $database->query($sql);

        return $database->affectedRows();
    }

    /**
     * Update the estimation date for the follow up meeting from an order
     * @param  Int $idOrder        Id of the order to be modified
     * @param  Int $idProcessStep  id of the porcess to be modified
     * @param  String $estimationDate new date to be added for a follow up meeting
     * @param  String $confirmedDate  confirmed date with the customer to be added for a follow up meeting
     * @return array                 response message for the update
     */
    public function updateScheduledDates($idOrder, $idPackage, $idProcess, $idProcessStep, $idSchedule, $newDate) {
        global $database;
        $idOrder = $database->escapeValue($idOrder);
        $idPackage = $database->escapeValue($idPackage);
        $idProcess = $database->escapeValue($idProcess);
        $idProcessStep = $database->escapeValue($idProcessStep);
        $idSchedule = $database->escapeValue($idSchedule);
        $newDate = $database->escapeValue($newDate);
        $orderDetailsParams = [
            'idOrder' => $idOrder,
            'idPackage' => $idPackage,
            'idProcess' => $idProcess
        ];
        $data = [];

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

        if(intval($idSchedule) === 0){
            $database->beginTransaction();
            $sql = "
                INSERT INTO ".TABLES['rel_order_scheduled_dates']." (
                    idOrder,
                    idPackage,
                    idProcessStep,
                    scheduledDate,
                    isDateConfirmed
                    )
                VALUES(
                        $idOrder,
                        $idPackage,
                        $idProcessStep,
                        $newDate,
                        0
                )";
            $query = $database->query($sql);
            $newIdSchedule = $database->getInsertId();
            $affectedRows = $database->affectedRows();
            $affectedRows += $this->addRequiredConfrimationUsers($idOrder, $newIdSchedule);
            if($affectedRows > 0){
                $database->commit();
            }else{
                $database->rollback();
                $err_mes = [
                    'code' => 'error',
                    'message' => 'SERVER_ERROR'
                ];
                $data['messages'][] = $err_mes;
                return $data;
            }
        }else{
            $sql = "UPDATE ".TABLES['rel_order_scheduled_dates']."
                    SET scheduledDate=$newDate
                    WHERE id=$idSchedule";
            $query = $database->query($sql);
            $affectedRows = $database->affectedRows();
        }

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

        if($affectedRows > 0){
            $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'] : '';

            /*if($estimationDate) {
                $orderDetailsParams['estimatedMeetingDate'] = $estimationDate;
            }
            if($confirmedDate) {
                $orderDetailsParams['confirmedMeetingDate'] = $confirmedDate;
            }
            $data['messages'][] = $this->sendConfirmationMail('scheduleMeeting', $orderDetailsParams);*/

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

        return $data;
    }

    /**
     * update the status for an existing schedule date
     * @param  INT $idSchedule id for schedule date
     * @param  string $status     new status for the schedule date
     * @return Array             update message
     */
    public function updateScheduleDateStatus($idSchedule, $status, $idOrder, $idPackage, $actionCode){
        global $database, $user;
        $idSchedule = $database->escapeValue($idSchedule);
        $data = [];

        $sql = "UPDATE ".TABLES['rel_order_schedules_confirmations']."
                SET status='$status'
                WHERE idSchedule=$idSchedule AND idUser=".$user->getUserId();
        $query = $database->query($sql);

        if($database->affectedRows() > 0){
            if($status === 'accepted' && $actionCode === 'choose-installation'){
                $sql = "UPDATE ".TABLES['orders']."
                        SET acceptanceDueDate=DATE_ADD(
                            (SELECT scheduledDate
                            FROM ".TABLES['rel_order_scheduled_dates']."
                            WHERE id=$idSchedule),
                            INTERVAL 15 DAY)
                        WHERE id=$idOrder";
                $query = $database->query($sql);
            }
            $updatedMainStatus = $this->updateScheduleGlobalStatus($idSchedule, $status);

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

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

            return $data;
        }
    }

    /**
     * update the status for the parent schedule date base on all users confirmation
     * @param  INT $idSchedule id for the scheduled date
     * @param  String $status     new status addded to child
     * @return INT             number of affected rows
     */
    private function updateScheduleGlobalStatus($idSchedule, $status){
        global $database;
        $confirmation = $status === 'accepted' ? 1 : -1;

        $sql = "UPDATE ".TABLES['rel_order_scheduled_dates']."
                SET isDateConfirmed=$confirmation
                WHERE id=$idSchedule";
        $query = $database->query($sql);

        return $database->affectedRows();
    }

    /**
     * get info for customer acceptance
     * @param  INT $idOrder    id for the order
     * @return Array           custoemr acceptance info
     */
    public function getCustomerAcceptance($idOrder){
        global $database;
        $idOrder = $database->escapeValue($idOrder);
        $data = [];

        $sql = "SELECT o.id AS idOrder,
                    o.customerAccepted,
                    IFNULL(o.customerDeclineReason, '') AS customerDeclineReason,
                    o.acceptanceDueDate
                FROM ".TABLES['orders']." o
                WHERE o.id=$idOrder";

        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $dueDate = new DateTime($row['acceptanceDueDate']);
            $now = time();
            $timeDiff = ($dueDate->getTimestamp() - $now ) / (3600 *24);
            $row['daysDiff'] = $timeDiff;
            $data[$row['idOrder']] = $row;
        }

        $sql = "SELECT
                   d.id AS idDocument,
                   d.documentName,
                   d.extension,
                   ro.idOrder
                FROM ".TABLES['documents']." d
                INNER JOIN ".TABLES['rel_order_documents']." ro
                    ON ro.idDocument=d.id
                WHERE ro.idOrder=$idOrder AND d.idDocumentType=".self::DOCUMENT_TYPES['ID_ACCEPTANCE_DOC_TYPE'];

        $query = $database->query($sql);
        while($row = $database->fetchArray($query)) {
            $data[$row['idOrder']]['acceptanceDocuments'][] = $row;
        }

        return $data;
    }

    /**
     * upload customer acceptance document
     * @param  INT $idOrder   id for the order
     * @param  INT $idPackage id for the packages
     * @param  FILE $file     file to be uploaded
     * @return Array          upload status
     */
    public function uploadAcceptanceDocument($idOrder, $idPackage, $file){
        global $database, $user;
        $idOrder = $database->escapeValue($idOrder);
        $idPackage = $database->escapeValue($idPackage);

        $fileManager = new FileManager();

        $sql = "SELECT MAX(d.id)+1 AS maxIdDocument
                FROM ".TABLES['documents']." d";
        $maxId = $database->fetchResultArray($sql);
        $maxIdDocument = $maxId && $maxId[0] && $maxId[0]['maxIdDocument'] ? $maxId[0]['maxIdDocument'] : 1;

        $sql = "SELECT o.orderNumber
                FROM orders o
                WHERE id=$idOrder";
        $query = $database->query($sql);
        $row = $database->fetchArray($query);
        $documentName = 'customerAcceptance_'.$row['orderNumber'].'_' . $maxIdDocument;
        $uploadedBy = $user->getUserId();
        $data = $fileManager->uploadFile($file, self::DOCUMENT_TYPES['ID_ACCEPTANCE_DOC_TYPE'], $documentName, $uploadedBy);

        if(isset($data['messages'])){
            return $data;
        }

        $idDocument = $data['idDocument'];
        $sql = "INSERT INTO ".TABLES['rel_order_documents']."
                (idOrder, idPackage, idDocument, validation)
                VALUES($idOrder, $idPackage, $idDocument, 'not-validated')";
        $query = $database->query($sql);

        if($database->affectedRows() > 0){
            $data['messages'][] = [
                'code' => 'success',
                'message' => 'FILE_UPLOADED'
            ];
        }else{
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'NOT_LINKED_TO_ORDER'
            ];
        }

        return $data;
    }

    /**
     * get customer questionaires for a specific order
     * @param  INT $idOrder  id for the order
     * @param  INT $idPackage id for the pacakge
     * @param  String $documentType the type of the documents needed - Order Questionaire or Installation protocol
     * @return Array            array of documents
     */
    public function getOrderDocumentsPerType($idOrder, $idPackage, $documentType){
        global $database, $user;

        $idOrder = $database->escapeValue($idOrder);
        $idPackage = $database->escapeValue($idPackage);
        $documentType = $database->escapeValue($documentType);
        $whereSql = $idPackage ? "AND rod.idPackage=$idPackage" : "";
        $data = [];

        if($documentType === 'orderQuestionaire') {
            $idDocumentType = self::DOCUMENT_TYPES['ID_QUESTIONAIRE_DOC_TYPE'];
        } else if($documentType === 'installationProtocol') {
            $idDocumentType = self::DOCUMENT_TYPES['ID_INSTALLATION_PROTOTCOL_DOC_TYPE'];
        } else {
            return [];
        }

        $sql = "SELECT d.id AS idDocument,
                d.uploadedBy,
                d.documentName,
                d.extension,
                rod.validation
                FROM ".TABLES['documents']." d
                INNER JOIN ".TABLES['rel_order_documents']." rod
                    ON rod.idDocument=d.id
                WHERE d.idDocumentType=$idDocumentType
                    AND rod.idOrder=$idOrder
                    $whereSql";
        $query = $database->query($sql);

        while($row = $database->fetchArray($query)) {
            $row['isUploadedByMe'] = $user->getUserId() === $row['uploadedBy'];
            unset($row['uploadedBy']);
            $data[] = $row;
        }

        return $data;
    }

    /**
     * checks if the next step enables the installation scheduling function
     * @param  Int $idOrder      id of the order
     * @param  Array $stepIds    the ids of the steps from which the scheduling function is enabled
     * @return Bool              true if the nest step is the one searched
     */
    public function checkIfIsNextStepWanted($idOrder, $stepIds) {
        global $database;
        $idOrder = $database->escapeValue($idOrder);
        $stepIds = (array) json_decode($stepIds);
        $firstStepEnabled = $database->escapeValue($stepIds['firstStepEnabled']);
        $lastStepEnabled = $database->escapeValue($stepIds['lastStepEnabled']);
        $sql = "
                SELECT
                  ps.id
                FROM
                  ".TABLES['rel_order_process_step']." rops
                  INNER JOIN ".TABLES['rel_process_steps']." rps
                    ON rps.id = rops.idProcessStep
                  INNER JOIN process_step ps
                    ON ps.id = rps.idStep
                    AND ps.idActionCode=$firstStepEnabled
                WHERE rops.idOrder = $idOrder
                  AND rops.status = 'inactive'
                UNION ALL
                SELECT
                  ps.id
                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
                  AND (
                    rops.status = 'in-progress'
                    OR rops.status = 'done'
                  )";
        $result = $database->query($sql);

        return $database->numRows($result) > 0;
    }
}
