<?php

class Transaction extends CI_Controller {
    private $response;
    private $table;
    private $column_order;
    private $column_search;
    private $request;
    private $format;


    public function __construct(){
        parent::__construct();
        $this->load->database();
        $this->response = array(
            'draw' => 0,
            'recordsTotal' => 0,
            'recordsFiltered' => 0,
            'data' => array()
        );
        $this->format = 'j M Y';
        $this->table = $this->db->dbprefix."transactions";
        $this->request = $this->input->post(null, true);
        $this->column_order = array(
            0 => "aclcreated",
            1 => "name",
            2 => "emailAddr",
            3 => "sellingcurrencyamount",
            4 => "aclbdtamount",
            5 => "aclgatewayfee",
            6 => "aclmethod",
        );
        $this->column_search = array(
            "aclmethod",
            "acldescription",
            "aclmethodnote",
            "paymenttypeid",
            "transid",
            "emailAddr",
            "userid",
            "usertype",
            "transactiontype",
            "invoiceids",
            "debitnoteids",
            "description",
            "redirecturl",
            "telNo",
        );
    }

    public function index(){
        if($this->input->is_ajax_request() && $this->session->has_userdata('logged')) {
            $bindings = array();
            $where = $this->filter($bindings);
            $limit = $this->limit();
            $order = $this->order();
            $select = " SELECT * ";
            $count = " SELECT COUNT(*) as count ";
            $from = " FROM `".$this->table."` ";

            $data_sql = $this->aclClean($select.$from.$where.$order.$limit);
            $total_sql = $this->aclClean($count.$from);
            $filter_sql = $this->aclClean($count.$from.$where);

            $data_result = !empty($bindings) ? $this->db->query($data_sql, $bindings) : $this->db->query($data_sql);
            $data_result = $data_result ? $data_result->result() : array();
            $total_result = $this->db->query($total_sql);
            $total_result = $total_result ? $total_result->row(0) : array();
            $filter_result = !empty($bindings) ? $this->db->query($filter_sql, $bindings) : $this->db->query($filter_sql);
            $filter_result = $filter_result ? $filter_result->row(0) : array();

            if(!empty($data_result) && !empty($total_result) && !empty($filter_result) ) {

                $rows = array();
                foreach ($data_result as $transaction) {
                    $row = array();
                    $actions = array();
                    $tags = array($this->aclDecodeStatus($transaction->aclstatus, $transaction->aclrequested, true));
                    if($transaction->acldisableexpire=='1' && $transaction->aclstatus!='C'){
                        $tags[] = '<span class="badge bg-orange" data-toggle="tooltip" data-placement="bottom" title="There is no time restriction. Expired transaction is allowed">Unrestricted</span>';
                    }

                    if($transaction->aclmanual=='1'){
                        $tags[] = '<span class="badge bg-blue-grey" data-toggle="tooltip" data-placement="bottom" title="Transaction paid manually">Manual</span>';
                    }

                    $actions[] = '<a class="btn btn-xs btn-default aclreview transaction" acl-review="'.$transaction->aclreference.'" data-toggle="tooltip" data-placement="bottom" title="Review Transaction" href="javascript:void(0)"><i class="acl-icon-info-circled" aria-hidden="true"></i></a>';

                    if($transaction->aclstatus=='N') {
                        if($transaction->aclrequested=='0') {
                            $actions[] = '<a class="btn btn-xs btn-default" data-toggle="tooltip" data-placement="bottom" title="Go to Payment" href="'.base_url('payment/'.$transaction->aclmethod.'?acl='.urlencode(base64_encode($transaction->transid))).'"><i class="acl-icon-export-4" aria-hidden="true"></i></a>';
                        }
                        if($transaction->acldisableexpire=='0' && $transaction->aclmethod=='bkash') {
                            $actions[] = '<a class="btn btn-xs btn-primary aclexpired transaction" acl-expired="'.$transaction->aclreference.'" data-toggle="tooltip" data-placement="bottom" title="Allow Expired Transaction" href="javascript:void(0)"><i class="acl-icon-clock-7" aria-hidden="true"></i></a>';
                        }
                        if($transaction->aclmethod == 'bkash' || ($transaction->aclrequested=='1')) {
                            $payAction = $transaction->aclmethod == 'bkash' ? 'aclpay bkash':'aclpay dynamic';
                            $actions[] = '<a class="btn btn-xs btn-success '.$payAction.'" acl-pay="'.$transaction->aclreference.'" data-toggle="tooltip" data-placement="bottom" title="Pay Transaction" href="javascript:void(0)"><i class="acl-icon-ok-circled-1" aria-hidden="true"></i></a>';
                        }
                        $actions[] = '<a class="btn btn-xs btn-warning aclcancel transaction" acl-cancel="'.$transaction->aclreference.'" data-toggle="tooltip" data-placement="bottom" title="Cancel Transaction" href="javascript:void(0)"><i class="acl-icon-minus-circled-1" aria-hidden="true"></i></a>';
                    } else if($transaction->aclstatus=='Y') {
                        $actions[] = '<a class="btn btn-xs btn-default aclrollback transaction" acl-rollback="'.$transaction->aclreference.'" data-toggle="tooltip" data-placement="bottom" title="Unpaid Transaction" href="javascript:void(0)"><i class="acl-icon-cw-circle" aria-hidden="true"></i></a>';
                    }

                    $actions[] = '<a class="btn btn-xs btn-danger aclremove transaction" acl-remove="'.$transaction->aclreference.'" data-toggle="tooltip" data-placement="bottom" title="Remove Transaction" href="javascript:void(0)"><i class="acl-icon-trash-6" aria-hidden="true"></i></a>';

                    $row[0] = xss_clean(strtoupper($this->aclGetDate($transaction->aclcreated, "j M Y, g:i a")));
                    $row[0] .= !empty($tags) ? "<br> ".implode(' ', $tags) : "";
                    $row[1] = xss_clean($transaction->aclreference);
                    $row[2] = xss_clean($transaction->name);
                    $row[3] = xss_clean($transaction->emailAddr);
                    $row[4] = xss_clean($transaction->sellingcurrencyamount . ' '.strtoupper($transaction->resellerCurrency)) ;
                    $row[5] = number_format( $transaction->aclbdtamount+$transaction->aclgatewayfee, 1, '.', '' ) . ' BDT';
                    $row[6] = $transaction->aclgatewayfee;
                    $row[7] = $transaction->aclmethod;
                    $row[8] = implode(' ', $actions);
                    $rows[] = $row;
                }

                $this->response['data'] = $rows;
                $this->response['draw'] = intval($this->request['draw']);
                $this->response['recordsTotal'] = intval($total_result->count);
                $this->response['recordsFiltered'] = intval($filter_result->count);
            }
        }

        $this->sendResponse();
    }

