<?php

/**
 * @package Pulsa Online w38s.com
 * @version 3.7.3
 * @author Samsul Bahri (0818118061 / achunk17@gmail.com)
 * @link http://w38s.com
 * @link http://facebook.com/achunks
 * @license http://w38s.com/lisensi
 * @copyright 2015 - 2018
 */

defined('BASEPATH') or exit('No direct script access allowed');

class W38s_gateway extends CI_Controller
{
    protected $events = array();

    public function index()
    {
        if ($this->system->get_set('maintenance') == 'on') {
            return $this->display_output(array(
                'success' => false,
                'message' => 'Situs sedang dalam maintenance',
                ));
        }

        $smsg_config = json_decode($this->system->get_set('w38s_gateway'));

        if (!$this->is_validated($smsg_config->password)) {
            return $this->display_output(array(
                'success' => false,
                'message' => 'Password Salah',
                ));
        }

        if ($this->system->set['smsg_aktif'] <= (time() - 60)) {
            $this->db->where('set_key', 'smsg_aktif');
            $this->db->set('set_val', time());
            $this->db->update('setelan');
        }

        $action = $this->input->get_post('action');
        $this->load->model('mtrx');

        if ($action == 'incoming' || $action == 'incoming_sms') {
            $this->incoming_sms();
        } elseif ($action == 'incoming_jabber') {
            $this->incoming_jabber();
        } elseif ($action == 'send_status') {
            $this->send_status();
        }

        $this->mtrx->sms_remind_trx();
        $this->send_sms_jabber();
        if (strtolower($this->input->get_post('notification')) == 'yes') {
            $this->get_notifications();
        }
        $payload = array(
            'success' => true,
            'events' => $this->events,
            );
        $this->display_output($payload);
    }

    protected function incoming_sms()
    {
        if ($this->input->get_post('disabled_inbox')) {
            return;
        }
        $from = $this->input->get_post('from');
        $message = $this->input->get_post('message');
        $timestamp = (int)substr($this->input->get_post('timestamp'), 0, 10);

        if (!$from || !$message || !$timestamp)
            return;

        // Modul transaksi via SMS
        $us_phone = substr($from, 0, 3) == '+62' ? '0' . substr($from, 3) : $from;
        $this->db->select('us_id');
        $this->db->where('us_phone', $us_phone);
        $q = $this->db->get('users');

        if ($q->num_rows() == 1) {
            $us = $q->row();
            $this->db->insert('sms_masuk', array(
                'in_uid' => 'user.' . $us->us_id,
                'in_from' => $from,
                'in_message' => $message,
                'in_timestamp' => $timestamp,
                ));
            $last_id = $this->db->insert_id();
            $this->load->model('smstrx_model');
            $this->smstrx_model->proses_pesan($from, $message, $last_id);
        } else {
            $this->proses_sms($from, $message, $timestamp);
        }
    }

    protected function incoming_jabber()
    {
        $from = strtolower($this->input->post('from'));
        $message = $this->input->post('message');
        $timestamp = (int)substr($this->input->post('timestamp'), 0, 10);
        if ($this->input->post('stanza_id'))
            $id = $this->input->post('stanza_id');
        else
            $id = '';

        if (!$from || !$message || !$timestamp)
            return;

        // Modul transaksi via Jabber
        $this->db->select('us_id');
        $this->db->where('ct_type', 'jabber');
        $this->db->where('ct_sender', $from);
        $this->db->where('ct_verified', '1');
        $this->db->where('ct_blocked', '0');
        $q = $this->db->get('center_trx');

        if ($q->num_rows() == 1) {
            $ct = $q->row();
            $this->db->insert('sms_masuk', array(
                'in_uid' => 'user.' . $ct->us_id,
                'in_type' => 'jabber',
                'in_from' => $from,
                'in_message' => $message,
                'in_timestamp' => $timestamp,
                ));
            $last_id = $this->db->insert_id();
            $this->load->model('jabbertrx_model');
            $this->jabbertrx_model->proses_pesan($from, $message, $last_id);
        } else {
            $this->proses_jabber($from, $message, $timestamp, $id);
        }
    }

