<?php

namespace App\Controllers;

use App\Models\KeysModel;

class Connect extends BaseController {
    protected $model, $game, $key, $publicKey, $uuid;

    public function __construct() {
        $this->model = new KeysModel();
        $this->maintenance = false;
        $this->staticWords = 'Vm8Lk7Uj2JmsjCPVPVjrLa7zgfx3uz9E';
    }

    public function index() {
        if ($this->request->getMethod() == 'post' || $this->request->getPost()) {
            return $this->index_post();
        } else {
            $data = [
                'message' => 'Victus-Bapan',
                'web__dev' => [
                    'author' => '@bapanff',
                    'telegram' => 'https://t.me/bapanff',
                ],
            ];
            return $this->response->setStatusCode(401)->setJSON($data);
        }
    }

    public function XOR_encryption($value, $key) {
        $text = '';
        $k = 0;
        $klen = strlen($key);
        $vlen = strlen($value);

        for ($v = 0; $v < $vlen; $v++) {
            $text .= $value[$v] ^ $key[$k];
            $k = ($k + 1) % $klen;
        }
        return $text;
    }

    public function get_Key($publicKey) {
        $keyCrypto = $publicKey;
        $keyDes = '';
        $keyDes .= $keyCrypto[58 - 1];
        $keyDes .= $keyCrypto[62 - 1];
        $keyDes .= $keyCrypto[10 - 1];
        $keyDes .= $keyCrypto[47 - 1];
        $keyDes .= $keyCrypto[20 - 1];
        $keyDes .= $keyCrypto[33 - 1];
        $keyDes .= $keyCrypto[87 - 1];
        $keyDes .= $keyCrypto[98 - 1];
        $keyDes .= $keyCrypto[14 - 1];
        return $keyDes;
    }

    public function custom_encrypt_to_hex($plaintext, $key) {
        $encrypted = '';
        $keyLength = strlen($key);
        $plaintextLength = strlen($plaintext);
        for ($i = 0; $i < $plaintextLength; $i++) {
            $encrypted .= sprintf('%02x', ord($plaintext[$i]) ^ ord($key[$i % $keyLength]));
        }
        return $encrypted;
    }
    
    public function readFileData($path) {
        $file = fopen($path, "r") or die();
        $data = fread($file, filesize($path));
        fclose($file);
        return base64_encode($data);
    }

    public function verify() {
        if ($this->request->getMethod() == 'post') {
            $decKey = '1234766666';
            date_default_timezone_set('UTC');
            $currentTime = time();
            $token = 'VICTUS_YOHOHO' . $currentTime;
            $data = [
                'message' => $this->custom_encrypt_to_hex($token, $decKey),
            ];
            return $this->response->setStatusCode(200)->setJSON($data);
        } else {
            $data = [
                'message' => 'Victus-Bapan',
                'web__dev' => [
                    'author' => '@bapanff',
                    'telegram' => 'https://t.me/bapanff',
                ],
            ];
            return $this->response->setStatusCode(401)->setJSON($data);
        }
    }

    public function index_post() {
        $rawData = file_get_contents('php://input');
        $data = json_decode($rawData, true);
        $isMT = $this->maintenance;
        
        $game = $data['game'];
        $key = $data['key'];
        $publicKey = $data['publicKey'];
        $uuid = $data['hwid'];
        
        $form_rules = [
            'game' => 'required|alpha_dash',
            'key' => 'required|alpha_numeric|min_length[1]|max_length[90]',
            'hwid' => 'required|alpha_dash',
        ];
        
        if (!$this->validate($form_rules)) {
            $data = [
                'status' => false,
                'message' => "Auth Failed",
            ];
            return $this->response->setStatusCode(401)->setJSON($data);
        }
        
        if ($isMT) {
            $data = [
                'status' => false,
                'message' => 'Server is on maintenance',
            ];
        } else {
            if (!$game or !$key or !$uuid) {
                $data = [
                    'status' => false,
                    'message' => 'Something Went Wrong',
                ];
            } else {
                $time = new \CodeIgniter\I18n\Time();
                $model = $this->model;
                $findKey = $model->getKeysGame(['user_key' => $key, 'game' => $game]);
                if ($findKey) {
                    if ($findKey->status != 1) {
                        $data = [
                            'status' => false,
                            'message' => 'Your User Has Been Banned',
                        ];
                    } else {
                        $id_keys = $findKey->id_keys;
                        $duration = $findKey->duration;
                        $expired = $findKey->expired_date;
                        $max_dev = $findKey->max_devices;
                        $devices = $findKey->devices;

                        function checkDevicesAdd($serial, $devices, $max_dev) {
                            $lsDevice = explode(',', $devices);
                            $cDevices = isset($devices) ? count($lsDevice) : 0;
                            $serialOn = in_array($serial, $lsDevice);
                            if ($serialOn) {
                                return true;
                            } else {
                                if ($cDevices < $max_dev) {
                                    array_push($lsDevice, $serial);
                                    $setDevice = reduce_multiples(implode(',', $lsDevice), ',', true);
                                    return ['devices' => $setDevice];
                                } else {
                                    return false;
                                }
                            }
                        }

                        if (!$expired) {
                            $setExpired = $time::now()->addDays($duration);
                            $model->update($id_keys, ['expired_date' => $setExpired]);
                            $data['status'] = true;
                        } else {
                            if ($time::now()->isBefore($expired)) {
                                $data['status'] = true;
                            } else {
                                $data = [
                                    'status' => false,
                                    'message' => 'Your key has been expired',
                                ];
                            }
                        }

                        if ($data['status']) {
                            $devicesAdd = checkDevicesAdd($uuid, $devices, $max_dev);
                            if ($devicesAdd) {
                                if (is_array($devicesAdd)) {
                                    $model->update($id_keys, $devicesAdd);
                                }
                                $data = [
                                    'status' => true,
                                    'expire_date' => $expired,
                                    'message' => "Login Success",
                                    'rng' => $time->getTimestamp(),
                                    'load' => [
                                        'load_data' => $this->readFileData("loader/libserver.so"),
                                    ],
                                    'auth' => [
                                        'message' => $this->XOR_encryption('Yohohohohohoho Successsss Yohohohoho Nikaaaaaaaaaaa', $this->get_Key($publicKey)),
                                        'token_access' => $publicKey,
                                    ],
                                ];
                                return $this->response->setStatusCode(200)->setJSON($data);
                            } else {
                                $data = [
                                    'status' => false,
                                    'message' => 'Number of registered devices are max',
                                ];
                            }
                        } else {
                            $data = [
                                'status' => false,
                                'message' => 'Your key has been expired',
                            ];
                        }
                    }
                } else {
                    $data = [
                        'status' => false,
                        'message' => 'User Doesnt Exist',
                    ];
                }
            }
        }
        return $this->response->setStatusCode(401)->setJSON($data);
    }
}