<?php

class Loginer {

    public function loginCheck(){

        //logger("Loginer: ---- loginCheck() started");

        //cookies name (must change in every panel)
        $session_name = "logged_in" . COOKIE_SALT;
        $cookie1 = "fgpro" . COOKIE_SALT;
        $cookie2 = "token" . COOKIE_SALT;

        $functions = new Functions;

        $user_id = -1 ;

        if ( isset($_SESSION[$session_name]) ) {
            $user_id = $_SESSION[$session_name];
            //logger("Loginer: USER LOGIN VERIFIED BY: SESSION");
        }else if ( isset($_COOKIE[$cookie1]) && isset($_COOKIE[$cookie2])  ){
            //__gid2 is random 20 number + userid
            //token_2 is random generated string to verify user

            //logger("Loginer: There is Cookies Exist. Goting to check them");

        
            $fake_user_id = $_COOKIE[$cookie1];
            $token = $_COOKIE[$cookie2];
            $real_user_id = substr($fake_user_id, 20);

            //logger("Loginer: cookies data: token: " . $token . " userid: " . $real_user_id );
        
            $ret = db::exist( "SELECT * FROM `admins_auth` WHERE admin_id = ? AND token = ? ", [ $real_user_id, $token ] );
        
            if($ret){
        
                $auth_row = db::fetch( "SELECT * FROM `admins_auth` WHERE admin_id = ? AND token = ? ", [ $real_user_id, $token ] );
                
                $current_date = date("Y-m-d");
                $expire_date = $auth_row['expire'];

                //logger("Loginer: token verified with database. now check expire date: curr: " . $current_date . " exp: " . $expire_date );

                $today_dt = new DateTime($current_date);
                $expire_dt = new DateTime($expire_date);
        
                if($today_dt < $expire_dt){
                    //logger("Loginer: cookie not expired yet.");
                    //logger("Loginer: USER LOGIN VERIFIED BY: COOKIE (exp of login is: ".$expire_date);
                    //not expired yet
                    $user_id = $auth_row['admin_id'];

                    $_SESSION[$session_name] = $user_id;
                    //logger("Loginer: re new session done.");

                    //change the token for more security
                    $newtoken = $functions -> TokenGenerator();
                    //make userid token
                    $newfakeuserid = $functions -> RandomNumberGenerator() . $user_id;
        
                    //logger("re new token: " . $newtoken . "\n new__gid2: " .$newfakeuserid );
                    setcookie($cookie1, $newfakeuserid, time() + (60*60*24*30), "/");
                    setcookie($cookie2, $newtoken, time() + (60*60*24*30), "/");
                    
                    //we dont update expire in CHECK login.

                    if(
                        db::query("UPDATE `admins_auth` SET `token` = ? WHERE admin_id = ?" ,
                            [ 
                                $newtoken,
                                $user_id
                            ]
                        )
                    ){
                        //logger("Loginer: refresh token compelete.");
                    }else{
                        //logger("Loginer: refresh token failed!!!.");
                    }
                }else{
                    //logger("Loginer: Expire Date Has Reached : exp:" . $expire_date  . "  today is:" . $current_date ." dont verify user");
                }
        
            }else{
                //logger("Loginer: cookies are not in database! dont verify user");
                //logger("Loginer: Cant Find user_id And token in *admins_auth* table, so dont verify user");
            }
        
        }

        //logger("Loginer: ---- loginCheck() ended with result:".$user_id);
        return $user_id;

    }

    public function saveLogin ($user_id){

        $functions = new Functions;

        $session_name = "logged_in" . COOKIE_SALT;
        $cookie1 = "fgpro" . COOKIE_SALT;
        $cookie2 = "token" . COOKIE_SALT;

        $_SESSION[$session_name] = $user_id;
        //generate token for remember me function
        $newtoken = $functions -> TokenGenerator();
        //make userid token
        $newfakeuserid = $functions -> RandomNumberGenerator() . $user_id;

        //logger("save login newtoken: " . $newtoken . "\n new__gid2: " .$newfakeuserid );
        setcookie($cookie1, $newfakeuserid, time() + (60*60*24*30), "/");
        setcookie($cookie2, $newtoken, time() + (60*60*24*30), "/");

        
        $expire = date('Y-m-d', strtotime(' + 7 days'));

        //logger("new expire time: " . $expire);

        $auth_user_exist = db::exist( "SELECT * FROM `admins_auth` WHERE admin_id = ?", [ $user_id ] );
        if($auth_user_exist){

            $ret1 = db::query("UPDATE `admins_auth` SET `token` = ? , `expire` = ? WHERE admin_id = ?" ,
                [ 
                    $newtoken,
                    $expire,
                    $user_id
                ]
            );

            if($ret1){
                //logger("success: update new token to database done");
            }else{
                //logger("error: update new token to database failed");
            }
            
        }else{
            
            $ret2 = db::insert(
                'admins_auth',
                [
                    'admin_id' => $user_id,
                    'token'   => $newtoken,
                    'expire'  => $expire
                ],
                false
            );

            if($ret2) {
                //logger("success: insert new token to database done");
            }else{
                //logger("error: insert new token to database failed");
            }
            
        }

    }

