<?php

namespace app\api\middleware;

use ReflectionException;
use support\exception\BusinessException;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;
use support\Container;

class Auth implements MiddlewareInterface
{
    /**
     * @param Request $request
     * @param callable $handler
     * @return Response
     * @throws ReflectionException|BusinessException
     */
    public function process(Request $request, callable $next): Response
    {
        if($request->method() == 'OPTIONS'){
            $headers = [
                'Access-Control-Allow-Credentials' => 'true',
                'Access-Control-Allow-Origin' => $request->header('origin', '*'),
                'Access-Control-Allow-Methods' => $request->header('access-control-request-method', '*'),
                'Access-Control-Allow-Headers' => $request->header('access-control-request-headers', '*'),
            ];
            $response = response('200',200,$headers);
            return $response;
        }
        $lang = $request->input('lang','zh-Hans');
        locale($lang);
        if ($request->controller) {
            $request->client = $request->header('client',"web");
            // if($request->client=='win' && $request->header('version') < 2.06){
            //     abort('旧版本不能再使用,请更新到最新版本', 603);
            // }
            
            //跨域请求检测
            //check_cors_request();

            // 检测IP是否允许
            //check_ip_allowed();
            $request->start_time = microtime();
            $controller = Container::get($request->controller);
            // 检测是否需要验证登录
            if (!\support\Jwt::match($controller->noNeedLogin)) {
                //检测是否登录
                try {
                    if (!\support\Jwt::isLogin()) {
                        return json([
                            "code"=>401,
                            "data"=>[],
                            "msg"=>__('Please login first')
                        ]);
                    }
                } catch (\Exception $e) {
                    return json([
                        "code"=>401,
                        "data"=>[],
                        "msg"=>__('Please login first')
                    ]);
                }
                $user = \support\Jwt\JwtToken::getUser();
                if(!$user['status']){
                    return json([
                        "code"=>403,
                        "data"=>[],
                        "msg"=>__('Account is locked')
                    ]);
                }

                // $key = "debounce_" . $request->path() . "_" . ($user->id ?? 'guest');
                // $ttl = 1; // 防抖时间（秒）
                // $redishandler = new \Redis;
                // $redishandler->connect(
                //     \support\Env::get('host'), 
                //     (int) \support\Env::get('port'), 
                //     (int) \support\Env::get('timeout'));
                // $redishandler->select(12);
                // if ($redishandler->setnx($key, 1)) {
                //     $redishandler->expire($key, $ttl);
                // }else{
                //     return new Response(429,[],__('Too frequent operation'));
                // }
                // 判断是否需要验证权限
                if (!\support\Jwt::match($controller->noNeedAuth)) {
                    // 判断控制器和方法判断是否有对应权限
                    $controllername = get_controller_name();
                    $actionname = strtolower(get_action_name());
                    $path = str_replace('.', '/', $controllername) . '/' . $actionname;
                    if (!\support\Jwt::check($path)) {
                        return json([
                            "code"=>405,
                            "data"=>[],
                            "msg"=>__('You have no permission')
                        ]);
                    }
                }
            }

            if($request->client!='web'){
                $data = $request->post('data');
                if($data){
                    $data = str_replace('%3D','=',$data);
                    $data = str_replace(' ','+',$data);
                    //var_dump($data);
                    $data = aesdecode($data);
                    $data = json_decode($data,true);
                    //var_dump($data);
                    $request->withBody($data);
                }
            }
            $config = Config('site');
            $config['debug'] = config('app.debug');
            $config['controller'] = $request->controller_name;
            $config['action'] = $request->action_name;
            $request->_view_vars = array_merge((array) $request->_view_vars,[
                'user'      =>  session('admin'),
                'config'    =>  $config
            ]);
            $IM = new \support\OpenImSdk\Client([
                'host' => 'http://127.0.0.1:10002', // OpenIM API地址
                'secret' => 'openIM123', // OpenIM密钥
            ]);
            $request->IM = $IM;
            $response = $next($request);
            $headers = [
                'Access-Control-Allow-Credentials' => 'true',
                'Access-Control-Allow-Origin' => $request->header('origin', '*'),
                'Access-Control-Allow-Methods' => $request->header('access-control-request-method', '*'),
                'Access-Control-Allow-Headers' => $request->header('access-control-request-headers', '*'),
            ];
            $response->withHeaders($headers);
            //cp('auth');
            //\support\Log::alert('auth');
            $body = str_replace([
                '__SELF__'
            ],[
                request()->path()
            ],$response->rawBody());
            if($request->app=="api" && $request->client!='web'){
                $body = aesencode($body);
            }
            $response->withBody($body)->getStatusCode();
            $time = microtime() - $request->start_time;
            //echo("响应时间:".$request->uri().':'.$time.PHP_EOL);
            //$response = $next($request);
            //\support\Log::error($response->rawBody());
            return $response;
        }
        return $next($request);
    }
}
