<?php
declare (strict_types = 1);

namespace app\admin\middleware\v1;

use app\admin\model\v1\LanguageModel;
class Auth extends \thans\jwt\middleware\BaseMiddleware
{
    // 获取语言信息
    private function setLanguage($request)
    {
        $code = $request->cookie('lang', 'zh-cn');
        $lang = LanguageModel::cache('lang:code.' . $code, 3600, 'lang')
            ->field(['id', 'name', 'code', 'icon', 'url'])
            ->withJoin(['country' => ['id', 'name', 'code', 'icon']])
            ->where('language_model.code', '=', $code)
            ->find();
        if (!is_null($lang)) {
            $request->lang_id = $lang['id'];
            $request->country_id = $lang->country['id'];
        }
    }

    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure       $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        // options 请求过滤
        if ($request->isOptions()) {
            return response();
        }
        
        // 白名单
        if (in_array($request->pathinfo(), config('auth.white_list'))) {
            return $next($request);
        }

        try {
            // 验证 token
            $payload = $this->auth->auth();

            // 将用户信息存入请求
            $request->uid = $payload['uid'];

            // 语言信息
            $this->setLanguage($request);
        } catch (\thans\jwt\exception\TokenExpiredException $e) {
            try {
                // 尝试刷新 token
                $this->auth->setRefresh();

                // 刷新 token
                $token = $this->auth->refresh();

                $payload = $this->auth->auth(false);
                $request->uid = $payload['uid'];

                // 语言信息
                $this->setLanguage($request);

                $response = $next($request);
                return $this->setAuthentication($response, $token);
            } catch (\thans\jwt\exception\TokenBlacklistGracePeriodException $e) {
                return error('登录已过期', [], 401);
            } catch (\Throwable $th) {
                return error('请登录', [], 401);
            }
        } catch (\Throwable $th) {
            return error('请先登录', [], 401);
        }

        return $next($request);
    }
}
