<?php
use SilverStripe\ORM\DataObject;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\ReadonlyField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\HiddenField;
use SilverStripe\Forms\ListboxField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\TabSet;
use SilverStripe\Forms\RequiredFields;
use Sheadawson\DependentDropdown\Forms\DependentDropdownField;
use UncleCheese\DisplayLogic\Forms\Wrapper;
use SilverStripe\Assets\File;
use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\ORM\ValidationException;
use SilverStripe\Control\Director;

/**
 * extends attachment
 */
class OutboxAttachmentData extends File
{
    private static $has_one = [
        'Outbox' => OutboxMessageData::class
    ];
}

/**
 * Outbox Message
 */
class OutboxMessageData extends DataObject
{
    /**
     * [$db description]
     * IDHost        IDPesan       Pesan        TO             media (email/wa/apps/sms)  waktucreated     
     * @var [type]
     */
    private static $db = [
        'Code' => 'Text',
        'Message' => 'Text',
        'Recipients' => 'Text',
        'SendVia' => 'Enum(array("Email", "Wa", "Apps", "SMS"), "Email")',
        'Subject' => 'Text',
        'CC' => 'Text',
        'BCC' => 'Text',
        'Status' => 'Text',
        'Checked' => 'Int',
        'IsOtp' => 'Int',
        'ErrorMessage' => 'Text',
        'ErrorDate' => 'Datetime',
        'ClientIP' => 'Varchar(255)'
    ];
    
    public function getFields()
    {
        return self::$db;
    }

    private static $has_one = [
        'App' => AppData::class,
        'Instance' => InstanceOutboxData::class
    ];

    private static $owns = [
        'Attachment'
    ];

    private static $has_many = [
        'Attachment' => OutboxAttachmentData::class,
    ];

    /*private static $searchable_fields = [
        'json_data',
        'status',
        'confirmed',
    ];*/

    /*private static $field_labels = [
        'json_data' => 'Data',
        'status' => 'Status',
        'confirmed' => 'Confirmed',
    ];*/

    private static $summary_fields = [
        'App.nama_app' => 'App',
        'Code' => 'Code',
        'Message' => 'Message',
        'Recipients' => 'Recipients',
        'SendVia' => 'Media',
        'Since' => 'Created',
        'Subject' => 'Subject/Title',
        'CC' => 'CC',
        'BCC' => 'BCC',
        'Status' => 'Status'
    ];

    public function getSince()
    {
        return date('d/m/Y H:i:s', strtotime($this->Created));
    }

    public function onBeforeWrite()
    {
        if (!$this->ID) {
            $this->Status = "Menunggu antrian dikirim";
        }
        $app = AppData::get()->byID($this->AppID);
        $base = date('d-m-Y_H-i-s');
        $this->Code = $app->nama_app . '_' . $base;
        $recipients = $this->Recipients;
        if ($this->SendVia == 'Apps' && !empty($this->RecipientsApps)) {
            $this->Recipients = $this->RecipientsApps;
            $recipients = $this->RecipientsApps;
        }
        /*var_dump($this->toMap());
        die;*/
        if ($recipients == '' || $recipients == null) {
            throw new ValidationException("Recipients harus ada");
        }
        $this->Recipients = preg_replace('/\s+/', '', $this->Recipients);

        parent::onBeforeWrite();
    }

    public function getCodeMessage()
    {
        if (!$this->ID)
            return '<Auto Generate>';

        return $this->Code;
    }
  
