<?php

namespace App\Exceptions;

use App\Services\LogService;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param Throwable $exception
     * @return void
     * @throws Exception
     */
    public function report(Throwable $exception)
    {
        parent::report($exception);
    }


    public function render( $request, Throwable $exception)
    {
        $errMsg='';
        try{
            $type = $exception->type ?? 'error';
            $errMsg=(function()use($request,$exception){
                return $errMsg=
                    '异常: '
                    .' URL:'.(
                    method_exists($request,'fullUrl')
                        ?($request->fullUrl()??'')
                        :'')
                    .' method:'.(
                    method_exists($request,'method')
                        ?($request->method()??'')
                        :'')
                    .' params:'.(
                    method_exists($request,'all')
                        ?json_encode($request->all()??'')
                        :'')
                    .' errors:'.(
                    method_exists($exception,'errors')
                        ?(json_encode($exception->errors(),JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES)??'')
                        :'')
                    .' header:'.(
                    method_exists($request,'header')
                        ?json_encode($request->headers->all()??'')
                        :'')
                    .' code:'.(
                    method_exists($exception,'getStatusCode')
                        ?($exception->getStatusCode()??'')
                        :'')
                    .' message:'.(
                    method_exists($exception,'getMessage')
                        ?($exception->getMessage()??'')
                        :'')
                    .' trace:'.
                    (method_exists($exception,'getTraceAsString')
                        ?($exception->getTraceAsString()??'')
                        :'');
            })();
            if($request->is("api/*")
                && $exception instanceof ValidationException){
                return response()->json($exception->errors(),200,[],JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
            }
            if(strpos($exception->getMessage(),'This action is unauthorized')!==false){
                return response()->view('exception.unauthorized');
            }
            if (method_exists($exception,'getStatusCode')) {
                $code = $exception->getStatusCode();
                switch ($code){
                    case 419: $view='exception.login';break;
                    case 404:$view='exception.404';break;
                    default: $view='exception.default';break;
                }
                return response()->view($view,[
                    'code'=> $code,
                    'message'=>$exception->getMessage(),
                ]);
            }
        }catch (\Exception $e){}finally{
            list(
                $className,
                $functionName,
                $tracesAll
                )           =(function()use($exception){
                $traces=method_exists($exception,'getTraceAsString')
                    ?($exception->getTraceAsString()??'')
                    :'';
                if(!$traces)return '';
                preg_match('/\#0.*?\: (.*?)(-\>|\:\:)(.*?)\(/', $traces, $result);
                return [$result[1]??'',$result[3]??'',$traces];
            })();
            LogService::log(
                $className,
                $functionName,
                ($errMsg??'')
                .'请求：'.json_encode($request->all())
                .'调用堆栈r：'.$tracesAll,
                Auth::id()??'',
                $type
            );
        }
        return parent::render($request, $exception);
    }
}
