<?php
namespace Plugin\VIP;

class VIP {
    private $_removePlatinumPackage = true;
    private $serverFiles;
    private $_configXml = 'config.xml';
    private $_modulesPath = 'modules';
    private $_configId;
    private $_vipTypeData;
    private $_username;
    private $_type;
    private $_days;
    private $_realm;
    private $_usercpmenu = array(
        array('active'=>true,'type'=>'internal','phrase'=>'vip_title','link'=>'vip/info','icon'=>'vip.png','visibility'=>'user','newtab'=>false,'order'=>110)
    );
    private $config;
    private $me;
    private $configFilePath;

    public function __construct() {
        $this->config = webengineConfigs();
        $this->serverFiles = strtolower($this->config['server_files']);
        $this->_realm = class_exists('NexoraRealm') ? \NexoraRealm::active() : null;
        $this->me = \Connection::Database('Me_MuOnline', $this->_realm);
        $this->configFilePath = self::configPath($this->_realm);
        if(!file_exists($this->configFilePath)) throw new \Exception(lang('vip_error_2'));
        $xml = simplexml_load_file($this->configFilePath);
        if(!$xml) throw new \Exception(lang('vip_error_2'));
        $this->_configId = (int)$xml->credit_config;
        if($this->_configId === 0) throw new \Exception(lang('vip_error_12'));
        $this->_vipTypeData = array(
            1 => $this->buildType($xml, 1, 'vip_title_type_1'),
            2 => $this->buildType($xml, 2, 'vip_title_type_2'),
            3 => $this->buildType($xml, 3, 'vip_title_type_3'),
            4 => $this->buildType($xml, 4, 'vip_title_type_4'),
        );
        if($this->serverFiles != 'igcn' && $this->_removePlatinumPackage) unset($this->_vipTypeData[4]);
    }

    public static function configPath($realm=null) {
        if(class_exists('NexoraRealm')) {
            try {
                $realm = \NexoraRealm::validate($realm === null ? \NexoraRealm::active() : $realm);
                $realmPath = __PATH_VIP_ROOT__.'config.'.$realm.'.xml';
                if(is_file($realmPath)) return $realmPath;
            } catch(\Throwable $e) {}
        }
        return __PATH_VIP_ROOT__.'config.xml';
    }

    private function buildType($xml, $type, $phrase) {
        return array(
            'enabled'=>(int)$xml->{'enable_vip_type_'.$type},
            'title'=>lang($phrase),
            'packages'=>array_values(array_filter(array_map('intval', explode(',', (string)$xml->{'vip_packages_'.$type})), function($v){return $v>0;})),
            'discounts'=>array_map('intval', explode(',', (string)$xml->{'vip_discount_'.$type})),
            'cost'=>(int)$xml->{'vip_cost_per_day_'.$type},
        );
    }

    public function loadModule($module) {
        if(!\Validator::Alpha($module) || !$this->_moduleExists($module)) throw new \Exception(lang('vip_error_3'));
        if(!@include_once(__PATH_VIP_ROOT__.$this->_modulesPath.'/'.$module.'.php')) throw new \Exception(lang('vip_error_3'));
    }
    public function isVipTypeEnabled($type) { return isset($this->_vipTypeData[(int)$type]) ? $this->_vipTypeData[(int)$type]['enabled'] : null; }
    public function getVipTypePackage($type) { return isset($this->_vipTypeData[(int)$type]) ? $this->_vipTypeData[(int)$type]['packages'] : null; }
    public function getVipCost($days=1, $type=1) {
        $type=(int)$type; $days=(int)$days;
        if(!isset($this->_vipTypeData[$type])) return null;
        $discount=0;
        foreach($this->_vipTypeData[$type]['packages'] as $key=>$value) if($days===$value && isset($this->_vipTypeData[$type]['discounts'][$key])) $discount=(int)$this->_vipTypeData[$type]['discounts'][$key];
        $result=$days*$this->_vipTypeData[$type]['cost'];
        if($discount>0) $result=$result*((100-$discount)/100);
        return (int)round($result);
    }
    public function setUsername($username) { if(\Validator::UsernameLength($username)) $this->_username=$username; }
    public function setVipType($type) { $type=(int)$type; if(!isset($this->_vipTypeData[$type])) throw new \Exception(lang('vip_error_5')); $this->_type=$type; }
    public function setVipPackage($days) { $days=(int)$days; if(!$this->_type || !in_array($days,$this->_vipTypeData[$this->_type]['packages'],true)) throw new \Exception(lang('vip_error_6')); $this->_days=$days; }