    public function loginCheckByToken($phone,$token){
        
        $adminExist = db::exist("SELECT * FROM admins WHERE phone = ?",[$phone]);
        if(!$adminExist) return -1;
        $admin = db::fetch("SELECT * FROM admins WHERE phone = ?",[$phone]);

        $adminAuthExist = db::exist("SELECT * FROM admins_auth WHERE admin_id = ?",[$admin['id']]);
        if(!$adminAuthExist) return -1;
        $adminAuth = db::fetch("SELECT * FROM admins_auth WHERE admin_id = ?",[$admin['id']]);

        if($adminAuth['token'] == $token){
            
            //init shared majoris if its first login with majoris fast login
            if(!MAJORIS_SELF_HOSTED_MODE){
                if( ($admin['removeable'] == 0) && $this -> needSharedInit($admin['selected_app'])){
                    $this -> startSharedInit($admin['selected_app']);
                }
            }
            $this -> saveLogin($admin['id']);
            return $admin['id'];
        }else{
            return -1;
        }

    }

    // this function check whether or not an app needs to be initiated, which includes
    // reading values from defaults and creating a folder for files
    public function needSharedInit($app_id){

        $subfolder    = '';
        $majoris_root = MAJORIS_ROOT;
        $majoris_root = str_replace('https://','',$majoris_root);
        $majoris_root = str_replace('http://','',$majoris_root);
        if (($pos = strpos($majoris_root, '/')) !== FALSE) { 
            $subfolder = substr($majoris_root, $pos); 
        }
        $upload_path = $_SERVER['DOCUMENT_ROOT'] . $subfolder . '/files/'.$app_id;

        if ( !file_exists( $upload_path ) || !is_dir( $upload_path ) ){
            return true;
        }
        $appconfig_count = db::rowCount("SELECT * FROM appconfig WHERE app_id = ?",[$app_id]);
        if ( $appconfig_count < 8 ) { // These 8 entries include appconfig apptext gateways gateways_map variable_map shipping_method color_map fallback_rootconfig
            return true;
        }

        $serverconfig_count = db::rowCount("SELECT * FROM serverconfig WHERE app_id = ?",[$app_id]);
        if ( $serverconfig_count < 5 ) { // These 5 entries include sms_providers user_notifs telegram_bot_config admin_notifs email_server_config
            return true;
        }

        $panelconfig_count = db::rowCount("SELECT * FROM panelconfig WHERE app_id = ?",[$app_id]);
        if ( $panelconfig_count < 1 ) { 
            return true;
        }
        if($panelconfig_count == 1) {
            $panelconfig = db::fetch("SELECT * FROM panelconfig WHERE app_id = ?",[$app_id]);
            if(empty($panelconfig['data'])){
                return true;
            }
        }

        return false;
    }