    protected function proses_sms($from, $message, $timestamp)
    {
        $trx_in_process = $this->mtrx->get_trx_in_process(array('sms', 'otomax_api_sms'));

        if ($trx_in_process) {
            foreach ($trx_in_process as $trx) {
                if ($trx->tr_status != 'dalam_proses')
                    continue;

                $nomor = $trx->tr_id_plgn ? $trx->tr_id_plgn : $trx->tr_no_hp;
                if (strpos($message, $nomor) !== false) {
                    $status = $this->mtrx->cek_status($message, $trx->sv_regex_sukses, $trx->
                        sv_regex_gagal);
                    if ($status == 'sukses') {
                        $this->db->where('in_trx_id', $trx->tr_id)->delete('sms_masuk');
                        $inbox = array(
                            'in_trx_id' => $trx->tr_id,
                            'in_type' => 'sms',
                            'in_from' => $from,
                            'in_message' => $message,
                            'in_timestamp' => $timestamp,
                            );
                        $this->db->insert('sms_masuk', $inbox);
                        $this->mtrx->set_sukses($trx, $message);
                        return;
                    }
                    if ($status == 'gagal') {
                        $this->db->where('in_trx_id', $trx->tr_id)->delete('sms_masuk');
                        $inbox = array(
                            'in_trx_id' => $trx->tr_id,
                            'in_type' => 'sms',
                            'in_from' => $from,
                            'in_message' => $message,
                            'in_timestamp' => $timestamp,
                            );
                        $this->db->insert('sms_masuk', $inbox);
                        $trx->sv_gateway = 'sms';
                        $this->mtrx->set_gagal($trx, $message);
                        return;
                    }
                }
            }
        }
        $this->db->insert('sms_masuk', array(
            'in_type' => 'sms',
            'in_from' => $from,
            'in_message' => $message,
            'in_timestamp' => $timestamp,
            ));
    }

    protected function proses_jabber($from, $message, $timestamp, $id)
    {
        $inbox = array(
            'in_uid' => $id,
            'in_type' => 'jabber',
            'in_from' => $from,
            'in_message' => $message,
            'in_timestamp' => time(),
            );
        $this->db->insert('sms_masuk', $inbox);
        $sms_id = $this->db->insert_id();

        $trx_in_process = $this->mtrx->get_trx_in_process(array('jabber'));

        if (!$trx_in_process)
            return;

        foreach ($trx_in_process as $trx) {
            if ($trx->sv_jabber_center != $from)
                continue;

            $nomor = $trx->tr_id_plgn ? $trx->tr_id_plgn : $trx->tr_no_hp;
            if (strpos($message, $nomor) !== false) {
                $status = $this->mtrx->cek_status($message, $trx->sv_regex_sukses, $trx->
                    sv_regex_gagal);
                if ($status == 'sukses') {
                    $this->db->where('in_trx_id', $trx->tr_id)->delete('sms_masuk');
                    $this->db->where('in_id', $sms_id)->set('in_trx_id', $trx->tr_id)->update('sms_masuk');
                    $this->mtrx->set_sukses($trx, $message);
                    return;
                }
                if ($status == 'gagal') {
                    $this->db->where('in_trx_id', $trx->tr_id)->delete('sms_masuk');
                    $this->db->where('in_id', $sms_id)->set('in_trx_id', $trx->tr_id)->update('sms_masuk');
                    $this->mtrx->set_gagal($trx, $message);
                    return;
                }
            }
        }
    }

