<?php

namespace App\Packages\User\Repository;

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

/**
 * Class UserRepository
 * @package App\Packages\User\Repository\v3
 *
 * @method UserNotification firstById($id)
 *
 * @property UserNotification $model
 */
class UserNotificationRepository extends AbstractRepository
{
	const LIMIT_PAGE = 20;

	public static function init()
    {
        return new UserNotificationRepository(UserNotification::class);
    }

	private function baseQuery(User $user)
    {
        $query = $this->query()
            ->select('table_user_notification.*')
            ->distinct()
            ->leftJoin(
                'table_friend_relation as friend',
                'friend.friend_id',
                '=',
                'table_user_notification.user_id'
            )
            ->leftJoin(
                'table_capsule as capsule',
                'capsule.id',
                '=',
                'table_user_notification.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));
            })

            ->where(function ($query) use ($user) {
                /** @var Builder $query */
                $query->whereRaw('"table_user_notification"."owner_id" = "table_user_notification"."user_id"')
                    ->orWhereNull('table_user_notification.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.capsule_id")
                        ->where(function ($q1) {
                            /** @var Builder $q1 */
                            $q1->where([
                                ["capsule.blocked", true],
                                ["table_user_notification.is_seen", false],
                                ["table_user_notification.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.capsule_id");
            });

        return $query;
    }

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

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

		return $query->get();
	}

    /**
     * @param User $user
     * @param string $lastCreatedAt
     * @param int $page
     */
    public function getListPaginated(User $user, $lastCreatedAt, $page)
    {
        $query = $this->baseQuery($user)
            ->where('table_user_notification.owner_id', '=', $user->id)
            ->orderBy('table_user_notification.created_at', 'desc');

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

        $query->skip(($page - 1) * static::LIMIT_PAGE)->take(static::LIMIT_PAGE);

        return $query->get();
    }

	/**
	 * @param User $user
	 *
	 * @return int
	 */
	public function userNotificationsCount(User $user)
	{
		$count = $this->baseQuery($user)
			->where('table_user_notification.owner_id', '=', $user->id)
            ->count('table_user_notification.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.owner_id', '=', $user->id)
//			->orderBy('created_at', 'desc')
			->where('table_user_notification.created_at_micro', '>', $user->last_notification_seen);

		return $query->count();
	}
}
