<?php

namespace App\Exceptions;

use App\Exceptions\ApiException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Response;
use Illuminate\Validation\ValidationException;
use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that should not be reported.
     *
     * @var array
     */
    protected $dontReport = [
        AuthorizationException::class,
        HttpException::class,
        ModelNotFoundException::class,
        ValidationException::class,
    ];

    /**
     * Report or log an exception.
     *
     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
     *
     * @param  \Throwable  $exception
     * @return void
     *
     * @throws \Exception
     */
    public function report(Throwable $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Throwable  $e
     * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
     *
     * @throws \Throwable
     */
    public function render($request, Throwable $e)
    {
        $content = [
            'code' => $e->getCode() == 0 ? '500' : $e->getCode(),
            'message' => $e->getMessage(),
            'data'=> []
        ];
        if ($e instanceof HttpResponseException) {
            $content['data'] = $e->getResponse();
        } elseif ($e instanceof ModelNotFoundException || $e instanceof NotFoundHttpException) {
            $content['code'] = 404;
            $content['message'] = '您访问的页面地址不存在';
            return redirect('/');
        } elseif ($e instanceof AuthorizationException) {
            $content['code'] = 403;
        } elseif ($e instanceof ValidationException && $e->getResponse()) {
            $content['code'] = 422;
//            $content['message'] = '验证不通过';
            $content['data'] = json_decode($e->getResponse()->getContent(), true);
            //处理多语言中的[11000,'xxx']格式
            $msg = [];
            $ret = [];
            foreach ($content['data'] as &$item) {
                if (is_array($item)) {
                    foreach ($item as &$item2) {
                        if (is_array($item2) && count($item2) == 2) {
                            $msg = array_merge($msg, [$item2[1]]);
                            $ret = array_merge($ret, [$item2[0]]);
                            $item2 = $item2[1];
                        } else {
                            $msg = array_merge($msg, [$item2]);
                        }
                    }
                } else {
                    $msg[] = $item;
                }
            }
            $content['message'] = reset($msg);
            $content['code'] = reset($ret) ?: 422;
            if (is_array($content['message'])) {
                if (count($content['message']) == 2) {
                    $content['code'] = $content['message'][0];
                    $content['message'] = $content['message'][1];
                }
            }
        } elseif($e instanceof ApiException){
            $content['data'] = $e->getData();
        }

        $trace = $e->getTraceAsString();
        if (isset($content['message']) && $content['message']) {
            $track = json_encode($trace, JSON_UNESCAPED_UNICODE);
            if (stristr($content['message'], 'connection')
                || stristr($content['message'], 'SQLSTATE')
                || stristr($track, 'PDOException: SQLSTATE')
            ) {
                $content['code'] = -100;
                //发短信通知
//                errorHandleSms($content['message']);
            }
        }

        if (config('app.app_debug')) { // 开发模式增加track输出
            $content['track'] = $trace;
        }
        $response = new Response(json_encode($content));
        $response->header('Content-Type', 'application/json;charset:UTF-8');
        $response->header('Access-Control-Allow-Origin', '*');
        $response->header('Access-Control-Allow-Credentials', 'true');
        $response->header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
        $response->header('Access-Control-Allow-Headers', 'Content-Type,token,api_token');
        $response->header('Access-Control-Expose-Headers', '*');
        $response->exception = $e;
        return $response;
       // return parent::render($request, $e);
    }
}