    protected function send_status()
    {
        $errors = array(
            "RESULT_ERROR_GENERIC_FAILURE",
            "RESULT_ERROR_RADIO_OFF",
            "RESULT_ERROR_NULL_PDU",
            "RESULT_ERROR_NO_SERVICE",
            "RESULT_UNKNOW",
            "STATUS_FAILED",
            "STATUS_NONE",
            "STATUS_UNKNOW",
            );
        $sid = explode('.', $this->input->get_post('id'));
        $status_code = $this->input->get_post('status');
        if (in_array($status_code, $errors)) {
            $status = "failed";
            $error = $status_code;
        } elseif ($status_code == "STATUS_COMPLETE") {
            $status = "sent";
            $error = "";
        } elseif ($status_code == "STATUS_PENDING") {
            $status = "queued";
            $error = "";
        } else {
            return;
        }

        if ($error == 'Timeout while attempting to send message') {
            return;
        }

        if ($sid[0] == 'sms') {
            $this->db->where('out_id', $sid[1]);
            $this->db->where('out_status', '-');
            $this->db->update('sms_keluar', array(
                'out_status' => $status,
                'out_error' => $error,
                'out_send_date' => time(),
                ));
            $rows = $this->db->affected_rows();
            if ($error && $rows) {
                $sms = $this->db->where('out_id', $sid[1])->get('sms_keluar')->row();
                $this->db->insert('notifikasi', array(
                    'us_id' => '0',
                    'nf_admin' => '1',
                    'nf_judul' => 'Gagal Mengirim SMS',
                    'nf_teks' => "No Tujuan: " . $sms->out_to . "\r\nPesan: " . $sms->out_message .
                        "\r\nKesalahan: " . $error,
                    'nf_link' => '',
                    'nf_tanggal' => time(),
                    ));
            }
        } elseif ($sid[0] == 'isi') {
            $this->db->select('transaksi.*, voucher.vo_kode_fisik, voucher.vo_kode_trx, server.*, ' .
                'users.us_username, users.us_name, users.us_email, users.us_phone, users.us_balance, ' .
                'users.us_data, users.us_telegram_id');
            $this->db->from('transaksi');

            $this->db->join('server', 'server.sv_id = transaksi.sv_id', 'LEFT');
            $this->db->join('voucher', 'voucher.vo_id = transaksi.vo_id', 'LEFT');
            $this->db->join('users', 'users.us_id = transaksi.us_id', 'LEFT');

            $this->db->where('transaksi.tr_id', $sid[1]);
            $this->db->where('transaksi.tr_status', '-');
            $query = $this->db->get();
            if (!$query->num_rows())
                return;

            $trx = $query->row();

            if (!$trx->sv_regex_sukses || !$trx->sv_regex_gagal)
                $status = 'sukses';
            else
                $status = 'dalam_proses';

            $status = $error ? 'gagal' : $status;
            if ($status == 'gagal') {
                $inbox = array(
                    'in_trx_id' => $trx->tr_id,
                    'in_type' => 'sms',
                    'in_from' => $trx->sv_nama,
                    'in_message' => 'Trx #' . $trx->tr_id . ' ' . ($trx->vo_kode_trx ? $trx->
                        vo_kode_trx : $trx->vo_kode) . '.' . ($trx->tr_id_plgn ? $trx->tr_id_plgn : $trx->
                        tr_no_hp) . ' tidak diproses karena gagal mengirim SMS. (Error: ' . $error . ')',
                    'in_timestamp' => time(),
                    );
                $this->db->insert('sms_masuk', $inbox);
                $trx->sv_gateway = 'sms';
                $this->mtrx->set_gagal($trx, $inbox['in_message']);
            } elseif ($status == 'sukses') {
                $inbox = array(
                    'in_trx_id' => $trx->tr_id,
                    'in_type' => 'sms',
                    'in_from' => $trx->sv_nama,
                    'in_message' => 'Trx #' . $trx->tr_id . ' ' . ($trx->vo_kode_trx ? $trx->
                        vo_kode_trx : $trx->vo_kode) . '.' . ($trx->tr_id_plgn ? $trx->tr_id_plgn : $trx->
                        tr_no_hp) . ' SUKSES',
                    'in_timestamp' => time(),
                    );
                $this->db->insert('sms_masuk', $inbox);
                $this->mtrx->set_sukses($trx, $inbox['in_message']);
            } else {
                $this->db->where('tr_id', $trx->tr_id);
                $this->db->set('tr_status', 'dalam_proses');
                $this->db->update('transaksi');
            }
        }
    }

    protected function send_sms_jabber()
    {
        $disabled_trx = $this->input->get_post('disabled_trx') ? true : false;
        $accept_sms = $this->input->get_post('accept_sms');
        if ($this->input->get_post('jabber')) {
            $jabber_active = $this->input->get_post('jabber');
        } else {
            $jabber_active = 'yes';
        }

        if (strpos($accept_sms, '.') !== false)
            $accept_sms = explode('.', $accept_sms);

        if (!$disabled_trx)
            $sms = $this->sms_trx();
        else
            $sms = array();

        if ($jabber_active == 'yes')
            $jabber = $this->jabber_trx();
        else
            $jabber = array();

        if ($jabber_active != 'yes')
            $this->db->where('out_type', 'sms');
        $this->db->where('out_status', '');
        $this->db->order_by('out_id', 'ASC');
        $this->db->limit(10);
        $query = $this->db->get('sms_keluar');

        if ($query->num_rows()) {
            foreach ($query->result() as $outbox) {
                if ($outbox->out_type == 'sms') {
                    $to = $outbox->out_to;
                    if (substr($to, 0, 3) == '628')
                        $to = '08' . substr($to, 3);

                    if (is_array($accept_sms) && !in_array(substr($to, 0, 4), $accept_sms))
                        continue;
                    
                    preg_match("/Kode verifikasi Nomor HP kamu adalah ([0-9]{5}+)/s", $outbox->
                        out_message, $matches);
                    if ($matches)
                        $outbox->out_message = parse_url(site_url(), PHP_URL_HOST).": " . $matches[1];

                    $sms[] = array(
                        'id' => "sms." . $outbox->out_id,
                        'to' => $to,
                        'message' => $outbox->out_message,
                        );
                } elseif ($outbox->out_type == 'jabber') {
                    $jabber[] = array(
                        'id' => "sms." . $outbox->out_id,
                        'to' => $outbox->out_to,
                        'message' => $outbox->out_message,
                        );
                }

                $this->db->where('out_id', $outbox->out_id);
                $this->db->set('out_status', '-');
                $this->db->update('sms_keluar');
            }
        }
        if ($sms) {
            $this->events[] = array(
                'event' => 'send_sms',
                'messages' => $sms,
                );
        }
        if ($jabber) {
            $this->events[] = array(
                'event' => 'send_jabber',
                'messages' => $jabber,
                );
        }
    }

