<?php

namespace App\Http\Middleware;

use App\Models\ApiKey;
use App\Services\Api\V1\ResponseService;
use App\Services\Log;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class ApiKeyVerification {
    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param Closure(Request): (Response) $next
     *
     * @return Response
     */
    public function handle( Request $request, Closure $next ): Response {
        $apiKey = ApiKey::where( 'api_key', $request->api_key )->first();

        if ( ! $apiKey ) {
            Log::add( '201', $request->api_key ?? '-', request()->ip(), array_merge( [ 'endpoint' => $request->route()->getName() ], $request->all() ) );

            return ResponseService::sign( [
                'response' => [
                    'code'    => 100,
                    'message' => __( 'Invalid API Key' )
                ]
            ], 401 );

        } else {
            $apiKey = $apiKey->toArray();

            if ( ! $apiKey['is_active'] ) {
                Log::add( '202', $request->api_key, request()->ip(), array_merge( [ 'endpoint' => $request->route()->getName() ], $request->all() ) );

                return ResponseService::sign( [
                    'response' => [
                        'code'    => 101,
                        'message' => __( 'Inactive API Key' )
                    ]
                ], 401 );
            } else {
                $capability = explode( '.', $request->route()->getName() );

                if ( ! $apiKey[ 'can_' . str_replace( '-', '_', $capability[0] ) ] ) {
                    Log::add( '203', $request->api_key, request()->ip(), array_merge( [ 'endpoint' => $request->route()->getName() ], $request->all() ) );

                    return ResponseService::sign( [
                        'response' => [
                            'code'    => 102,
                            'message' => __( "The used API key doesn't have the required capability to access this endpoint" )
                        ]
                    ], 401 );
                } elseif ( $apiKey['ip_address'] != '' && $apiKey['ip_address'] != $request->ip() ) {
                    Log::add( '204', $request->api_key, request()->ip(), array_merge( [ 'endpoint' => $request->route()->getName() ], $request->all() ) );

                    return ResponseService::sign( [
                        'response' => [
                            'code'    => 103,
                            'message' => __( "API key can't be used from this IP address" )
                        ]
                    ], 401 );
                }
            }
        }

        return $next( $request );
    }
}