    public function getCMSFields()
    {
        // $fields = parent::getCMSFields();
        // $fields->removeByName('Code');
        // $fields->removeByName('Recipients');
        // $fields->removeByName('CC');
        // $fields->removeByName('BCC');
        // $fields->removeByName('SendVia');
        // $fields->removeByName('Message');
        // $fields->removeByName('Attachment');
        // $fields->removeByName('AppID');
        // $fields->removeByName('InstanceID');
        $fields = new FieldList();
        $fields->add(new TabSet("Root"));
        
        $msg = new TextareaField('Message', 'Message');
        $fields->addFieldToTab("Root.Main", $msg
        ->setDescription('Untuk Mengirim File Via WA, Pisahkan Pesan dengan url menggunakan <~>. Ex: <b>Tolong lihat file ini.<~>www.website.com/img.jpeg</b>'));
        
        //dropdown sendvia 
        $dropdown_sendvia = new DropdownField('SendVia', 'Send Message Via', array(
            "Email" => "Email", 
            "Wa" => "Wa", 
            "Apps" => "Apps", 
            "SMS" => "SMS"
        ));
        $dropdown_sendvia->setEmptyString("Pilih via");
        $fields->insertBefore('Message', $dropdown_sendvia);
        
        // dropdown app
        $dropdown_app = new DropdownField('AppID', 'App', AppData::get()->Map('ID', 'nama_app')); 
        $dropdown_app->setEmptyString("Pilih App");
        // $fields->insertBefore('InstanceID', $dropdown_app);
        $fields->insertBefore('Message', $dropdown_app);
        
        // dropdown instance
        $instanceByApp = function ($val) {
            return InstanceOutboxData::instanceByApp($val);
        };
        $instance = DependentDropdownField::create("InstanceID", 
        'Instance', 
            $instanceByApp
            )->setDepends($dropdown_app);
        $instance->setEmptyString("Pilih instance");
        // $fields->insertAfter('AppID', $instance);
        $fields->insertBefore('Message', $instance);
        $fields->insertBefore("Message", new ReadonlyField('CodeMessage', 'Code'));
            
        // $dropdown_instance = InstanceOutboxData::get();
        // $dropdown_instance = new DropdownField('InstanceID', 'Instance', $dropdown_instance->Map('ID', 'InstanceName')); 
        // $fields->insertAfter('AppID', $dropdown_instance);
        // recipients wrapper
        $wrapper_recipients_apps = Wrapper::create(
            TextField::create('RecipientsApps', 'Recipients Apps', $this->Recipients)
        )->displayIf('SendVia')->isEqualTo('Apps')->end();

        $wrapper_recipients_other = Wrapper::create(
            TextareaField::create('Recipients', 'Recipients')
        )->displayIf('SendVia')->isNotEqualTo('Apps')->end();
            
        $wrapper_recipients_other
            ->setDescription('Untuk banyak Recipients pisahkan dengan koma ",". Misal untuk No. Telp menjadi 084987578, 0887487489 begitupun untuk email menjadi email@mail.com, mail2@email.co. Untuk Grup Wa menggunakan GroupID ex:6287850397863-1587012191@g.us. Dan untuk tipe pesan apps tolong gunakan No. Telp');
        
        $fields->insertBefore('Message', $wrapper_recipients_other);
        $fields->insertBefore('Message', $wrapper_recipients_apps);
        $fields->insertBefore('Message', new TextareaField('Subject', 'Subject'));
        
        // display cc & bcc if sendvia is email
        $wrapper = Wrapper::create(
           TextareaField::create('CC', 'CC'),
           TextareaField::create('BCC', 'BCC')
        )->displayIf('SendVia')->isEqualTo('Email')->end();
        $fields->addFieldToTab('Root.Main', $wrapper);
            
        $wrapperAttachment = Wrapper::create(
            UploadField::create('Attachment', 'Attachment')
        )->displayIf('SendVia')
            ->isEqualTo('Email')
            ->end(); 
        $fields->addFieldToTab('Root.Main', $wrapperAttachment);

        // $app = AppData::get();
        // $dropdown = new DropdownField('AppID', 'App', $app->map('ID', 'nama_app'));
        // $dropdown->setEmptyString("Pilih App");
        // $fields->addFieldToTab("Root.Main", $dropdown);

        // $dropdown_app = AppData::get();

        return $fields;

    }

    public function getCMSValidator()
    {
        return new RequiredFields([
            'ModulsID',
            // 'Recipients',
            'SendVia',
            'Subject',
            'Message'
        ]);
    }

