<?php
/**
 * Created by PhpStorm.
 * User: mindu
 * Date: 17/8/18
 * Time: 11:05 AM
 */
namespace App\Http\Controllers\Admin;

use App\ABFL\Services\Services;
use App\Avanse\Services\AvanseServices;
use App\Events\V1\EventABFLWebhook;
use App\Http\Controllers\Admin\ABFLController;
use App\Http\Controllers\Admin\AvanseController;
use App\Http\Controllers\Controller;
use App\Merchant;
use App\MerchantApiCredentials;
use App\Slack;
use App\Vendor;
use App\VendorApiCredentials;
use App\VendorWebhook;
use App\Webhook;
use App\WebhookRequestLogs;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class VendorIntegrationController extends Controller
{
    /**
     * @var Request
     */
    private $request;

    public function __construct(Request $request){
        $this->request = $request;
    }

    public function getVendors(){

        $data['vendors'] = Vendor::paginate(10);
        return view('admin.vendor.index', $data);
    }

    public function addVendor(){
        $consumerDocument = new ConsumerDocument($this->request);
        if($this->request->get('name')) {
            if ($this->request->get('vendor_id')){
                $vendor = Vendor::find($this->request->get('vendor_id'));
            }else{
                $vendor = new Vendor();
            }
            $this->request->merge([
                'merchant_id' => implode(',', $this->request->get('merchant_id')),
            ]);
            foreach($this->request->all() as $key=>$item){
                if(!in_array($key,['vendor_id','_token','signature','logo','bot_app_id'])) {
                    $vendor->$key = $item;
                }else if($key == 'logo'){
                    if($this->request->hasFile($key)) {
                    //     if(filesize($this->request->files->get('logo')) > 18874368){
                    //         Session::flash('error', 'Uploaded file is too large');
                    //         return redirect()->back();
                    //     }
                        $filePath = $this->request->get('name') . '_' . $key;
                        $filePath = $consumerDocument->uploadToS3ByPath($filePath, '/' . $this->request->get('name'), $this->request->file($key), true);
                        $filePath = "http://s3.ap-south-1.amazonaws.com/"._env('AWS_BUCKET', 'creditfair-customer-documents')."/".$filePath;
                        $vendor->$key = $filePath;
                    }
                }
                else if($key == 'vendor_id'){
                    $vendor->id = $item;
                }
            }
            // $vendor->fill($this->request->all());
            $vendor->created_by = Auth::user()->id;
            $vendor->created_at = Carbon::now()->toDateTimeString();
            $vendor->save();
            return redirect()->to('admin/vendor');
        }else{
            $merchants = Merchant::whereNull('deleted_at')->get(['id','merchant_name']);
            return view('admin.vendor.add',['merchants'=>$merchants]);
        }
    }

    public function editVendor($id){
        $vendor = Vendor::find($id);
        $merchants = Merchant::whereNull('deleted_at')->get(['id','merchant_name']);
        if (!$vendor){
            return redirect()->to('admin/vendor');
        }
        return view('admin.vendor.add', ['vendor' => $vendor,'merchants' => $merchants]);
    }

    public function index($id){

        $merchantApiCredentials = VendorApiCredentials::with('user','vendor.webhook')->where('vendor_id', $id)->orderBy('created_at','desc')->get();

        $init = [
            'key' => isset($merchantApiCredentials[0]) && $merchantApiCredentials[0]->status == 1 ? $merchantApiCredentials[0]->key : '',
            'secret' => isset($merchantApiCredentials[0]) && $merchantApiCredentials[0]->status == 1 ? $merchantApiCredentials[0]->secret : '',
            'keys' => $merchantApiCredentials
        ];

        $application = new ConsumerApplicationController();
        $status = $application->status;

        $data = ['init' => $init, 'vendor_id' => $id, 'vendor' => isset($merchantApiCredentials[0]) ? $merchantApiCredentials[0]->vendor : '', 'status' => $status];
        return view('admin.v-api.index', $data);
    }

    public function updateWebhook(){

        if($this->request->get('exists')){
            $webhook = VendorWebhook::find($this->request->get('exists'));
        }else{
            $webhook = new VendorWebhook();
        }
        $webhook->fill([
            'vendor_id' => $this->request->get('id'),
            'user_id' => $this->request->get('user_id'),
            'name' => $this->request->get('webhook_name'),
            'endpoint' => $this->request->get('webhook_url'),
            'events' => implode(',', $this->request->get('events')),
            'status' => 1,
            'created_at' => Carbon::now()->toDateTimeString()
        ]);

        $webhook->save();

        return response()->json(['status' => $webhook->id ? 'OK' :'FAIL', 'message' => $webhook->id ? 'Webhook added successfully' : 'Failed to save webhook']);
    }

    public function deleteWebhook(){
        $webhook = VendorWebhook::where('id', $this->request->get('id'))->delete();

        return response()->json(['status' => $webhook ? 'OK' :'FAIL', 'message' => $webhook ? 'Webhook deleted successfully' : 'Failed to delete webhook']);
    }

    public function enableInit($id){

        //$merchant = Merchant::where('id', $id)->first(['id', 'slug', DB::raw('UNIX_TIMESTAMP(created_at) AS time')]);
//        $this->setDefaultPayload($merchant);
//
//        $process = new Process([_env('PYTHON3_PATH'),  __DIR__.'/jwtEE.py', $id.','.$this->merchantSecretKey]);
//        $process->run();
//
//        if (!$process->isSuccessful()) {
//            throw new ProcessFailedException($process);
//        }
//
//        $key = $process->getOutput();

        try {
            $bytes = random_bytes(16);
            $key = bin2hex($bytes);
            $bytes = random_bytes(24);
            $secret = bin2hex($bytes);
        } catch (\Exception $e) {
            return redirect()->back()->withErrors(['Failed to communicate auth service']);
        }

        if ($key) {
            VendorApiCredentials::insert(
                [
                    'vendor_id' => $id,
                    'key' => $key,
                    'secret' => $secret,
                    'created_at' => Carbon::now()->toDateTimeString(),
                    'created_by' => Auth::user() ? Auth::user()->id : ($this->request->has('user_id') ? $this->request->get('user_id') : 107),
                    'status' => 1
                ]
            );

            return redirect()->back();
        }

        return redirect()->back()->withErrors(['Failed to communicate auth service']);
    }

    public function changeStatus(){
        $apiKey = VendorApiCredentials::where('id', $this->request->get('id'))->first(['id', 'status']);
        if (isset($apiKey->id)){
            $apiKey = VendorApiCredentials::where('id', $this->request->get('id'))->update(['status' => !$apiKey->status]);
            if ($apiKey){
                return response()->json(['status' => 'OK']);
            }
        }

        return response()->json(['status' => 'FAIL', 'message' => 'Failed to change the status']);
    }

    public function updateIPs(){
        $ipUpdate = Vendor::where('id', $this->request->get('id'))->update(['ips' => $this->request->get('ips')]);
        $vendorCredsIPUpdate = VendorAPICredentials::where('vendor_id', $this->request->get('id'))->update(['ips' => $this->request->get('ips')]);
        if ($ipUpdate){
            return response()->json(['status' => 'OK', 'message' => 'Added Successfully']);
        }

        return response()->json(['status' => 'FAIL', 'message' => 'Failed to save']);
    }

    public function push(){

        $status = 'FAIL';
        //$invoice = ProFormaInvoice::where('application_id', $this->request->get('application_id'))->first(['loan_application_no']);

        if ($this->request->get('application_id')) {

            $webhooks = VendorWebhook::whereIn('id', json_decode($this->request->get('webhook_id')))->where('status', 1)->get();
            //(new Slack(new Request(['title' => 'mConnect Webhook - Check 4', 'fields' => ['payload' => 'a'], 'group' => Slack::$STAGE_TESTING])))->send();

            foreach ($webhooks as $webhook) {
                $webhook_array = array('NACH-Webhook', 'RazorPay-Webhook', 'Paytm-Webhook', 'Cashfree-Webhook', 'Digio-VKYC-Webhook', 'Application-Webhook');
                if (isset($webhook->id) && (in_array($this->request->get('payload')['status'], explode(',', $webhook->events)) || (isset($this->request->get('payload')['type']) && in_array($this->request->get('payload')['type'], $webhook_array)))) {

                    $request_id = $this->guidv4();
                    //(new Slack(new Request(['title' => 'mConnect Webhook - Check 4', 'fields' => ['end' => $webhook->endpoint], 'group' => Slack::$STAGE_TESTING])))->send();

                    //$payload = json_encode(array('applicationNo' => $invoice->loan_application_no, "status" => $this->request->get('status'), 'remark' => ''));
                    $payload = json_encode($this->request->get('payload'));
                    //(new Slack(new Request(['title' => 'mConnect Webhook - Check 4', 'fields' => ['payload' => $payload], 'group' => Slack::$STAGE_TESTING])))->send();
                    $curl = curl_init();
                    curl_setopt_array($curl, array(
                        CURLOPT_URL => $webhook->endpoint,
                        CURLOPT_RETURNTRANSFER => true,
                        CURLOPT_ENCODING => "",
                        CURLOPT_MAXREDIRS => 10,
                        CURLOPT_TIMEOUT => 30,
                        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                        CURLOPT_CUSTOMREQUEST => "POST",
                        CURLOPT_POSTFIELDS => $payload,
                        CURLOPT_HTTPHEADER => array(
                            "Content-Type: application/json",
                            "Credit-Fair-Signature:".$request_id
                        ),
                    ));

                    $response = curl_exec($curl);
                    $err = curl_error($curl);
                    $info = curl_getinfo($curl);

                    $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);

                    (new Slack(new Request(['title' => 'Webhook Response Response | Curl Res', 'fields' => ['Webhook Id' => $webhook->id, 'Info' => json_encode($info), 'Signature' => $request_id, 'URL' => $webhook->endpoint, 'application_id' => $this->request->get('application_id'), 'Error' => $err, 'Response' => $response, 'http_code' => $http_code ?? 1, 'payload' => $payload], 'group' => Slack::$M_CONNECT])))->send();

                    if (!$err) {
                        switch ($http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE)) {
                            case 200:  # OK
                                WebhookRequestLogs::insert([
                                    'request_id' => $request_id,
                                    'webhook_id' => $webhook->id,
                                    'request' => json_encode($payload),
                                    'response' => $response,
                                    'application_id' => $this->request->get('application_id'),
                                    'created_at' => Carbon::now()->toDateTimeString()
                                ]);
                                $status = 'success';
                                break;
                            default:
                                WebhookRequestLogs::insert([
                                    'request_id' => $request_id,
                                    'webhook_id' => $webhook->id,
                                    'request' => json_encode($payload),
                                    'response' => $response,
                                    'application_id' => $this->request->get('application_id'),
                                    'created_at' => Carbon::now()->toDateTimeString()
                                ]);
                                (new Slack(new Request(['title' => 'Webhook Response Error | Code', 'fields' => ['Webhook Id' => $webhook, 'application_id' => $this->request->get('application_id'), 'HCode' => $http_code, 'payload' => $payload, 'response' => json_encode($response)], 'group' => Slack::$M_CONNECT])))->send();
                                $status = 'Webhook Response Error | Code';
                        }
                    }else{
                        (new Slack(new Request(['title' => 'Webhook Response Error | Curl Error', 'fields' => ['Webhook Id' => $webhook, 'application_id' => $this->request->get('application_id'), 'Error' => json_encode($err), 'payload' => $payload], 'group' => Slack::$M_CONNECT])))->send();
                        $status = 'Webhook Response Error | Curl Error';
                    }

                    curl_close($curl);
                }
            }
        }

        return $status;
    }

    function guidv4($data = null) {
        // Generate 16 bytes (128 bits) of random data or use the data passed into the function.
        try {
            $data = $data ?? random_bytes(16);
        } catch (\Exception $e) {
        }
        assert(strlen($data) == 16);

        // Set version to 0100
        $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
        // Set bits 6-7 to 10
        $data[8] = chr(ord($data[8]) & 0x3f | 0x80);

        // Output the 36 character UUID.
        return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
    }
}