<?php

namespace App\Console\Commands;

use App\Account;
use App\Components\Functions;
use App\Notification;
use App\User;
use Dompdf\Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use LaravelFCM\Message\OptionsBuilder;
use LaravelFCM\Message\PayloadDataBuilder;
use LaravelFCM\Message\PayloadNotificationBuilder;
use FCM;
use Minishlink\WebPush\Subscription;
use Minishlink\WebPush\WebPush;
use Mockery\Matcher\Not;

class PushNotification extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'push:notification';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */

    public function pushNotificationBrowser($accountId, $content, $notificationId = null)
    {
        $account = User::find($accountId);
        if ($account) {
            if (!empty($account->webpush_token)) {
                $tokens = json_decode($account->webpush_token, true);
                if (is_array($tokens)) {
                    $endpoint = $tokens['endpoint'];
                    $key = $tokens['key'];
                    $token = $tokens['token'];

                    $data = ['title' => 'Thông báo từ itro.vn',
                        'body' => $content,
                        'icon' => 'https://itro.vn/frontend3/assets/img/logo.png'];
                    $notification =
                        [
                            'subscription' => Subscription::create([
                                'endpoint' => $endpoint,
                                'publicKey' => $key, // base 64 encoded, should be 88 chars
                                'authToken' => $token, // base 64 encoded, should be 24 chars
                                'contentEncoding' => 'aesgcm'
                            ]),
                            'payload' => json_encode($data),
                        ];

                    $auth = array(
                        'VAPID' => array(
                            'subject' => 'https://itro.vn',
                            'publicKey' => config('constants.VAPID_PUBLIC_KEY'),
                            'privateKey' => config('constants.VAPID_SECRET_KEY'), // in the real world, this would be in a secret file
                        ),
                    );

                    $webPush = new WebPush($auth);


                    $webPush->sendNotification(
                        $notification['subscription'],
                        $notification['payload'], // optional (defaults null)
                        true
                    );

                    if(!empty($notificationId)) {
                        \App\Models\Notification::find($notificationId)->forceFill([
                            'status' => \App\Models\Notification::PUSHED
                        ])->save();
                    }
                }
            }
        }
    }

    public function pushNotification($accountId, $title, $notificationId, $token, $content, $isAndroid, $payload)
    {

        $optionBuiler = new OptionsBuilder();
        $optionBuiler->setTimeToLive(60 * 20);

        $notificationBuilder = new PayloadNotificationBuilder($title);

        $badge = Functions::countBadge($accountId);

        $notificationBuilder->setBody($content)
            ->setBadge($badge)
            ->setSound('default');

        $dataBuilder = new PayloadDataBuilder();

        if (!empty($payload)) {
            $payloadArr = json_decode($payload, true);
        }

        $payloadArr['notification_id'] = $notificationId;

        if (!empty($payloadArr)) {
            if ($isAndroid == 'yes') {
                $payloadArr['title'] = $title;
                $payloadArr['badge'] = $badge;
                $payloadArr['body'] = $content;
            }

            $dataBuilder->addData($payloadArr);
        } else {

            if ($isAndroid == 'yes') {

                $payloadArr['title'] = null;
                $payloadArr['badge'] = null;
                $payloadArr['body'] = null;

            }

            $dataBuilder->addData([
                'type' => null,
                'id' => null
            ]);
        }

        $option = $optionBuiler->build();
        $notification = $notificationBuilder->build();

        $data = $dataBuilder->build();

        if ($isAndroid == 'yes') {

            $downstreamResponse = FCM::sendTo($token, $option, $notification, $data);

        } else {
            $downstreamResponse = FCM::sendTo($token, $option, $notification, $data);
        }

        if (!empty($downstreamResponse)) {
            \App\Models\Notification::find($notificationId)->forceFill([
                'status' => \App\Models\Notification::PUSHED
            ])->save();

            $downstreamResponse->numberSuccess();
            $downstreamResponse->numberFailure();
            $downstreamResponse->numberModification();

//return Array - you must remove all this tokens in your database
            $deleteTokens = $downstreamResponse->tokensToDelete();

            if (is_array($deleteTokens)) {

                foreach ($deleteTokens as $deleteToken) {
                    User::where('android_token', $deleteToken)->update([
                        'android_token' => null
                    ]);

                    User::where('ios_token', $deleteToken)->update([
                        'ios_token' => null
                    ]);
                }
            }

            $modifyTokens = $downstreamResponse->tokensToModify();

            if (is_array($modifyTokens)) {

                foreach ($modifyTokens as $oldToken => $modifyToken) {
                    User::where('android_token', $oldToken)->update([
                        'android_token' => $modifyToken
                    ]);

                    User::where('ios_token', $oldToken)->update([
                        'ios_token' => $modifyToken
                    ]);
                }
            }
        }

        return;

    }


    public function handle()
    {

        $notifications = \DB::table('notifications')->select(DB::raw('notifications.*, users.ios_token, users.android_token, users.webpush_token'))
            ->leftJoin('users', 'notifications.to_user', '=', 'users.id')
            ->where('notifications.status', \App\Models\Notification::NOT_PUSH)
            ->get();


        foreach ($notifications as $notification) {
            try {


                if (!empty($notification->ios_token)) {
                    $this->pushNotification($notification->to_user, $notification->title, $notification->id,
                        $notification->ios_token, $notification->content, $isAndroid = 'no', $notification->payload);
                    $this->line('Success send notification ios to ' . $notification->id);
                }

                if (!empty($notification->android_token)) {

                    $this->pushNotification($notification->to_user, $notification->title, $notification->id,
                        $notification->android_token, $notification->content, $isAndroid = 'yes', $notification->payload);
                    $this->line('Success send notification android to ' . $notification->id);
                }
                if (!empty($notification->webpush_token)) {

                    $this->pushNotificationBrowser($notification->to_user, $notification->content, $notification->id);
                    $this->line('Success send notification browser to ' . $notification->id);
                }


            } catch (\Exception $ex) {
//                dump($ex->getMessage());
//                dd($ex->getTraceAsString());
            }
        }
    }
}
