<?php

if (!defined('DISPLAY_ERRORS')) {
    define('DISPLAY_ERRORS', false);
}

function errorPost($msg = [], $code = 422) {
    if (!is_array($msg) || count($msg) == 0) {
        $msg = ['Something went wrong during the request. Contact an IT-supporter.'];
    }

    http_response_code($code === 404 ? 404 : 422);

    $array = [];

    foreach ($msg as $key => $val) {
        if (is_array($val)) {
            $array[] = ['name' => $val['name'], 'msg' => $val['msg']];
        }
        else {
            $array[] = ['name' => $key, 'msg' => $val];
        }
    }

    //echo '{"message": ' . json_encode($array, JSON_PRETTY_PRINT) . '}';

    exit;
}

class DB {
    private $DB_CLOUDS     = 'clouds';
    private $SERVER_DB     = '35.240.38.241';
    private $DB_USER       = 'clouds';
    private $DB_PASS       = '32gmS56G4MxoUIvyFYfc';

    private $db            = null;
    private $name          = '';
    private $error         = null;
    private $executeResult = null;

    private $config = [];

    private $options = [
        PDO::ATTR_STRINGIFY_FETCHES => false,
        PDO::ATTR_EMULATE_PREPARES  => false,

        PDO::ATTR_CASE               => PDO::CASE_NATURAL,
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_ORACLE_NULLS       => PDO::NULL_EMPTY_STRING,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ];

    public function __construct($name, $config = null) {
        $this->config[$this->DB_CLOUDS] = [
            'server'   => $this->SERVER_DB,
            'username' => $this->DB_USER,
            'password' => $this->DB_PASS,
        ];

        if ($config && is_array($config)) {
            $this->config[$config['name']] = $config['data'];
        }

        $this->db($name);
        $this->name = $name;
    }

    public function __destruct() {
        $this->db = null;
    }

    private function db($name) {
        global $__DBS;

        $name = strtolower($name);

        if (!isset($this->config[$name])) {
            return -1;
        }

        if (!isset($__DBS[$name])) {
            try {
                $config = $this->config[$name];

                $__DBS[$name] = new PDO('mysql:host=' . $config['server'] . ';dbname=' . $name . ';collation=utf8mb4_unicode_ci', $config['username'], $config['password'], $this->options);
            }
            catch (PDOException $err) {
                unset($__DBS[$name]);

                return -1;
            }
        }

        $this->db = $__DBS[$name];
    }

    public function query($sql, $data = []) {
        $this->error         = null;
        $this->executeResult = null;

        try {
            if (empty($sql)) {
                throw new Exception('Query cannot be empty');
            }

            if (!is_array($data)) {
                throw new Exception('Data needs to be an array');
            }

            if ($this->db == null) {
                throw new Exception('Database connection is broken');
            }

            //var_dump($sql);
            

            $stmt = $this->db->prepare($sql);
            

            foreach ($data as $key => $val) {
                if (is_string($key)) {
                    $stmt->bindValue($key, $val);
                }
            }

            $this->executeResult = $stmt->execute();

            return $stmt;
        }
        catch (PDOException $err) {
            $this->error = $err;

            if (DISPLAY_ERRORS) {
                var_dump($err);
            }

            return false;
        }
        catch (Exception $err) {
            $this->error = $err;

            if (DISPLAY_ERRORS) {
                var_dump($err);
            }

            return false;
        }
    }

    /**
     * Gets the last inserted id
     * @return int
     */
    public function getLastId() {
        return $this->db->lastInsertId();
    }

    public function getRow($table, $data = [], $conjunction = ' AND ', $search = 0, $order = '') {
        $where   = [];
        $newData = [];

        foreach ($data as $key => $datum) {
            if (substr($key, -3) == '-op') {
                continue;
            }

            if (!$search) {
                $datakey                 = str_replace('`', '', $key);
                $where[]                 = $key . ($data[str_replace('`', '', $key) . '-op'] ?? '=') . ':' . $datakey;
                $newData[':' . $datakey] = $datum;
            }
            else {
                $where[] = $key . " LIKE '%" . $datum . "%'";
            }
        }

        $sql = 'SELECT * FROM ' . $table . (count($where) > 0 ? ' WHERE ' : '') . implode($conjunction, $where) . ' ' . $order . ' LIMIT 1';

        $result = $this->query($sql, $newData);

        return $result && $result->rowCount() > 0 ? $result->fetch() : [];
    }

    public function getColl($table, $data = [], $conjunction = ' AND ', $search = false, $order = '') {
        $where   = [];
        $newData = [];

        foreach ($data as $key => $datum) {
            if (substr($key, -3) == '-op') {
                continue;
            }

            if (!$search) {
                $where[]             = $key . ($data[$key . '-op'] ?? '=') . ((!empty($data[$key . '-op']) ? $data[$key . '-op'] == ' IN ' : false) ? '(:' . $key . ')' : ':' . $key);
                $newData[':' . $key] = $datum;
            }
            else {
                $where[] = $key . " LIKE '%" . $datum . "%'";
            }
        }

        $sql = 'SELECT * FROM ' . $table . (count($where) > 0 ? ' WHERE ' : '') . implode($conjunction, $where) . ' ' . $order;

        $result = $this->query($sql, $newData);

        return $result && $result->rowCount() > 0 ? $result->fetchAll() : [];
    }

