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

class SessionFilter
{
    protected $container;

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

    public function __invoke($request, $response, $next) {
        $path = $request->getUri()->getPath();
        if (in_array($path, enum::IGNORE_SESSION_PATH)) {
            return $next($request, $response);
        }
        $contentType = $request->getContentType();
        $mediaType = $request->getMediaType();
        $accountController = new AccountController($this->container);
        if (!empty($_SESSION['tokenId'])) {
            $userId = $_SESSION['ID'];
            $authInfo = $accountController->getRedisAuthData($userId);
            if (!empty($authInfo['session']['tokenId'])) {
                $redisTokenId = $authInfo['session']['tokenId'];
                $expireTime = $authInfo['session']['expireTime'];
                if ($redisTokenId == $_SESSION['tokenId']) {
                    if ($expireTime < time()) {
                        $accountController->logout($request, $response, []);
                        return $this->sessionLogout($request, $response, enum::SESS_TYPE_SESSION_EXPIRED);
                    }
                }
                else {
                    if (!in_array($userId, enum::SESS_DUPLICATE_EXCEPT_IDS)) {
                        $accountController->logout($request, $response, []);
                        return $this->sessionLogout($request, $response, enum::SESS_TYPE_SESSION_DUPLICATED);
                    }
                }

                $common = new common();
                $common->refreshSession();
                $common->refreshSessionServerType();
                $authInfo['session']['expireTime'] = time() + enum::SESS_EXPIRE_TIME;
                $accountController->setRedisAuthData($userId, $authInfo);
            }
            else {
                $accountController->logout($request, $response, []);
                return $this->sessionLogout($request, $response, enum::SESS_TYPE_SESSION_EXPIRED);
            }
        }
        else {
            $accountController->logout($request, $response, []);
            return $this->sessionLogout($request, $response, enum::SESS_TYPE_SESSION_EXPIRED);
        }

        return $next($request, $response);
    }

    // response
    private function sessionLogout($request, $response, $checkSessionType) {
        $isXhr = $request->isXhr();
        if ($isXhr) {
            $resData = [];
            $common = new common();
            $common->setCommonData($resData, $request, $this->container);
            $alertMessage = "세션 유효시간이 만료되어 로그아웃 처리되었습니다.";
            if ($checkSessionType == enum::SESS_TYPE_SESSION_DUPLICATED) {
                $alertMessage = "다른 브라우저에서 동일한 계정으로 로그인하여 세션이 만료되었습니다.";
            }
            else if ($checkSessionType == enum::SESS_TYPE_SESSION_EXPIRED) {
                $alertMessage = "세션 유효시간이 만료되어 로그아웃 처리되었습니다.";
            }

            $output = [
                'error' => [
                    'code' => enum::HTTP_STATUS_UNAUTHORIZED,
                    'message' => $alertMessage,
                ]
            ];

            return $response->withStatus(enum::HTTP_STATUS_UNAUTHORIZED)->withJson($output);
        }
        else {
            return $response->withRedirect(enum::PERMISSION_ERROR_PATH . '/' . $checkSessionType);
        }
    }

}