<?php

/**
 * @property NotificationComponent $Notification
 */
    class BackupShell extends AppShell
    {
        public $unique_url;
        public $uses = array('AccessInfo','ExpiredRecord');


        public function main() {
            
        }

        /*
         * command:  Console/cake Backup generateAccessInfo
         * Run it only once to generate accessinfo for records before 25 february 2018
         */
        public function generateAccessInfo(){
            $backup_mode = Configure::read('expensecount.backup.mode');
            $db = ConnectionManager::getDataSource('default');
            $limit = 100;
            if($backup_mode){
                //retrieve all expense which is not  exist in Access Info and update date before   4 months
                // create access info  records  for those  expenses; id=>expense_id, unique_url=>unique_url,  access_time=>created_date

               $range = date('Y-m-d', strtotime("25 February, 2018"));
               $expense_counts = $db->query("SELECT id, unique_url, create_date FROM `expenses` WHERE id not in(select id from access_infos) and `create_date` < '$range'");
               foreach ($expense_counts as $key=>$value) {
                    $expense_id = $value['expenses']['id'];
                    $unique_url = $value['expenses']['unique_url'];
                   // $access_time =  $value['expenses']['create_date'];
                    $access_time = date('Y-m-d H:i:s', $value['expenses']['update_date']);
                    $db->query("insert into access_infos(id, unique_url, access_time) values(".$expense_id.",'".$unique_url."','".$access_time."')");
                }
            }
            exit;

            //insert multiple record into the table Expired_Records
            //check the case whether the record insertion successful or not for multi insertion when pk already exist
        }

        /*
         * command:  Console/cake Backup shiftExpiredRecords
         * Run it in every hours  once
         * This method generates records into the table expired_records and delete all records fron access info
         */
        public function shiftExpiredRecords(){
            
            $backup_mode = Configure::read('expensecount.backup.mode');
            $month = isset($this->args[0]) ? (int)$this->args[0] : 4; // default 4 months
            $type = isset($this->args[1]) ? (int)$this->args[1] : 1; // default 1. 1 = Months, 2 = Days; Type will always be 1 because no value is passed for this parameter.

            if ($month <= 0) {
                echo('Month must be a positive number');
                exit;
            }
            if($backup_mode){
                //retrieve all expried records
                $result =  $this->AccessInfo->getExpiredExpenses($month,$type);

                if(!empty($result)){
                    $currentDate = $this->getSystemCurrentTimeStamp();
                    foreach($result as $key=>$value){
                        $deleteList[] = $value["AccessInfo"]["id"];
                        $data["ExpiredRecord"][$key]["id"] = $value["AccessInfo"]["id"];
                        $data["ExpiredRecord"][$key]["unique_url"] = $value["AccessInfo"]["unique_url"];
                        $data["ExpiredRecord"][$key]["inserted_on"] = $currentDate;
                    }
    
                    $error = $this->ExpiredRecord->saveAllExpiredRecords($data);
                    if(empty($error)){
                        //delete all records from AccessInfo table
                        $this->AccessInfo->deleteAllExpiredExpenses($deleteList);
                    }
                }
            }
            exit;

            //insert multiple record into the table Expired_Records
            //check the case whether the record insertion successful or not for multi insertion when pk already exist
        }

        /*
         * command:  Console/cake Backup initiateBackup 100
         * Run it in every six hours  once
         * This method scan expire_records table and shift records to backup  tables; 
         * After  taking backup, it  delete records from expire_records table.
         */
        public function initiateBackup($limit = BACKUP_LIMIT){
            $limit = isset($this->args[0]) ? (int)$this->args[0] : BACKUP_LIMIT;
            $this->backupAndRemoveOriginalRecords($limit);
        }
        
        /*
         * Command : Console/cake Backup backupSingleExpense 1ILcOUb0fe3JpgB
         *  This method shifts and backup single expense from live tables to backup tables in the production database.
         */
        public function backupSingleExpense($unique_url=null)
        {
            $unique_url = isset($this->args[0]) ? $this->args[0] : null;
            $db = ConnectionManager::getDataSource('default');
            try {
                $backup_expense = $db->query("select * from backup_expenses where unique_url='".$unique_url."'");
            } catch (Exception $ex) {
            }
            if (empty($backup_expense)) {
                $expense = $db->query("select * from expenses where unique_url= '".$unique_url."'");
                if(!empty($expense)) {
                    
                    $this->loadModel('Backup');
                    $this->Backup->processBackupAndRemove($expense);
                    
                } else {
                    echo "Expense is not found in production  database. Could not perform backup!";
                    exit;
                }
            } else {
                echo "Expense is already in backup database. Could not perform backup!";
                exit;
            }
        }

        /*
         * command:  Console/cake Backup archieveSingleItem 1ILcOUb0fe3JpgB
         * Run it to archieve a sinle expense
         * 
         * This method shifts one single expense from backup tables(live db) to archieve database
         * 
         */
        public function archieveSingleItem($unique_url=null)
        {
            $unique_url = isset($this->args[0]) ? $this->args[0] : null;
            $this->loadModel('Backup');
            $this->Backup->archieveSingleExpense($unique_url);
        }


        /*
         * command: Console/cake Backup initiateArchive 10 100
         * Run it to archive records older than custom month, with a row limit.
         *  e.g. 10 months before from the current date and 100 records
         */
        public function initiateArchive($month = 50, $limit = BACKUP_LIMIT){
            $month = isset($this->args[0]) ? (int)$this->args[0] : 50;
            $limit = isset($this->args[1]) ? (int)$this->args[1] : BACKUP_LIMIT;

            $this->archiveAndRemoveOriginalRecords($limit,$month);
        }

        /*
        * command: Console/cake Backup initiateRemoveArchive 10 100
        * Run it to remove archived records older than custom month, with a row limit.
        *  e.g. 10 months before from the current date and 100 records
       */
        public function initiateRemoveArchive($month = 50, $limit = BACKUP_LIMIT){
            $month = isset($this->args[0]) ? (int)$this->args[0] : 50;
            $limit = isset($this->args[1]) ? (int)$this->args[1] : BACKUP_LIMIT;

            $this->removeArchiveRecords($limit,$month);
        }

        private function backupAndRemoveOriginalRecords($limit = BACKUP_LIMIT){

            $backup_mode = Configure::read('expensecount.backup.mode');
            if($backup_mode){

                //retrieve 100 records from the table expired_records
                $query = "select id,unique_url from expired_records limit 0,".$limit;
                $db = ConnectionManager::getDataSource('default');
                $expiredRecordList = $db->query($query);
                $db->begin();
                try {
                    if (!empty($expiredRecordList)) {
                        $this->loadModel('Backup');
                        $this->Backup->processBackupAndRemove($expiredRecordList, true);
                        $db->commit();
                    }

                }catch (Exception $ex) {
                    $db->rollback();
                    $message = "Backup process failed. Rolled back. Error: " . $ex->getMessage();
                    $this->emailSend($message,"Backup process failed");
                    echo $message;

                }
            }
            exit;
        }

        private function archiveAndRemoveOriginalRecords($limit = BACKUP_LIMIT, $month = 36){

            $month = (int)$month;
            if ($month <= 0) {
                echo('Month must be a positive number');
                exit;
            }
            $backup_mode = Configure::read('expensecount.backup.mode');
            $db = ConnectionManager::getDataSource('default');

            $before_date = (new DateTime())
                ->modify("-{$month} months")
                ->format('Y-m-d');

            $range = strtotime($before_date);

            if($backup_mode){
                //retrieve records from the table back_expenses
                $query = "SELECT id, unique_url
                            FROM backup_expenses WHERE update_date <= $range 
                            LIMIT $limit";
                $backupRecordList = $db->query($query);

                if(!empty($backupRecordList)){
                    $this->loadModel('Backup');
                    $this->Backup->processArchiveAndRemove($backupRecordList,true);
                }
            }
            exit;
        }

        private function removeArchiveRecords($limit = BACKUP_LIMIT, $month = 36){

            $month = (int)$month;
            if ($month <= 0) {
                echo('Month must be a positive number');
                exit;
            }
            $backup_mode = Configure::read('expensecount.backup.mode');


            $before_date = (new DateTime())
                ->modify("-{$month} months")
                ->format('Y-m-d');

            $range = strtotime($before_date);

            $db = ConnectionManager::getDataSource('archieve');

            if ($backup_mode) {
                    //retrieve records from the table expenses
                    $query = "SELECT id, unique_url
                            FROM expenses WHERE update_date <= $range
                            LIMIT $limit";
                   $archiveRecordList = $db->query($query);

                    if (!empty($archiveRecordList)) {
                        $this->loadModel('Backup');
                        $this->Backup->processRemoveArchive($archiveRecordList, true);
                    }
                }



        }


        private function emailSend($message = null, $subject = null)
        {
            App::uses('ComponentCollection', 'Controller');
            App::uses('NotificationComponent', 'Controller/Component');

            $this->Notification = new NotificationComponent(new ComponentCollection());
                $this->Notification->sendEmail(array(
                    "email_from" => SUPPORT_EMAIL,
                    "email_to" => REPORTING_EMAIL,
                    "title" => $message,
                    "template" => "backup_archive_process_error",
                    "subject" => $subject,
                ));

        }



    }

    ?>