    private function aclDecodeStatus($state, $requested='0', $tag=false) {
        $status = array(
            "Y" => "Paid",
            "N" => "Unpaid",
            "C" => "Cancelled"
        );

        $tag = array(
            "Y" => "bg-green",
            "N" => "bg-red",
            "C" => "bg-grey"
        );

        return array_key_exists($state, $status) ? ( $state=='N' && $requested=='1' ? (
            $tag ? '<span class="badge bg-orange">Pending</span>': 'Pending'
        ) : (
            $tag ? '<span class="badge '.$tag[$state].'">'.$status[$state].'</span>': $status[$state] )
        ) : (
            $tag ? '<span class="badge bg-black">Unknown</span>': 'Unknown'
        );
    }

    private function limit ( )
    {
        $limit = '';
        if ( isset($this->request['start']) && $this->request['length'] != -1 ) {
            $limit = " LIMIT ".intval($this->request['start']).", ".intval($this->request['length']);
        }

        return $limit;
    }

    private function order ()
    {
        $order = '';

        if ( isset($this->request['order']) && count($this->request['order']) ) {
            $orderBy = array();
            for ( $i=0, $ien=count($this->request['order']) ; $i<$ien ; $i++ ) {

                $columnIdx = intval($this->request['order'][$i]['column']);
                $requestColumn = $this->request['columns'][$columnIdx];

                if(array_key_exists($requestColumn['data'], $this->column_order)){
                    if ( $requestColumn['orderable'] == 'true' ) {
                        $dir = $this->request['order'][$i]['dir'] === 'asc' ?
                            'ASC' :
                            'DESC';

                        $orderBy[] = ' `'.$this->column_order[$requestColumn['data']].'` '.$dir;
                    }
                }
            }

            $order = count($orderBy)>0?' ORDER BY '.implode(', ', $orderBy).' ':'';
        }

        return $order;
    }

