<?php

namespace App\Http\Controllers\Organisation;

use App\Helpers\Utility\SymEncrypt;
use App\Http\Controllers\BaseController;

use App\Models\Webhook;
use App\Models\WebhookMessage;
use App\Models\WebhookMessageStatus;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Notification;
use App\Notifications\SlackNotification;
use App\Rules\OwnedWebhookIdentity;
use App\Rules\SafeDomain;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

class HookController extends BaseController
{
    public function get_hooks(Request $_r) {

        return $this->paged_table($_r, function() {
            return Webhook::select('id', 'created_at', 'hook_type', 'usage_type', 'name')->where('organisation_id', '=', Auth::user()->organisation_id);
        }, [ 
            'name'          => [ 'db' => 'name', 'searchable' => true ],
            'hook_type'     => [ 'db' => 'hook_type', 'searchable' => true ],
            'usage_type'    => [ 'db' => 'usage_type', 'searchable' => true ],
            'created_at'    => [ 'db' => 'created_at', 'searchable' => true ]
        ], 'id', null);
    }

    public function get_hook_messages(Request $_r) {

    }

    public function post_hook(Request $_r) {

        try {
            $name = $_r->input('name');
            $hook = $_r->input('hook');
            $hook_type = $_r->input('hook_type');
            $usage_type = $_r->input('usage_type');

            if(!Validator::make($_r->all(), [
                'name'          => [ 'required', 'string' ],
                'hook'          => [ 'required', 'string', new SafeDomain ],
                'hook_type'     => [ 'required', Rule::in(['slack', 'discord', 'google', 'raw']) ],
                'usage_type'    => [ 'required', Rule::in(['reporting']) ]
            ])->fails()) {
                $wh = new Webhook([
                    'name'              => $name,
                    'hook'              => (new SymEncrypt(config('creatia.reporting.encryption_key')))->encrypt($hook),
                    'hook_type'         => $hook_type,
                    'usage_type'        => $usage_type,
                    'organisation_id'   => Auth::user()->organisation_id
                ]);

                if($wh->save()) {
                    Notification::route('slack', config('creatia.webhook.standard'))->notify(new SlackNotification(
                        "USER CREATED A WEBHOOK\n" .
                        'USER: ' . Auth::user()->email . '( O-' . Auth::user()->organisation_id . ' )' .
                        "\nTYPE: $hook_type" . 
                        "\nPURPOSE: $usage_type"
                    ));

                    return response()->json(__('api.200_GENERIC'), 200);
                }
            }
        } catch(\Throwable $e) {
            \Log::debug($e);
        }

        Notification::route('slack', config('creatia.webhook.standard'))->notify(new SlackNotification(
            "USER FAILED TO CREATE A WEBHOOK\n" .
            'USER: ' . Auth::user()->email . '( O-' . Auth::user()->organisation_id . ' )' .
            "\nTYPE: $hook_type" . 
            "\nPURPOSE: $usage_type"
        ));

        return response()->json(__('api.400_INVALID_PAYLOAD'), 400);
    }

    public function delete_hook(Request $_r, $_hook_id) {

        $valid_request = !Validator::make( [ 'hook_id' => $_hook_id ], [
            'hook_id' => [ 'required', new OwnedWebhookIdentity ]
        ])->fails();
        

        if(!$valid_request) {
            return response()->json(['detail' => __('api.400_INVALID_PAYLOAD')], 400);
        }

        Webhook::find($_hook_id)->delete();

        return response()->json(__('api.200_GENERIC'), 200);
    }

    public function test_hook(Request $_r, $_hook_id) {

        /**
         * It's really important to rate limit this so nobody can essentially turn Creatia into something that will spam peoples endpoints through simple CURL hits.
         */

        $limiterKey = 'webhook_test' . Auth::user()->id;

        $response = null;

        $executed = RateLimiter::attempt(
            $limiterKey,
            6,
            function() use(&$response, $_hook_id, $_r) {
                try {
                    $valid_request = !Validator::make( [ 'hook_id' => $_hook_id ], [
                        'hook_id' => [ 'required', new OwnedWebhookIdentity ]
                    ])->fails();
        
                    if($valid_request) {
       
                        $code = 'EX-' . Auth::user()->organisation_id . time();

                        WebhookMessage::create([
                            'key' => $code,
                            'organisation_id' => Auth::user()->organisation_id,
                            'webhook_id' => $_hook_id,
                            'message_type' => Webhook::find($_hook_id)->usage_type,
                            'status' => WebhookMessageStatus::Pending->value,
                            'payload' => ["Example Webhook Payload $code"]
                        ]);
        
                        $response = response()->json(__('api.200_GENERIC'), 200);
                    }
                    
                } catch(\Exception $ex) {
                    $response = response()->json(__('api.400_INVALID_PAYLOAD'), 400);
        
                    \Log::debug($ex);
                }
            }
        );

        return $response === null ? response()->json(['detail' => "Tests exceeded."], 429) : $response;
    }
}
