<?php
 
namespace App\Http\Middleware;

use Carbon\Carbon;
use App\Helpers\Security;
use App\Models\SecurityEvent;
use App\Models\User;

use App\Notifications\SlackNotification;

use Closure;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;

class Bouncer
{
    /**
     * Handle the incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string  $role
     * @return mixed
     */

    public function handle($_request, Closure $_next, ...$_bounceable)
    {
        if(!$_request->user() === null) {
            return response()->json(['detail' => 'Insufficient Permissions'], 401);
        }

        Log::info($_request->user()->email . ' (#' . $_request->user()->id . ') (' . Security::real_ip() . ') hit ' . $_request->path() . ' using ' . $_request->header('user-agent') . ' via ' . $_request->method(), $_bounceable);

        if($_request->user()->canDo($_bounceable)) {

            if($_request->method() != 'GET') {
                SecurityEvent::create([
                    'user_id'       => $_request->user()->id,
                    'ip'            => Security::real_ip(),
                    'user_agent'    => $_request->userAgent(),
                    'route'         => $_request->path(),
                    'payload'       => $_request->input('password') ? json_encode('OBSCURED FOR SECURITY') : json_encode($_request->input()),
                    'description'   => 'Successful pass requiring: '  . join(', ', $_bounceable),
                ]);

                if(config('app.demonstration')) {

                    [$controller, $func] = explode('@', $_request->route()->getAction()['controller']);

                    $instance = app($controller);

                    if (property_exists($instance, 'demoResponses')) {
                        $demoResponses = $instance->demoResponses;
                        
                        if (isset($demoResponses[$func])) {
                            return $demoResponses[$func];
                        }
                    }

                    return response()->json(['detail' => 'SUCCESS', 'demonstration' => true], 200);
                }
            }

            User::where('id', '=', $_request->user()->id)->update([
                'refreshed_at' => Carbon::now()
            ]);

            return $_next($_request);
        }

        Log::warning(Security::real_ip() . ' failed to hit ' . $_request->path() . ' using ' . $_request->header('user-agent') . ' via ' . $_request->method(), $_bounceable);

        SecurityEvent::create([
            'user_id'       => null,
            'ip'            => Security::real_ip(),
            'user_agent'    => $_request->userAgent(),
            'route'         => $_request->path(),
            'payload'       => $_request->input('password') ? json_encode('OBSCURED FOR SECURITY') : json_encode($_request->input()),
            'description'   => 'Failed pass requiring: '  . join(', ', $_bounceable) . 'using method: ' . $_request->method(),
        ]);

        Notification::route('slack', config('creatia.webhook.standard'))->notify(new SlackNotification('Bouncer Security Middleware: ' . Security::real_ip() . ' failed to access ' . $_request->path() . ' using ' . $_request->header('user-agent') . ' which requires: ' . join(', ', $_bounceable)));

        return response()->json(['detail' => 'Insufficient Permissions'], 401);
        
    }
 
}