    protected function sms_trx()
    {
        $sms = array();
        $pending_trx = $this->mtrx->get_pending_trx(array('sms', 'otomax_api_sms'));

        if (!$pending_trx)
            return $sms;

        foreach ($pending_trx as $trx) {
            if ($trx->vo_kode_fisik) {
                $this->mtrx->trx_voucher_fisik($trx);
            } else {
                if ($trx->sv_gateway == 'otomax_api_sms' && (int)$trx->tr_retry == 0)
                    continue;
                $sms[] = array(
                    'id' => "isi." . $trx->tr_id,
                    'to' => $trx->sv_sms_center,
                    'priority' => 1,
                    'message' => $this->mtrx->get_format_trx($trx),
                    );
                $this->db->where('sv_id', $trx->sv_id);
                $this->db->set('sv_saldo', $trx->sv_saldo - $trx->tr_harga2);
                $this->db->update('server');
                $this->mtrx->set_proses($trx);
            }
        }
        return $sms;
    }

    protected function jabber_trx()
    {
        $cfg = json_decode($this->system->get_set('jabber_api'));
        if (!$cfg->server_url || !$cfg->username || !$cfg->password) {
            $jabber_api = false;
        } else {
            $jabber_api = true;
        }

        $jabber = array();
        $pending_trx = $this->mtrx->get_pending_trx(array('jabber'));

        if (!$pending_trx)
            return $jabber;

        foreach ($pending_trx as $trx) {
            if ($trx->vo_kode_fisik) {
                $this->mtrx->trx_voucher_fisik($trx);
            } else {
                if ($jabber_api && (int)$trx->tr_retry == 0)
                    continue;
                $jabber[] = array(
                    'id' => "isi." . $trx->tr_id,
                    'to' => $trx->sv_jabber_center,
                    'message' => $this->mtrx->get_format_trx($trx),
                    );
                $this->db->where('sv_id', $trx->sv_id);
                $this->db->set('sv_saldo', $trx->sv_saldo - $trx->tr_harga2);
                $this->db->update('server');
                $this->mtrx->set_proses($trx);
            }
        }
        return $jabber;
    }

    protected function get_notifications()
    {
        $notifications = array();
        $this->db->where('nf_admin', '1');
        $this->db->where('nf_baca', '0');
        $this->db->order_by('nf_id', 'DESC');
        $this->db->limit(5);
        $query = $this->db->get('notifikasi');
        if ($query->num_rows()) {
            $results = array_reverse($query->result());
            foreach ($results as $res) {
                $notifications[] = array(
                    'id' => (int)$res->nf_id,
                    'title' => $res->nf_judul,
                    'content' => $res->nf_teks,
                    'link' => site_url('akun/notifikasi/read/' . $res->nf_id),
                    'time' => (int)$res->nf_tanggal,
                    );
            }
        }
        $this->events[] = array(
            'event' => 'notification',
            'notifications' => $notifications,
            );
    }

    protected function is_validated($correct_password)
    {
        if ($this->input->get_post('password') && $this->input->get_post('password') ==
            $correct_password) {
            return true;
        }
        $signature = @$_SERVER['HTTP_X_REQUEST_SIGNATURE'];
        if (!$signature) {
            return false;
        } elseif ($signature == $correct_password) {
            return true;
        } else {
            return false;
        }
    }

    protected function display_output($data = array())
    {
        $this->output->set_content_type('application/json', 'utf-8');
        $this->output->set_output(json_encode($data));
        $this->output->_display();
        exit();
    }
}