    private function filter ( &$bindings )
    {
        $where = array();

        if(isset($this->request['email']) && !empty($email = trim($this->request['email']))) {
            array_push($where, ' `emailAddr` = ? ');
            $bindings[] = $email;
        }

        if(isset($this->request['trxid']) && !empty($trxid = trim($this->request['trxid']))) {
            array_push($where, ' `acltrxid` = ? ');
            $bindings[] = $trxid;
        }

        if( isset($this->request['datestart']) && !empty($datestart = trim($this->request['datestart'])) &&
            isset($this->request['dateend']) && !empty($dateend = trim($this->request['dateend'])) ) {
            if($this->aclVerify($datestart, $this->format) && $this->aclVerify($dateend, $this->format)){
                array_push($where, " ( `aclcreated` BETWEEN ? AND ? ) ");
                $bindings[] = $this->aclDateRange($datestart, $this->format);
                $bindings[] = $this->aclDateRange($dateend, $this->format, 2);
            }
        }

        if(isset($this->request['reference']) && !empty($reference = trim($this->request['reference']))) {
            array_push($where, ' `aclreference` = ? ');
            $bindings[] = $reference;
        }

        if(isset($this->request['status']) && !empty($status = trim($this->request['status']))) {
            if($status=='P') {
                array_push($where, " `aclstatus` = ? ");
                array_push($where, " `aclrequested` = ? ");
                $bindings[] = 'N';
                $bindings[] = '1';
            } else {
                array_push($where, ' `aclstatus` = ? ');
                $bindings[] = $status;
            }
        }

        if(isset($this->request['other']) && !empty($other = trim($this->request['other']))){
            $common = array();
            foreach ($this->column_search as $columns) {
                array_push($common, ' `'.$columns.'` LIKE ? ');
                $bindings[] = '%'.$other.'%';
            }

            if(!empty($common)) {
                array_push($where, ' ( ' . implode(' OR ', $common) . ' ) ');
            }
        }

        return count($where)>0?(
            ' WHERE ' . implode(' AND ', $where) . ' '
        ):'';
    }

    private function aclGetDate($date, $def = "Y-m-d H:i:s", $format = 'Y-m-d H:i:s')
    {
        $d = \DateTime::createFromFormat($format, $date);
        return $d->format($def);
    }

    private function aclDateRange($date, $format = 'Y-m-d H:i:s', $position=1){

        return ($position==2)?(
           $this->aclGetDate($date, "Y-m-d", $format) . " 23:59:59"
        ):(
            $this->aclGetDate($date, "Y-m-d", $format) . " 00:00:00"
        );
    }

    private function aclVerify($date, $format = 'Y-m-d H:i:s')
    {
        $d = \DateTime::createFromFormat($format, $date);
        return $d && $d->format($format) == $date;
    }

    private function aclClean($query) {
        return preg_replace('/\s+/', ' ', $query);
    }

    private function sendResponse(){
        header('Content-Type: application/json');
        echo json_encode($this->response);
        exit;
    }
}