<?php

declare (strict_types=1);

namespace app\appapi\middleware;

// use thans\jwt\exception\JWTException;
// use thans\jwt\exception\TokenBlacklistException;
// use thans\jwt\exception\TokenBlacklistGracePeriodException;
// use thans\jwt\exception\TokenExpiredException;
// use thans\jwt\middleware\JWTAuth;
use Firebase\JWT\JWT as FireJWT;
use Firebase\JWT\Key as FireKey;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use Firebase\JWT\ExpiredException;

use think\exception\HttpException;
use think\facade\Log;

/**
 * JWT驗證刷新token機制
 * Class JWTToken
 * @package app\api\middleware
 */
class JWT
{
    /**
     * 刷新token
     * @param $request
     * @param \Closure $next
     * @return mixed
     * @throws JWTException
     * @throws TokenBlacklistException
     * @throws TokenBlacklistGracePeriodException
     */
    public function handle($request, \Closure $next): object
    {
        
        if ($request->isOptions()) {
            return response();
        }
        
        // try{
        try{
            $payload = FireJWT::decode(trim(str_replace('Bearer ','',$request->header('authorization'))), new FireKey(\think\facade\Config::get('jwt.secret'), 'HS256'));
            $decoded = (array) $payload;           
        // } catch (SignatureInvalidException $e) {
        //     throw new HttpException(401, 'token error...');
        // } catch (BeforeValidException $e) {
        //     // provided JWT is trying to be used before "nbf" claim OR
        //     // provided JWT is trying to be used before "iat" claim.
        // } catch (ExpiredException $e) {
        //     print_r($e);
        //     // token過期
        //     throw new HttpException(401, 'login error...');
        } catch(\Exception $e){
            throw new HttpException(401, $e->getMessage());
        }

        // try {
        //     $payload = $this->auth->auth();
        // } catch (TokenExpiredException $e) { // token過期
        //     // 嘗試刷新token，會將舊token加入黑名單
        //     try {
        //         $this->auth->setRefresh();
        //         $token = $this->auth->refresh();
        //         $payload = $this->auth->auth(false);
        //     } catch (TokenBlacklistGracePeriodException $e) {
        //         // 黑名單寬限期
        //         $payload = $this->auth->auth(false);
        //     } catch (JWTException $exception) {
        //         // 如果捕獲到此異常，即代表 refresh 也過期了，用户無法刷新令牌，需要重新登錄。
        //         throw new HttpException(401, $exception->getMessage());
        //     }catch(\Exception $e){
        //         throw new HttpException(401, $e->getMessage());
        //     }
        // } catch (TokenBlacklistGracePeriodException $e) { // 捕獲黑名單寬限期
        //     $payload = $this->auth->auth(false);
        // } catch (TokenBlacklistException $e) { // 捕獲黑名單，退出登錄或者已經自動刷新，當前token就會被拉黑
        //     throw new HttpException(401, 'not login...');
        // }catch (\Exception $e){
        //     throw new HttpException(401, 'login error...');
        // }

        if(isset($payload)){
            $request->uid = $payload->user_id;
        }else{
            $request->uid = 0;
        }

        if($request->header('SessionId')){
            $request->SessionId = $request->header('SessionId');
        }        

        $response = $next($request);

        if (isset($token)) {
            $this->setAuthentication($response, $token);
        }

        return $response;
    }
}