    public function startSharedInit($app_id){
        $functions = new Functions;

        $subfolder    = '';
        $majoris_root = MAJORIS_ROOT;
        $majoris_root = str_replace('https://','',$majoris_root);
        $majoris_root = str_replace('http://','',$majoris_root);
        if (($pos = strpos($majoris_root, '/')) !== FALSE) { 
            $subfolder = substr($majoris_root, $pos); 
        }

        $upload_path = $_SERVER['DOCUMENT_ROOT'] . $subfolder . '/files/'.$app_id;
        if ( !file_exists( $upload_path ) || !is_dir( $upload_path ) ){
            mkdir($upload_path,0777,TRUE);
        }

        $defaults_path = $_SERVER['DOCUMENT_ROOT'] . $subfolder . '/defaults';

        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "appconfig", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "appconfig", $defaults_path."/appconfig.json");
            if( !$res ){
                return "مشکلی در افزودن appconfig پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "webconfig", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "webconfig", $defaults_path."/webconfig.json");
            if( !$res ){
                return "مشکلی در افزودن webconfig پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "apptext", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "apptext", $defaults_path."/apptext.json");
            if( !$res ){
                return "مشکلی در افزودن apptext پیش آمد";
            }
        }
        
        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "gateways", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "gateways", $defaults_path."/gateways.json");
            if( !$res ){
                return "مشکلی در افزودن gateways پیش آمد";
            }
        }
        
        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "gateways_map", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "gateways_map", $defaults_path."/gateways_map.json");
            if( !$res ){
                return "مشکلی در افزودن gateways_map پیش آمد";
            }
        }
        
        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "variable_map", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "variable_map", $defaults_path."/variable_map.json");
            if( !$res ){
                return "مشکلی در افزودن variable_map پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "color_map", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "color_map", $defaults_path."/color_map.json");
            if( !$res ){
                return "مشکلی در افزودن color_map پیش آمد";
            }
        }
        
        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "shipping_methods", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "shipping_methods");
            if( !$res ){ 
                return "مشکلی در افزودن shipping_methods پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "shipping_limits", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "shipping_limits");
            if( !$res ){ 
                return "مشکلی در افزودن shipping_limits پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "custom_css", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "custom_css");
            if( !$res ){ 
                return "مشکلی در افزودن custom_css پیش آمد";
            }
        }
        
        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "color_map", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "color_map");
            if( !$res ){
                return "مشکلی در افزودن color_map پیش آمد";
            }
        }
        
        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "fallback_rootconfig", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "fallback_rootconfig");
            if( !$res ){
                return "مشکلی در افزودن fallback_rootconfig پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "homepage_android", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "homepage_android");
            if( !$res ){
                return "مشکلی در افزودن homepage_android پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `appconfig` WHERE `type` = ? AND app_id = ?", [ "homepage_web", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "appconfig", "homepage_web");
            if( !$res ){
                return "مشکلی در افزودن homepage_web پیش آمد";
            }
        }
        
        $ret = db::exist( "SELECT * FROM `panelconfig` WHERE app_id = ?", [ $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "panelconfig", "", $defaults_path."/panelconfig.json");
            if( !$res ){
                return "مشکلی در افزودن panelconfig پیش آمد";
            }
        } else {
            $panelconfig = db::fetch("SELECT * FROM panelconfig WHERE app_id = ?",[$app_id]);
            
            if(empty($panelconfig['data'])){
                $data = file_get_contents($defaults_path."/panelconfig.json");
                $toUpdate = [];
                $toUpdate['data'] = $data;

                $res = db::update('panelconfig',$toUpdate," `id` = " . $panelconfig['id'] );
                $res = is_numeric($res);
                if( !$res ){
                    return "مشکلی در افزودن panelconfig پیش آمد";
                }
            }
        }


        
        $ret = db::exist( "SELECT * FROM `serverconfig` WHERE `type` = ? AND app_id = ?", [ "sms_providers", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "serverconfig", "sms_providers", $defaults_path."/sms_providers.json");
            if( !$res ){
                return "مشکلی در افزودن sms_providers پیش آمد";
            }
        }
        
        $ret = db::exist( "SELECT * FROM `serverconfig` WHERE `type` = ? AND app_id = ?", [ "user_notifs", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "serverconfig", "user_notifs", $defaults_path."/user_notifs.json");
            if( !$res ){
                return "مشکلی در افزودن user_notifs پیش آمد";
            }
        }

        
        $ret = db::exist( "SELECT * FROM `serverconfig` WHERE `type` = ? AND app_id = ?", [ "telegram_bot_config", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "serverconfig", "telegram_bot_config", $defaults_path."/telegram_bot_config.json");
            if( !$res ){
                return "مشکلی در افزودن telegram_bot_config پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `serverconfig` WHERE `type` = ? AND app_id = ?", [ "admin_notifs", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "serverconfig", "admin_notifs", $defaults_path."/admin_notifs.json");
            if( !$res ){
                return "مشکلی در افزودن admin_notifs پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `serverconfig` WHERE `type` = ? AND app_id = ?", [ "email_server_config", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "serverconfig", "email_server_config", $defaults_path."/email_server_config.json");
            if( !$res ){ 
                return "مشکلی در افزودن email_server_config پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `serverconfig` WHERE `type` = ? AND app_id = ?", [ "web_homepage_lastmod", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "serverconfig", "web_homepage_lastmod", "");
            if( !$res ){ 
                return "مشکلی در افزودن web_homepage_lastmod پیش آمد";
            }
        }

        $ret = db::exist( "SELECT * FROM `serverconfig` WHERE `type` = ? AND app_id = ?", [ "static_pages_lastmod", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "serverconfig", "static_pages_lastmod", "");
            if( !$res ){ 
                return "مشکلی در افزودن static_pages_lastmod پیش آمد";
            }
        }
        
        $ret = db::exist( "SELECT * FROM `serverconfig` WHERE `type` = ? AND app_id = ?", [ "sitemap_last_generate_date", $app_id ] );
        if(!$ret){
            $res = $functions->writeDefault($app_id, "serverconfig", "sitemap_last_generate_date", "");
            if( !$res ){ 
                return "مشکلی در افزودن sitemap_last_generate_date پیش آمد";
            }
        }

        return "ok";
    }

    public function getAccessType($user_id){
        $admin_exist = db::exist( "SELECT * FROM `admins` WHERE id = ?", [ $user_id ] );
        if($admin_exist){
            $admin = db::fetch( "SELECT * FROM `admins` WHERE id = ?", [ $user_id ] );
            return $admin['access'];
        }else{
            return "no_access";
        }

    }

    public function checkAccess($user_id, $page){
        $admin_exist = db::exist( "SELECT * FROM `admins` WHERE id = ?", [ $user_id ] );
        if($admin_exist){
            $admin = db::fetch( "SELECT * FROM `admins` WHERE id = ?", [ $user_id ] );
            if($admin['removeable'] != 0){

                if(!empty($admin['access_limit'])){
                    $access = json_decode(trim($admin['access_limit']), true);

                    //update version3: add new pages to access_limit:
                    if(!array_key_exists("sitemap",$access)){
                        $subfolder    = '';
                        $majoris_root = MAJORIS_ROOT;
                        $majoris_root = str_replace('https://','',$majoris_root);
                        $majoris_root = str_replace('http://','',$majoris_root);
                        if (($pos = strpos($majoris_root, '/')) !== FALSE) { 
                            $subfolder = substr($majoris_root, $pos); 
                        }
                        $access_def = $_SERVER['DOCUMENT_ROOT'] . $subfolder . '/defaults/access_limit.json';
                        $access_def = json_decode(file_get_contents($access_def),true);
                        
                        if(count($access_def) > count($access)){
                            foreach ($access_def as $key => $val ){
                                if(!array_key_exists($key,$access)){
                                    $val = strval($val);
                                    $access[$key] = $val; //add missing key val to access_limit
                                }
                            }
                            $data = json_encode($access,JSON_UNESCAPED_UNICODE);
                            $res = db::query("UPDATE `admins` SET `access_limit` = ? WHERE id = ? " , [ $data, $user_id ]);
                        }
                    }
                    
                    //normal access check
                    if(array_key_exists($page,$access)){
                        return $access[$page];
                    } else {
                        return "no_access";
                    }

                } else {
                    return "no_access";
                }

            } else {
                return "has_access";
            }
        }else{
            return "no_access";
        }
    }

    public function checkAdminType($user_id){
        $admin_exist = db::exist( "SELECT * FROM `admins` WHERE id = ?", [ $user_id ] );
        if($admin_exist){
            $admin = db::fetch( "SELECT * FROM `admins` WHERE id = ?", [ $user_id ] );
            if($admin['removeable'] == 0)
                return 'owner';
            else
                return 'normal';
        } else {
            return 'error';
        }

    }

    // public function checkExpireDate($app_id){
    //     $app_exist = db::exist( "SELECT * FROM `apps` WHERE id = ?", [ $app_id ] );
    //     if($app_exist){
    //         $app = db::fetch( "SELECT * FROM `apps` WHERE id = ?", [ $app_id ] );
    //         if(!empty($app['expire_date'])){
    //             $current_date = date("Y-m-d");
    //             $today_dt     = new DateTime($current_date);
    //             $expire_dt    = new DateTime($app['expire_date']);
    //             if($expire_dt < $today_dt){
    //                 return 1006; //app has expired
    //             }
    //         } else {
    //             return 1007; //app does not have expire_date
    //         }
    //     } else {
    //         return 1005; //app does not exist
    //     }
    //     return 'ok';
    // }

    public function calculateExpireDate($app_id){
        $app_exist = db::exist( "SELECT * FROM `apps` WHERE id = ?", [ $app_id ] );
        if($app_exist){
            $app = db::fetch( "SELECT * FROM `apps` WHERE id = ?", [ $app_id ] );
            if(!empty($app['expire_date'])){
                $current_date = date("Y-m-d");
                $today_dt     = new DateTime($current_date);
                $expire_dt    = new DateTime($app['expire_date']);

                $interval = $today_dt->diff($expire_dt);
                $days = intval( $interval->format('%R%a') );
                return $days;
            } else {
                return false;
            }
        } else {
            return false;
        }
        return false;
    }

    public function changeSelectedApp($user_id, $app_id){
        $toUpdate['selected_app'] = $app_id;
        $res = db::update('admins' , $toUpdate ," `id` = " . $user_id );

        $res = is_numeric($res);
        
        if(!$res){
            return "error";
        }else{
            return "ok";
        }
    }

}