<?php
use Psr\Container\ContainerInterface;
use Psr\Http\Message\RequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

class AccountController
{
    private $loginBlockTime = 1800; // 30 mins.
    private $redisTTL = 86400 * 30; // 30 days
    private $loginFailedLimit = 5;
    private $redis = NULL;

    protected $container;

    public function __construct(ContainerInterface $container) {
        $this->container = $container;
        $menu = $this->container->menu;
    }

    private function getRedisKey($param) {
        $common = new common();
        $type = strtoupper($common->getServerName($this->container));
        
        if ($type == 'WALLET') {
            return enum::WALLET_ADMIN_DB_PREFIX[getServerType()].':LOGIN:'.$param;
        }
        else {
            return enum::MARKET_ADMIN_DB_PREFIX[getServerType()].':LOGIN:'.$param;
        }
    }

    private function getRedis() {
        if (!is_resource($this->redis)) {
            $this->redis = $this->container->redis;
            $this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
        }
        return $this->redis;
    }

    public function getRedisAuthData($param) {
        $redis = $this->getRedis();
        $result = $redis->get($this->getRedisKey($param));
        if(!$result) {
            $result = [
                'password' => [
                    'failCount' => 0,
                    'blockTime' => 0,
                ],
                'session' => [
                    'tokenId' => '',
                    'expireTime' => 0,
                ]
            ];
        }
        return $result;
    }

    public function setRedisAuthData($param, $data) {
        $redis = $this->getRedis();
        $redis->setex($this->getRedisKey($param), $this->redisTTL, $data);
        return true;
    }

    public function sessionReset($request, $response, $args) {
        $result = ['Code' => enum::COMMON_SUCCESS];
        $uid = $args['uid'] ?? '';
        if (!empty($uid)) {
            $authInfo = $this->getRedisAuthData($uid);
            $authInfo = NULL;
            $this->setRedisAuthData($uid, $authInfo);
        }
        return $response->withJson($result);
    }

    public function sessionInfo($request, $response, $args) {
        $timezone = ini_get('Timezone');
        $result = ['Code' => enum::COMMON_SUCCESS];
        $uid = $args['uid'] ?? '';
        if (!empty($uid)) {
            $authInfo = $this->getRedisAuthData($uid);
            $result = $authInfo;
            $result['password']['blockTime'] = empty($result['password']['blockTime']) ? 0 : date('Y-m-d H:i:s', $result['password']['blockTime']);
            $result['session']['expireTime'] = empty($result['session']['expireTime']) ? 0 : date('Y-m-d H:i:s', $result['session']['expireTime']);
        }
        return $response->withJson($result);
    }

