<?php

namespace App\Packages\User\Repository;

use App\Packages\Core\Repository\AbstractRepository;
use App\Packages\User\Models\User;
use App\Packages\User\Models\UserNotificationPush;
use App\Packages\User\Notifications\TypesNotification;
use DB;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Safe\Type;

/**
 * Class UserNotificationPushRepository
 * @package App\Packages\User\Repository
 *
 * @method UserNotificationPush firstById($id)
 *
 * @property UserNotificationPush $model
 */
class UserNotificationPushRepository extends AbstractRepository
{

    const LIMIT_PAGE = 20;

    public static function init()
    {
        return new UserNotificationPushRepository(UserNotificationPush::class);
    }

    private function baseQuery(User $user)
    {
        $query = $this->query()
            ->distinct()
            ->select('table_user_notification_push.*')
            ->leftJoin(
                'table_friend_relation as friend',
                'friend.friend_id',
                '=',
                'table_user_notification_push.user_id'
            )
            ->leftJoin(
                'table_capsule as capsule',
                'capsule.id',
                '=',
                'table_user_notification_push.capsule_id'
            )
            ->leftJoin('table_capsule_tagged_user as tagged', function(JoinClause $join) use ($user) {
                $join->on('tagged.capsule_id', '=', 'capsule.id')
                    ->on('tagged.user_id', '=', DB::raw($user->id));
            })

            /** For notifications without friends */
            ->where(function ($query) use ($user) {
                /** @var Builder $query */
                $query->whereRaw('"table_user_notification_push"."owner_id" = "table_user_notification_push"."user_id"')
                    ->orWhereNull('table_user_notification_push.user_id')
                    ->orWhere('friend.user_id', '=', $user->id);
            })

            /** For blocked capsule */
            ->where(function ($query) use ($user) {
                /** @var Builder $query */
                $query->where(function ($q) use ($user) {
                    /** @var Builder $q */
                    $q->whereNotNull("table_user_notification_push.capsule_id")
                        ->where(function ($q1) {
                            /** @var Builder $q1 */
                            $q1->where([
                                ["capsule.blocked", true],
                                ["table_user_notification_push.type", "=", TypesNotification::BLOCKED]
                            ])
                                ->orWhere("capsule.blocked", false);
                        })
                        ->where(function ($q) use ($user) {
                            /** @var Builder $q */
                            $q->where("capsule.is_private", "=", false)
                                ->orWhere(function ($q) use ($user) {
                                    /** @var Builder $q */
                                    $q->whereNotNull('tagged.id')
                                        ->orWhere('capsule.user_id', '=', $user->id);
                                });
                        });
                })
                    ->orWhereNull("table_user_notification_push.capsule_id");
            });

        return $query;
    }

    /**
     * @param User $user
     * @param string $lastCreatedAt
     *
     * @return UserNotificationPush[]|Collection
     */
    public function getList(User $user, $lastCreatedAt)
    {
        $query = $this->baseQuery($user)
            ->take(static::LIMIT_PAGE)
            ->where('table_user_notification_push.owner_id', '=', $user->id)
            ->orderBy('table_user_notification_push.created_at', 'desc');

        if ($lastCreatedAt) {
            $query->where('table_user_notification_push.created_at_micro', '<', $lastCreatedAt);
        }

        return $query->get();
    }

    /**
     * @param User $user
     *
     * @return int
     */
    public function userNotificationsCount(User $user)
    {
        $count = $this->baseQuery($user)
            ->where('table_user_notification_push.owner_id', '=', $user->id)
            ->count('table_user_notification_push.id');

        return $count;
    }

    /**
     * @param User $user
     *
     * @return int
     */
    public function newNotificationsExists(User $user)
    {
        $query = $this->baseQuery($user)
//			->take(static::LIMIT_PAGE)
            ->where('table_user_notification_push.owner_id', '=', $user->id)
//			->orderBy('created_at', 'desc')
            ->where('table_user_notification_push.created_at_micro', '>', $user->last_notification_seen);

        return $query->count();
    }

    /**
     * @param User $friend
     * @param User $user
     *
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|null
     */
    public function findFriendInvite(User $friend, User $user) {
        return $this->query()
            ->where('owner_id', $friend->id)
            ->where('user_id', $user->id)
            ->where('type', TypesNotification::INVITE_NEW)
            ->first();
    }

}