    public function insert($table, $data = []) {
        $fieds   = [];
        $values  = [];
        $newData = [];

        if (empty($data) || !is_array($data)) {
            errorPost(['name' => $data, 'msg' => 'Doesn\'t array exist']);

            return false;
        }

        foreach ($data as $key => $datum) {
            $fieds[]             = $key;
            $values[]            = ':' . $key;
            $newData[':' . $key] = $datum;
        }

        $sql = 'INSERT INTO ' . $table . ' (`' . implode('`, `', $fieds) . '`) VALUES (' . implode(', ', $values) . ')';

        $result = $this->query($sql, $newData);

        return $result;
    }

    public function update($table, $setData, $data = [], $conjunction = ' AND ') {
        $setField = [];
        $where    = [];

        $newData = [];

        if (empty($setData) || !is_array($setData)) {
            errorPost(['name' => $setData, 'msg' => 'Doesn\'t array exist']);

            return false;
        }

        foreach ($setData as $key => $datum) {
            $setField[]          = '`' . $key . '`=:' . $key;
            $newData[':' . $key] = $datum;
        }

        if (empty($data) || !is_array($data)) {
            errorPost(['name' => $data, 'msg' => 'Doesn\'t array exist']);

            return false;
        }

        foreach ($data as $key => $datum) {
            $tmp           = ':' . $key . time();
            $where[]       = $key . '=' . $tmp;
            $newData[$tmp] = $datum;
        }

        $sql = 'UPDATE ' . $table . (count($setField) > 0 ? ' SET ' : '') . implode(', ', $setField) . (count($where) > 0 ? ' WHERE ' : '') . implode($conjunction, $where);

        return $this->query($sql, $newData);
    }

    public function delete($table, $data = [], $conjunction = ' AND ', $operator = null, $iteration = null) {
        $where = [];
        $i     = 1;

        if (empty($data)) {
            errorPost(['name' => $data, 'msg' => 'Doesn\'t array exist']);

            return false;
        }

        if (is_array($data)) {
            foreach ($data as $key => $datum) {
                $where[] = $key . ($iteration == $i ? $operator : '=') . $datum;
                $i++;
            }
        }
        else {
            errorPost(['name' => $data, 'msg' => 'Doesn\'t array exist']);

            return false;
        }

        $sql = 'DELETE FROM ' . $table . (count($where) > 0 ? ' WHERE ' : '') . implode($conjunction, $where);

        $result = $this->query($sql);

        return $result;
    }

    public function jsonEncodedError() {
        return json_encode($this->error, JSON_PRETTY_PRINT);
    }
}

if (!empty($_GET['uuid']) && !empty($_GET['k'])) {
    $dbClouds = new DB('clouds');

    $__RB_session = $dbClouds->getRow('session', ['`uuid`' => $_GET['uuid'], '`key`' => $_GET['k']]);

    if (!$__RB_session) {
        http_response_code(404);

        exit;
    }

    $_SESSION['accepted_ref'] = $_GET['k'];
    $_SESSION['returnPage'] = $__RB_session['return'];
    
    $returnPage = $_SESSION['returnPage'];

    if (substr($returnPage, -3) == 'php') {
        $returnPage = explode('/', $returnPage);
        
        array_pop($returnPage);

        $returnPage = implode('/', $returnPage);
    }

    if (substr($returnPage, -1) == '/') {
        $returnPage = substr($returnPage, 0, -1);
    }

    $dbClouds->update('session', ['set' => 1], ['uuid' => $_GET['uuid']]);

    header('location: ' . $returnPage . '/checkout.php?uuid='. $_GET['uuid']);

    exit;
}

if (!empty($_GET['uuid']) && !empty($_GET['a']) && in_array($_GET['a'], ['checkout', 'thankyou'])) {
    $returnPage = $_SESSION['returnPage'];

    if (substr($returnPage, -3) == 'php') {
        $returnPage = explode('/', $returnPage);
        
        array_pop($returnPage);

        $returnPage = implode('/', $returnPage);
    }

    if (substr($returnPage, -1) == '/') {
        $returnPage = substr($returnPage, 0, -1);
    }

    if ($_GET['a'] == 'checkout') {
        remoteSessionChecker();

        $returnPage .= '/checkout.php?error=1&uuid=' . $_GET['uuid'];

    } else {
        $var = $_SESSION['returnPage'];

        $var = explode('/', $var);
        $lng = array_pop($var);

        if (empty($lng) || strpos($lng, '.') !== false) {
            $lng = array_pop($var);
        }

        $template = array_pop($var);

        include(__DIR__ .'/cp/'. $template .'/'. $lng .'/thankyou.php');

        exit;

        $returnPage .= '/thankyou.php';
    }

    header("location: " . $returnPage);

    exit;
}

if (!empty($_POST['submitTo3d']) && !empty($_GET['uuid'])) {
    remoteSessionChecker();

    $executeTo3d = json_decode($_POST['submitTo3d'], true);

    if (!empty($executeTo3d['script'])) {
        echo "<html><head></head><body><script>". $executeTo3d['script'] ." </script></body></html>";

        exit;
    }

    if (!empty($executeTo3d['url'])) {
        echo "<script>window.location = '". $executeTo3d['script'] ."';</script>";

        exit;
    }

    http_response_code(404);

    exit;
}

function remoteSessionChecker() {
    $dbClouds = new DB('clouds');

    $__RB_session = $dbClouds->getRow('session', ['uuid' => $_GET['uuid']]);

    if (!$__RB_session || empty($_SESSION['accepted_ref']) || $__RB_session['key'] != $_SESSION['accepted_ref']) {
        http_response_code(404);

        exit;
    }
}