<?php

namespace App\Console\Commands\Mock;

use App\Packages\Capsule\Models\Capsule;
use App\Packages\Capsule\Models\CapsuleComment;
use App\Packages\Capsule\Models\CapsuleLike;
use App\Packages\Capsule\Models\CapsuleSubscriber;
use App\Packages\Capsule\Models\CapsuleTaggedUser;
use App\Packages\User\Models\User;
use App\Packages\User\Models\UserNotification;
use App\Packages\User\Notifications\TypesNotification;
use Illuminate\Console\Command;
use Faker\Generator as Faker;
use Illuminate\Support\Collection;

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

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create mock notifications';

    /**
     * @var Faker $faker
     */
    protected $faker;

    /**
     * @var UserNotification $notify
     */
    protected $notify;

    /**
     * Create a new command instance.
     *
     * @param Faker $faker
     * @param UserNotification $notify
     */
    public function __construct(Faker $faker, UserNotification $notify)
    {
        parent::__construct();
        $this->faker = $faker;
        $this->notify = $notify;
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $users = User::repository()->getRegisteredUsers();

        if ( ! $users ) {
            $this->info('No registered users');
            return false;
        }

        $capsules = Capsule::repository()->all();

        if ( ! $capsules ) {
            $this->info('No capsules');
            return false;
        }

        $max_notifications = (int) $this->ask('Max notifications per capsule')?:7;

        $status_bar = $this->output->createProgressBar($capsules->count());
        $status_bar->start();

        foreach ($capsules as $capsule) {

            for ($i = 0; $i <= rand(0, $max_notifications); $i++) {

                $type = rand(1, 7);

                if ( $type == TypesNotification::COMMENT ) {

                    $this->createCommentNotify($type, $capsule, $users);

                } elseif ( $type == TypesNotification::LIKE ) {

                    $this->createLikeNotify($type, $capsule, $users);

                } elseif ( $type == TypesNotification::NEW_SUBSCRIBER ) {

                    $this->createSubscriberNotify($type, $capsule, $users);

                } elseif ( $type == TypesNotification::CAPSULE_TAGGED ) {

                    $this->createTaggedNotify($type, $capsule, $users);

                } else {

                    $this->createNotify($type, $capsule, $users);
                }
            }

            $status_bar->advance();
        }

        $status_bar->finish();
        $this->info('');
    }

    /**
     * @param $type
     * @param Capsule $capsule
     * @param User|Collection $users
     */
    private function createCommentNotify($type, $capsule, $users)
    {
        $comment_table = (new CapsuleComment())->getTable();

        $comment = \DB::table($comment_table . ' as c')
            ->select('c.*')
            ->join($this->notify->getTable() . ' as n', 'n.comment_id', '=', 'c.id', 'left')
            ->where('c.capsule_id', '=', $capsule->id)
            ->where('n.id', '=', null)
            ->first();

        if ( ! $comment ) {
            $comment = CapsuleComment::createComment($capsule, $users->random(), $this->faker->text());

            /** Refresh total comment for capsule */
            $capsule->refreshCommentCount();

            /** Refresh total comment for user */
            $comment->user->refreshCommentCount();
        }

        $this->createNotify($type, $capsule, $users, $comment->id);
    }

    /**
     * @param $type
     * @param Capsule $capsule
     * @param User|Collection $users
     */
    private function createLikeNotify($type, $capsule, $users)
    {
        $like_table = (new CapsuleLike)->getTable();

        $like = \DB::table($like_table . ' as l')
            ->select('l.*')
            ->join($this->notify->getTable() . ' as n', 'n.user_id', '=', 'l.user_id', 'left')
            ->where('l.capsule_id', '=', $capsule->id)
            ->where('n.id', '=', null)
            ->first();

        if ( ! $like ) {
            $like = CapsuleLike::createLike($capsule, $users->random());

            /** Refresh total like for capsule */
            $capsule->refreshLikeCount();
        }

        $this->createNotify($type, $capsule, $users, $like->user_id);
    }

    /**
     * @param $type
     * @param Capsule $capsule
     * @param User|Collection $users
     */
    private function createSubscriberNotify($type, $capsule, $users)
    {
        $subscriber_table = (new CapsuleSubscriber())->getTable();

        $subscriber = \DB::table($subscriber_table . ' as s')
            ->select('s.*')
            ->join($this->notify->getTable() . ' as n', 'n.user_id', '=', 's.user_id', 'left')
            ->where('s.capsule_id', '=', $capsule->id)
            ->where('n.id', '=', null)
            ->first();

        if ( ! $subscriber ) {
            $subscriber = CapsuleSubscriber::createSubscriber($capsule, $users->random());

            /** Refresh total subscribers for capsule */
            $capsule->refreshSubscribersCount();

            /** Refresh total subscribers for user */
            $capsule->user->refreshSubscriptionCount();
        }

        $this->createNotify($type, $capsule, $users, $subscriber->user_id);
    }

    /**
     * @param $type
     * @param Capsule $capsule
     * @param User|Collection $users
     */
    private function createTaggedNotify($type, $capsule, $users)
    {
        $tagged_table = (new CapsuleTaggedUser())->getTable();

        $tagged = \DB::table($tagged_table . ' as t')
            ->select('t.*')
            ->join($this->notify->getTable() . ' as n', 'n.user_id', '=', 't.user_id', 'left')
            ->where('t.capsule_id', '=', $capsule->id)
            ->where('n.id', '=', null)
            ->first();

        if ( ! $tagged ) {
            $owner = $users->random();
            $user = User::where('id', '!=', $owner->id)->inRandomOrder()->first();
            $tagged = CapsuleTaggedUser::assignTaggedUser($capsule, $owner, $user);

            /** Refresh total tagged users for capsule */
            $capsule->refreshTaggedUserCount();
        }

        $this->createNotify($type, $capsule, $users, $tagged->user_id);
    }

    /**
     * @param $type
     * @param Capsule $capsule
     * @param User|Collection $users
     * @param $relation_id
     */
    private function createNotify($type, $capsule, $users, $relation_id = false)
    {
        $notify = new UserNotification();
        $notify->owner_id = $users->random()->id;
        $notify->type = $type;
        $notify->capsule_id = $capsule->id;

        /** Comment */
        if ( $type == TypesNotification::COMMENT ) $notify->comment_id = $relation_id;

        /** Like || Subscriber || Tagged */
        if ( $type == TypesNotification::LIKE
            || $type == TypesNotification::CAPSULE_TAGGED
            || $type == TypesNotification::NEW_SUBSCRIBER
        ) {
            $notify->user_id = $relation_id;
        }

        $notify->is_seen = rand(0, 1);
        $notify->content = "";
        $notify->persist();
    }
}
