<?php
// +----------------------------------------------------------------------
// | Bwsaas
// +----------------------------------------------------------------------
// | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Gitee ( https://gitee.com/buwangyun/bwsaas )
// +----------------------------------------------------------------------
// | Author: buwangyun <hnlg666@163.com>
// +----------------------------------------------------------------------
// | Date: 2020-9-28 10:55:00
// +----------------------------------------------------------------------

namespace app;

use buwang\exception\MiniappException;
use buwang\traits\JsonTrait;
use buwang\traits\JumpTrait;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use Firebase\JWT\ExpiredException;

use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use \UnexpectedValueException;
use buwang\exception\AuthException;

use think\Response;
use Throwable;

/**
 * 应用异常处理类
 */
class ExceptionHandle extends Handle
{
    use JsonTrait;
    use JumpTrait;

    /**
     * 不需要记录信息(日志)的异常类列表
     * @var array
     */
    protected $ignoreReport = [
        HttpException::class,
        HttpResponseException::class,
        ModelNotFoundException::class,
        DataNotFoundException::class,
        ValidateException::class,
    ];

    /**
     * 记录异常信息(包括日志或者其它方式记录)
     *
     * @access public
     * @param Throwable $exception
     * @return void
     */
    public function report(Throwable $exception): void
    {
        // 使用内置的方式记录异常日志
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @access public
     * @param \think\Request $request
     * @param Throwable $e
     * @return Response
     */
    public function render($request, Throwable $e): Response
    {
        // 添加自定义异常处理机制

        //token jwt验证
        if ($e instanceof UnexpectedValueException) {
            return $this->code(422)->error($e->getMessage(), [], 400422);
        }
        if ($e instanceof SignatureInvalidException) {
            // return json("Incorrect signature", 422);//签名不正确
            return $this->code(422)->error("Incorrect signature", [], 400422);
        }
        if ($e instanceof BeforeValidException) {
            //return json("The signature will take some time to us", 422);//签名尚未生效,签名在某个时间点之后才能用
            return $this->code(422)->error("The signature will take some time to us", [], 400422);
        }
        if ($e instanceof ExpiredException) {
            // return json("Token has expired", 422);//token已经过期
            //var_dump($e->getFile(),$e->getline());die;
            return $this->code(422)->error("Token has expired", [], 400422);
        }

        //JWT token解析错误
        if ($e instanceof \DomainException) {
            return $this->code(422)->error("Token error");
        }

        // 参数验证错误
        if ($e instanceof ValidateException) {
            $statusCode = $e->getCode() ?: 200;
            return $this->code($statusCode)->error($e->getError());
        }
        //应用状态异常
        if ($e instanceof MiniappException) {
            $statusCode = $e->getCode() ?: 200;
            if(request()->isAjax()) return $this->code($statusCode)->error($e->getMessage());
            return $this->error_jump($e->getMessage(),NOT_JUMP);
        }
        // 请求异常
        if ($e instanceof HttpException && ($request->isGet() || $request->isPost())) {
            //return response($e->getMessage(), $e->getStatusCode());
            return $this->code(500)->error($e->getMessage());
        }
        //捕获response异常
        if ($e instanceof HttpResponseException) {
            return $e->getResponse();
        }

        //权限认证异常错误
        if ($e instanceof AuthException) {
            $statusCode = $e->getCode() ?: 200;
            if(request()->isAjax()) return $this->code($statusCode)->error($e->getMessage());
            return $this->error_jump($e->getMessage(),NOT_JUMP);
        }
        
        //其它错误自定义处理
        if($request->isAjax() && ($e instanceof \Throwable)){
            trace(["msg"=>$e->getMessage(),"file"=>$e->getFile(),"line"=>$e->getLine()],'error');
            return $this->code(500)->error($e->getMessage().':'.$e->getFile().':'.$e->getLine());
        }
        // 其他错误交给系统处理
        return parent::render($request, $e);
    }
}