<?php

namespace Extension\VisitorBlocker;

use Application\Config;
use Application\CrmPayload;
use Application\CrmResponse;
use Application\Session;
use Application\Request;
use Exception;
use Database\Connectors\ConnectionFactory;
use DateTime;
use Application\Model\Configuration;

class RedirectUsers
{

    private $currentStepId, $currentPageType;
    private $database, $tableName, $configId;

    public function __construct()
    {
        $this->visitorBlockerConfig = Config::extensionsConfig('VisitorBlocker');
        $this->currentStepId        = (int) Session::get('steps.current.id');
        $this->currentPageType      = Session::get('steps.current.pageType');
        $this->database             = STORAGE_DIR . DS . 'redirectusers.sqlite';
        $this->tableName            = 'redirectlogs';
        $this->ip                   = Request::getClientIp();

        $this->configId = (int) Session::get('steps.current.configId');
        try {
            $this->configuration = new Configuration($this->configId);
        } catch (Exception $ex) {
        }
        $this->createTable();
    }

    public function increaseIPLimitCount()
    {
        if (Request::attributes()->get('action') === 'prospect' || empty($this->visitorBlockerConfig['enable_order_limit_on_ip'])) {
            return;
        }

        if ($this->currentStepId > 1) {
            return;
        }

        $allowedIPs = preg_split('/\r\n|\r|\n/', $this->visitorBlockerConfig['redirect_user_ip_whitelists']);

        if (in_array($this->ip, $allowedIPs)) {
            return;
        }

        $response = CrmResponse::all();
        
        $allowPrepaid = Config::configurations(sprintf(
            '%s.accept_prepaid_cards', $this->configId
        ));

        if( preg_match("/Prepaid.+Not Accepted|Prepaid.+not allowed/i", $response['errors']['crmError']) && !empty($response['errors']['crmError']) && !empty($allowPrepaid)) {
            return;
        }

        if (empty($response['success']) && $response['errors']) {
            return;
        }

        $email = CrmPayload::get('email');
        $list = $this->getDbInfo($this->ip);
        if(!$list) {
            //insert new
            $time = new DateTime();
            $this->insert(array(
                'email'            => $email,
                'ip_address'       => $this->ip,
                'user_block_count' => 1, 
                'date'             => $time->format("Y-m-d H:i:s"),
            ));
        }
        else {
            //update
            $time = new DateTime();
            $tempId = current($list)['id'];
            $numberOfBlock = (int) current($list)['user_block_count'];
            $this->update($tempId, array(
                'user_block_count' => $numberOfBlock + 1,
                'date'             => $time->format("Y-m-d H:i:s"),
            ));
        }
    }

    public function checkIPLimit()
    {
        if (empty($this->visitorBlockerConfig['enable_order_limit_on_ip'])) {
            return;
        }

        if ($this->currentPageType != 'leadPage') {
            return;
        }

        $allowedIPs = preg_split('/\r\n|\r|\n/', $this->visitorBlockerConfig['redirect_user_ip_whitelists']);

        if (in_array($this->ip, $allowedIPs)) {
            return;
        }

        $maxBlockLimit = $this->visitorBlockerConfig['order_ip_limit'];
        $redirectUrl   = $this->visitorBlockerConfig['ip_limit_redirect_url'];

        $userData = $this->getDbInfo($this->ip);

        if (!$userData) {
            return;
        }

        $blockCount = (int) current($userData)['user_block_count'];
        $id         = (int) current($userData)['id'];
        if ($blockCount >= $maxBlockLimit) {
            try {
                $this->createConnection()->table($this->tableName)
                    ->where('id', '=', $id)
                    ->update(array(
                        'status' => 1
                    ));
            } catch (Exception $ex) {
            }

            header('Location: ' . $redirectUrl);
            exit;            
        }
        
    }

    private function createTable()
    {
        try {
            $sql = "CREATE TABLE IF NOT EXISTS '" . $this->tableName . "' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 'email' TEXT, 'ip_address' TEXT, 'user_block_count' TEXT, 'status' BOOLEAN, 'date' DATETIME)";
            $query = $this->createConnection()->query($sql);
            return true;
        } catch (Exception $ex) {

        }
    }

    /*
     * This function used Database\Connectors\ConnectionFactory class 
     */
    private function createConnection()
    {
        try {
            if (!extension_loaded('pdo_sqlite')) {
                //throw new Exception('PDO extension does not exists');
            }
            if (!file_exists($this->database)) {
                file_put_contents($this->database, '');
            }
            if (!is_writable($this->database)) {
                //throw new Exception('Check write permission of database file');
            }
            $factory    = new ConnectionFactory();
            $connection = $factory->make(array(
                'driver'   => 'sqlite',
                'database' => $this->database,
            ));
            return $connection;
        } catch (Exception $ex) {
            
        }
    }

    public function getDbInfo($ip)
    {
        try {
            $query =  $this->createConnection()->table($this->tableName)->select('id', 'email', 'ip_address', 'user_block_count');
            $query->where('ip_address', '=', $ip);
            $list = $query->get();
        } catch (Exception $ex) {
        }

        if (!empty($list)) {
            return $list;
        }

        return $list = !empty($list) ? $list : false;
    }

    /*
     * This function will insert data into table
     */
    private function insert($data)
    {
        try {
            $this->createConnection()->table($this->tableName)->insert($data);
            return;
        } catch (Exception $ex) {
        }
    }

    /*
     * Update data
     */
    private function update($id, $data)
    {
        try {
            $this->createConnection()->table($this->tableName)
                ->where('id', '=', $id)
                ->update($data);
            return;
        } catch (Exception $ex) {
            
        }
    }
}