    public function getVip() {
        if(!$this->_username || !$this->_type || !$this->_days) throw new \Exception(lang('vip_error_8'));
        if(!$this->_vipTypeData[$this->_type]['enabled']) throw new \Exception(lang('vip_error_5'));
        $accountInfo=(new \Account())->accountInformation($_SESSION['userid']);
        if(!is_array($accountInfo)) throw new \Exception(lang('vip_error_10'));
        $creditSystem=new \CreditSystem();
        $creditSystem->setConfigId($this->_configId);
        $configInfo=$creditSystem->showConfigs(true);
        switch($configInfo['config_user_col_id']) {
            case 'userid': $identifier=$accountInfo[_CLMN_MEMBID_]; break;
            case 'username': $identifier=$accountInfo[_CLMN_USERNM_]; break;
            case 'email': $identifier=$accountInfo[_CLMN_EMAIL_]; break;
            default: throw new \Exception(lang('vip_error_7'));
        }
        $cost=$this->getVipCost($this->_days,$this->_type);
        $economy=new \NexoraEconomy($this->_realm);
        $economy->vipPurchase($this->_configId,$identifier,$this->_username,$this->_type,$this->_days,$cost);
        redirect(1,'vip/info/success/1/');
    }

    public function isAccountVip() {
        if(!$this->_username) throw new \Exception(lang('vip_error_4'));
        $data=$this->_getAccountVipData();
        if(!is_array($data) || !isset($data[_CLMN_VIP_TYPE_]) || !isset($this->_vipTypeData[(int)$data[_CLMN_VIP_TYPE_]])) return false;
        if(empty($data[_CLMN_VIP_DATE_])) return false;
        return time() < strtotime($data[_CLMN_VIP_DATE_]);
    }
    public function getAccountVipData() { if(!$this->_username) throw new \Exception(lang('vip_error_4')); return $this->_getAccountVipData(); }
    public function getVipTypeData() { return $this->_vipTypeData; }
    public function getRealm() { return $this->_realm; }
    public function getConfigId() { return $this->_configId; }

    public static function issuePurchaseToken() {
        if(session_status()!==PHP_SESSION_ACTIVE) return '';
        $token=bin2hex(random_bytes(24));
        $_SESSION['nexora_vip_purchase_token']=$token;
        $_SESSION['nexora_vip_purchase_token_at']=time();
        return $token;
    }
    public static function consumePurchaseToken($token) {
        if(session_status()!==PHP_SESSION_ACTIVE) return false;
        $expected=isset($_SESSION['nexora_vip_purchase_token']) ? (string)$_SESSION['nexora_vip_purchase_token'] : '';
        $at=isset($_SESSION['nexora_vip_purchase_token_at']) ? (int)$_SESSION['nexora_vip_purchase_token_at'] : 0;
        unset($_SESSION['nexora_vip_purchase_token'],$_SESSION['nexora_vip_purchase_token_at']);
        return $expected!=='' && is_string($token) && hash_equals($expected,$token) && $at>0 && (time()-$at)<=900;
    }

    public function checkPluginUsercpLinks() {
        $cfg=loadConfig('usercp'); if(!is_array($cfg)) return;
        $links=array(); foreach($cfg as $row) if(isset($row['link'])) $links[]=$row['link'];
        foreach($this->_usercpmenu as $row) if(!in_array($row['link'],$links,true)) $cfg[]=$row;
        usort($cfg,function($a,$b){return ((int)$a['order'])<=>((int)$b['order']);});
        $json=json_encode($cfg,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
        if(file_put_contents(__PATH_CONFIGS__.'usercp.json',$json,LOCK_EX)===false) throw new \Exception('No se pudo actualizar el menu UserCP.');
    }

    protected function _getAccountVipData() {
        return $this->me->query_fetch_single('SELECT '._CLMN_VIP_ID_.', '._CLMN_VIP_TYPE_.', '._CLMN_VIP_DATE_.' FROM '._TBL_VIP_.' WHERE '._CLMN_VIP_ID_.' = ?',array($this->_username));
    }
    private function _moduleExists($module) { return is_file(__PATH_VIP_ROOT__.$this->_modulesPath.'/'.$module.'.php'); }
}
