<?php

namespace App\Http\Middleware;

use App\ConsumerAPIRequests;
use App\JWTAccess;
use App\Logs;
use App\Slack;
use Closure;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class JwtMiddleware extends JWTAccess
{
    private $request = null;
    protected $errorCode = [
        'Wrong number of segments' => 401,
        'Signature verification failed' => 402,
        'Expired token' => 408
    ];

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        $API_ID = ConsumerAPIRequests::log(['enc' => $request->all()]);

        try {
            $this->request = $request;
            if($this->verifyAccessToken($request)) {

                $this->request->request->add(['data' => $this->getAttributes($this->request->all()), 'user' => $this->user, 'secret' => $this->secret]);
            }

            if ($error = $this->isError($request, $this->request)){
                return $error;
            }

            ConsumerAPIRequests::log(['dec' => $this->request->all(), 'id' => $API_ID, 'user' => $this->user]);
            $response = $next($this->request);
            ConsumerAPIRequests::log(['dec_r' => ($response instanceof JsonResponse ? $response->getOriginalContent() : $response), 'id' => $API_ID, 'user' => $this->user]);
            $responseReturn = response()->json($this->getAttributes($response, true), 200);
            ConsumerAPIRequests::log(['enc_r' => ($responseReturn instanceof JsonResponse ? $responseReturn->getOriginalContent() : $responseReturn), 'id' => $API_ID, 'user' => $this->user]);
            return $responseReturn;
        } catch (Exception $e) {
            if ($this->is_success()) {
                return $this->getResponseAsPerOrigin((object)['message' => 'Exception occurred while signature verification', 'code' => $this->errorCode[$e->getMessage()], 'type' => 'CF_EXCEPTION', 'cf_error_code' => $e->getLine()]);
            }else{
                return $this->initErrors(['message' => 'Exception occurred while signature verification', 'code' => $this->errorCode[$e->getMessage()], 'type' => 'CF_EXCEPTION', 'cf_error_code' => $e->getLine()]);
            }
        }
    }

    public function getAttributes($data, $res = false){
        if($this->is_success()) {
            //var_dump($this->current_origin);
            $response = json_decode(json_encode($data->original ?? $data));
            return !$res ? $response : $this->getResponseAsPerOrigin($response);
        }elseif($res){
            return $this->encodeJWT(new Request(['data' => ($data instanceof JsonResponse ? $data->getOriginalContent() : $data), 'user' => $this->user]), $this->secret);
        }else{
            return json_decode(json_encode($this->decodeJWT($this->request)));
        }
    }

    public function isError(Request $request, Request $requestDec){
        if(request()->is('consumer/*') && (empty($request->all()) || empty($requestDec->all()))){
            return response()->json($this->encodeJWT(new Request(['data' => ['status' => 'FAIL', 'message' => 'Please check your input and try again'], 'user' => $this->user]), $this->secret), 200);
        }

        return false;
    }

    private function getResponseAsPerOrigin($response){
        return [
            "message" => $response->message ?? 'Unknown error',
            "status" => $response->status ?? 'OK',
            "statusCode" => $response->code ?? "CF200",
            "data" => $response->data ?? []
        ];
    }

    private function is_success(){
        if(array_key_exists('HTTP_X_CF_CUSTOMER_APP', $_SERVER)) {
            return true;
        }
        return false;
    }
}