    public function login($request, $response, $args) {
        if ($this->container['checkFlag'] != true) {
            echo '<script>location.href="../home/view";</script>';
            exit;
        }

        $common = new common();
        $isLogin = false;
        $displayname = "";
        $company = "";                     
        $params = $request->getParsedBody();  
        $redirectflag = false;
        $serverType = $common->getServerName($this->container);

        if (!$params) {
            $getparam = $request->getQueryParams();
            if (isset($getparam['payload'])) {
                $aesKey = $serverType . 'backoffice';
                if ($serverType == 'market') {
                    $aesIv = '1234567890123456';
                }
                else {
                    $aesIv = '0987654321098765';
                }

                //복호화
                $payload = $common->aes128Decrypt($getparam['payload'], $aesKey, $aesIv);
                $params = json_decode($payload, true);

                //시간 비교
                $time =$params['time'];
                $timenow = strtotime(date("Y-m-d H:i:s"));
                $diff = date('s',abs($timenow-$time));
                
                //시간차이가 10초 이상일때 
                if($diff > 10) {
                    $response = new \Slim\Http\Response(404);
                    $data = array('error' => 'page not found');
                    return $response->withJson($data);
                }

                $redirectflag = true;
            }
        }

        if (isset($params['SaveID']) && true == $params['SaveID']) {
            setcookie($serverType . "OperatorUID", $params['ID'], time() + 259200, "/");
        }

        // 로그인 실패 5회 횟수 처리
        $authInfo = $this->getRedisAuthData($params['ID']);
        if (isset($authInfo['password']['blockTime'])) {
            if ($authInfo['password']['blockTime'] > time()) {
                $resData = [];
                $common->setCommonData($resData, $request, $this->container);
                $blockMessage = "5회 이상 비밀번호 입력 실패로 로그인이 차단 되었습니다. 30분 후에 다시 로그인해주세요.";
                if ($redirectflag) {
                    echo '<script>alert("'.$blockMessage.'");location.href="../home/view";</script>';
                }
                else {
                    $result['Code'] = -999;
                    $result['Msg'] = $blockMessage;
                    return $response->withJson($result);
                }
            }
        }

        $data = $common->getAccountInfo($params['ID'], $params['Password']);

        $result['Data'] = $data;

        if ($data['Code'] > 0) {
            $result['OperationUID'] = $data['Data']['id'];
            $result['DisplayName'] = $data['Data']['displayname'];
            $result['Position'] = $data['Data']['title'];
            $result['Company'] = $data['Data']['company'];
            $result['Department'] = $data['Data']['department']; 
            $result['IsLogin'] = TRUE;

            $common->setSessionServerType($serverType);

            // 로그인 실패 5회 횟수 처리
            $authInfo['password'] = [
                    'failCount' => 0,
                    'blockTime' => 0,
            ];

            // 중복 세션 처리
            $_SESSION['tokenId'] = $common->uuid();
            $authInfo['session'] = [
                'tokenId' => $_SESSION['tokenId'],
                'expireTime' => time() + enum::SESS_EXPIRE_TIME,
            ];

            //admin 유저의 경우 최초 계정 등록시 모든 메뉴에 쓰기 권한을 넣는다.

            $isAdmin = $common->checkPermission_admin($result);
            $result['Authority'] = enum::AUTH_MENU_PERMISSION_NONE;

            if ($isAdmin == true) {
                $allmenu = $this->container->menu->getAll();
                foreach ($allmenu as $key=>$val) {
                    common::UpdateUserPermission($params['ID'], $key, enum::AUTH_MENU_PERMISSION_WRITE);
                }
            }

            //세션에 정보를 저장한다.
            $common->setSession($params['ID'], $params['Password'], $result['Company'], $result['Department'], $result['DisplayName'], $result['Position'], $params['ID']); 
        }
        else {
            $result['IsLogin'] = FALSE;

            // 로그인 실패 5회 횟수 처리
            $authInfo['password']['failCount'] += 1;
            if ($authInfo['password']['failCount'] >= $this->loginFailedLimit) {
                $authInfo['password']['blockTime'] = time() + $this->loginBlockTime;
            }
        }

        $this->setRedisAuthData($params['ID'], $authInfo);

        if ($redirectflag) {
            echo '<script>location.href="../home/view";</script>';
        }
        else {
            return $response->withJson($result);        
        }
    }

    public function logout($request, $response, $args) {
        $common = new common();
        $common->destroySession();
    }

    public function sendLog($resultCode, $input) {
        //log 생성 
        $log = array();
        $log['eventType'] = enum::EVENT_TYPE_INSERT;
        $log['userId'] = 0;
        $log['userType'] = enum::LOG_USER_TYPE_NONE;
        $log['resultCode'] = $resultCode;    
        $log['input'] = $input;    
        $log['output'] = "";

        $common = new common();
        $common->sendLog($this->container, enum::LOGTYPE_MENU, $log);
    }

    public function passLoginInfo($request, $response, $args) {
        //session_start();
        if ($this->container['checkFlag'] == false) {
            echo '<script>location.href="' . $_POST['link'] . '";</script>';
            exit;
        }

        $id = $_SESSION['ID'] ?? '';
        $pass = $_SESSION['Password'] ?? '';
        $link = $_POST['link'];
        $timenow = strtotime(date("Y-m-d H:i:s"));

        $array = array('ID' => $id, 'Password' => $pass, 'time' => $timenow);
        $result = json_encode($array);

        $common = new common();
        $serverType = $common->getServerName($this->container);
        $aesKey = $serverType . 'backoffice';
        if ($serverType == 'market') {
            $aesIv = '1234567890123456';
        }
        else {
            $aesIv = '0987654321098765';
        }

        //암호화
        $common = new common();
        $payload = $common->aes128Encrypt($result, $aesKey, $aesIv);
        $payload = urlencode($payload);
        $home = $request->getUri()->getBasePath();
        
        echo '<script>location.href="' . $link . '/account/login?payload=' . $payload . '";</script>';
    }
}