    public function 
sendWA() {
        if ($this->cekAllRequired() == false) {
            return false;
        }

        $message = new MessageHelper();
        $message->notif = $this;

        try {
            $message->sendWA();
            // $this->delete();
            $this->setError('success');
        } catch (Exception $e) {
            $cek = AppMessageData::get()->where('AppID = '.$this->AppID);
            if($cek->count() > 0){
                $app = $cek->first();
                $rawRecipients = [];
                 $formattedRecipients = [];
                if (strpos($app->Nomor, ",")) {
                    $rawRecipients = explode(",", $app->Nomor);
                } else {
                    $rawRecipients[] = $app->Nomor;
                }

                foreach ($rawRecipients as $value) {
                    $cek = $message->checkPhoneNumber(trim($value));
                    if ($cek == false) {
                        continue;
                    } else {
                        $formattedRecipients[] = $cek;
                    }
                }

                $cekAgain = InstanceOutboxData::get()->innerJoin("AppInstanceData", "\"AppInstanceData\".\"InstanceID\" = \"InstanceOutboxData\".\"ID\"")->where("InstanceWaType = 'VenomWA' and AppInstanceData.AppID = ".$this->AppID);
                $pesaError = $e->getMessage();
                $pesaError = explode(' ', $pesaError);
                $IsiPesanError = '';
                for ($i=0; $i <3 ; $i++) { 
                    if(isset($pesaError[$i])){
                        $IsiPesanError .= $pesaError[$i]." ";
                    }
                }
                
                $IsiPesan = 'Notif ada yang macet '.$this->App()->nama_app.' pada link '.Director::AbsoluteBaseURL()." ".$IsiPesanError;

                if($cekAgain->count() > 0){
                    $wa = $cekAgain->first();
                    foreach ($formattedRecipients as $value) {
                        $body = [
                            'phone' => $value,
                            'text' => $IsiPesan
                        ];
                        $this->postVenomWA($wa,$body);
                    }
                } else {
                    $cekAgain = InstanceOutboxData::get()->innerJoin("AppInstanceData", "\"AppInstanceData\".\"InstanceID\" = \"InstanceOutboxData\".\"ID\"")->where("InstanceWaType = 'ChatAPI' and AppInstanceData.AppID = ".$this->AppID);
                    if($cekAgain->count() > 0){
                        $wa = $cekAgain->first();
                        foreach ($formattedRecipients as $value) {
                            $body = [
                                'phone' => $value,
                                'text' => $IsiPesan
                            ];
                            $this->postChatAPI($wa,$IsiPesan);
                        }
                    }
                }
                $date = new DateTime(date('Y-m-d H:i:s'));
                $timeZone = new DateTimeZone('Asia/Jakarta');
                $date->setTimeZone($timeZone);
                $arr = [
                    '@timestamp' => $date->format('c'),
                    'formatIndonesia' => date('d/m/Y H:i:s'),
                    'log.level' => 'URGENT',
                    'message' => implode(' ', $pesaError)
                ];
                $log_msg = json_encode($arr). "\r\n";
                $file = '../log/mgnotif.log';
                if (!is_dir('../log/')) {
                  mkdir('../log/');
                }
                file_put_contents($file, $log_msg, FILE_APPEND | LOCK_EX);
            }
            $this->setError($e->getMessage());
        }
    }

    public function sendEmail() {
        if ($this->cekAllRequired() == false) {
            return false;
        }

        $message = new MessageHelper();
        $message->notif = $this;

        try {
            $message->sendEmail();
            $this->delete();
        } catch (Exception $e) {
            $this->setError($e->getMessage());
        }
    }

    public function cekAllRequired() {
        if ($this->isAppExist() == false) {
            $this->setError("App Data Not Exist");
            return false;
        }

        if ($this->isInstanceExist() == false) {
            $this->setError("Instance Data Not Exist");
            return false;
        }

        if ($this->isInstanceExist() == false) {
            $this->setError("App Data and Instance Data Not Connected");
            return false;
        }

        return true;
    }

    public function isAppExist() {
        $data = AppData::get()->where("ID = ".$this->AppID)->limit(1);
        foreach ($data as $key => $value) {
            return true;
        }
        return false;
    }

    public function isInstanceExist() {
        $data = InstanceOutboxData::get()->where("ID = ".$this->InstanceID)->limit(1);
        foreach ($data as $key => $value) {
            return true;
        }
        return false;
    }

    public function isAppAndInstanceConnected() {
        $data = AppinstanceData::get()->where("InstancID = ".$this->InstanceID." AND AppID = ".$this->AppID)->limit(1);
        foreach ($data as $key => $value) {
            return true;
        }
        return false;
    }

    public function setError($message) {
        $this->ErrorMessage = $message;
        $this->write();
    }

    public function postVenomWA($Instance,$message) {
        $authorization = "Authorization: Bearer " . $Instance->AuthToken;
        
        $httpHeader = array('Content-Type:application/json');
        $url = $Instance->InstanceLink."sendText";
        $message = json_encode($message);

        $httpHeader[] = $authorization;

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeader);

        $output = curl_exec($ch);

        curl_close($ch);
    }

    public function postChatAPI($Instance,$message)
    {
        $url = $Instance->InstanceLink;

        $httpHeader = array('Content-Type:application/json');
        $message = json_encode($message);
        $message = str_replace("\\r\\n", "\\n", $message);
        $message = str_replace("\\n\\n", "\\n \\n", $message);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, false);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeader);


        $output = curl_exec($ch);

        curl_close($ch);
    }
}
