<?php

namespace App\Exceptions;


use Illuminate\Http\Request;
use RuntimeException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;


abstract class AppRuntimeException extends RuntimeException implements HttpExceptionInterface, ExceptionCodePrefixInterface
{

    protected $codePrefix;
    protected $errors;
    protected $status_code;
    protected $headers;
    protected $data;
    public static $errorList = [];

    public function getCodePrefix(): int
    {
        return 1;
    }

    /**
     * @param int $code
     * @param string $message
     * @param array $errors
     * @param int $status_code
     * @param array $headers
     * @param array $data
     */
    public function __construct(int $code = 1, $message = 'error', $errors = [], int $status_code = 400, array $headers = [], array $data = [])
    {
        parent::__construct();
        $code = sprintf("%03d", $code);
        $code = (string)($this->getCodePrefix() . $code);
        $this->status_code = $status_code;
        $this->code = (int)($code);
        $this->message = $this->getDefaultMessage($code, $message);
        $this->errors = $errors;
        $this->headers = $headers;
        $this->data = $data;
    }


    public function getDefaultMessage($code, $message = '')
    {
        if (filled($message)) {
            return $message;
        }
        return self::$errorList[$code] ?? ($this->message ?? '');
    }


    public function getStatusCode(): int
    {
        return $this->status_code;
    }

    public function getErrors()
    {
        return count($this->errors) > 0 ? $this->errors : null;
    }

    public function getData()
    {
        return $this->data;
    }

    public function errors()
    {
        return count($this->errors) > 0 ? $this->errors : null;
    }

    public function getHeaders(): array
    {
        return $this->headers;
    }

    public static function invalid($request, $exception)
    {

    }

    /**
     * @param int $status_code
     */
    public function setStatusCode(int $status_code): void
    {
        $this->status_code = $status_code;
    }

    public static function render(Request $request, self $exception)
    {
        return $request->expectsJson() ? self::invalidJson($exception) : self::invalidJson($exception);
    }

    /**
     * 无效json
     *
     * @param AppRuntimeException $exception
     * @param string $lang
     * @return \Illuminate\Http\JsonResponse
     */
    public static function invalidJson(self $exception)
    {
        $data = [
            'errors' => $exception->errors,
            'message' => $exception->getMessage(),
            'code' => $exception->getCode(),
            'status_code' => $exception->getStatusCode(),
            'data' => $exception->getData(),
        ];
        if (app()->environment(['local'])) {
            $data['trace'] = $exception->getTrace();
            $data['time'] = microtime(true) - LARAVEL_START;
        }
        return response()->json($data, $exception->getStatusCode(),
            $exception->getHeaders());
    }


}
