<?php
namespace NMS;
use \nms_job;

class ProcessJob_CmsJob extends \CMSMS\Async\Job
{
    private $nms_jobid;
    private $time_limit;
    private $_start_time;
    private $email_limiter;

    public function __construct( $nms_jobid )
    {
        parent::__construct();
        $this->module = 'NMS';
        $this->name = 'Process Emails for job '.$nms_jobid;

        $nms_jobid = (int) $nms_jobid;
        if( $nms_jobid < 1 ) throw new \LogicException('Invalid jobid passed to '.__METHOD__);
        $this->nms_jobid = (int) $nms_jobid;

        $config = \cms_config::get_instance();
        $time_limit = (int) $config['cmsjobmanager_timelimit'];
        if( !$time_limit ) $time_limit = (int) ini_get('max_execution_time');
        $time_limit = max(30,min(1800,$time_limit)) - 2; // no stupid time limit values
        $this->time_limit = $time_limit;

        $mod = \cms_utils::get_module('NMS');
        $email_limit = (int) $mod->GetPreference( 'messagesperhour' );
        $email_limit = max(0,$email_limit);
        $this->email_limiter = new bg_emailsperhour( $email_limit );
    }

    protected function start_timer()
    {
        $this->_start_time = time();
    }

    protected function under_time_limit()
    {
        return ( (time() - $this->_start_time) < $this->time_limit ) ? true : false;
    }

    public function execute()
    {
        $message = null;
        $nms_jobid = $this->nms_jobid;
        $db = cmsms()->GetDb();
        $nms = \cms_utils::get_module(MOD_NMS);

        $nms_job = nms_job::load($nms_jobid);
        if( $nms_job['status'] != NMS_JOBSTATUS_RUNNING ) {
            if( $nms_job['STATUS'] == NMS_JOBSTATUS_PAUSED || $nms_job['status'] == NMS_JOBSTATUS_ABORTED ) return;
            audit($nms_jobid,'NMS','nms job has invalid status');
            throw new \RuntimeException("Job $nms_jobid has invalid status, cannot initialize");
        }

        $this->start_timer();
        $sql = 'SELECT * FROM '.NMS_MAILS_TABLE.' where jobid = ? AND status IS NULL ORDER BY messageid';
        $dbr = $db->Execute( $sql, [ $nms_jobid ] );
        $n_sent = 0;
        while( !$dbr->EOF() && $this->under_time_limit() && $this->email_limiter->under_email_limit() ) {
            $email_row = $dbr->fields;

            // todo: update this row to set the status so that it can absolutely not be read again

            // get the message, if we do not already have it.
            if( is_null($message) || !is_array($message) || !isset($message['messageid']) || $message['messageid'] != $email_row['messageid'] ) {
                $sql = 'SELECT * FROM '.NMS_MESSAGES_TABLE.' WHERE messageid = ?';
                $message = $db->GetRow($sql, [ $email_row['messageid'] ]);
                if( !is_array($message) || !isset($message['messageid']) ) throw new \RuntimeException('Could not get a valid message with id '.$email_row['messageid'] );
            }

            // update the status to sending.
            $status = 'sending';
            $sql = 'UPDATE '.NMS_MAILS_TABLE.' SET status = ? WHERE jobid = ? AND messageid = ? AND email = ?';
            $db->Execute($sql, [ $status, $email_row['jobid'], $email_row['messageid'], $email_row['email'] ] );

            // send it
            $res = $nms->_ProcessOneEmail('cntnt01', $message, $email_row, $nms_job);
            if( !$res ) debug_to_log('failed sending to '.$email_row['email'] );

            // update status again
            $status = 'sent';
            if( !$res ) $status = 'error';
            $sql = 'UPDATE '.NMS_MAILS_TABLE.' SET senddate = ?, status = ? WHERE jobid = ? AND messageid = ? AND email = ?';
            $db->Execute($sql, [ time(), $status, $email_row['jobid'], $email_row['messageid'], $email_row['email'] ] );

            // record sent
            $n_sent++;
            $this->email_limiter->record_email();
            $dbr->MoveNext();
        }

        debug_to_log("Sent $n_sent emails for job $nms_jobid",__METHOD__);

        if( !$dbr->EOF() ) {
            // we are not done yet... for some reason
            // must create another job in the job manager.
            if( !$this->email_limiter->under_email_limit() ) {
                audit($nms_jobid,'NMS','Job incomplete (email limit), creating a new task to resume this job later');
            } else if( !$this->under_time_limit() ) {
                audit($nms_jobid,'NMS','Job incomplete (time limit issue), creating a new task to resume this job later');
            }
            $new_job = new self( $nms_jobid );
            $new_job->errors = $this->errors;
            $jobid = $new_job->save();

            $nms_job['async_id'] = $jobid;
            $nms_job->save();
        } else {
            // update master job
            $new_job = new FinishJob_CmsJob( $nms_jobid );
            $jobid = $new_job->save();

            $nms_job['status'] = NMS_JOBSTATUS_FINISHING;
            $nms_job['async_id'] = $jobid;
            $nms_job->save();

            // audit message
            audit($nms_jobid,'NMS','Finished sending emails for job');
        }
    }
} // class