<?php

/**
 * Lifestyle Webconsulting GmbH
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is private by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * @copyright  2018 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */

namespace LifeStyle\SamlAuthBundle\Database\Data\User;

use LifeStyle\SamlAuthBundle\Database\Manager as DbManger;
use LifeStyle\SamlAuthBundle\Entity\User;
use LifeStyle\SamlAuthBundle\Security\User\SamlUser;
use LifeStyle\SamlAuthBundle\Entity\UserLoginHistory;
use LifeStyle\SamlAuthBundle\Entity\User as UserEntity;
use LifeStyle\SamlAuthBundle\Model\UserData\User as UserModel;

/**
 * Class Index
 * @package LifeStyle\SamlAuthBundle\Database\Data\User
 */
class Index
{
    /**
     * @var DbManger
     */
    private $dbM;

    /**
     * Factory constructor.
     * @param DbManger $dbM
     */
    public function __construct(DbManger $dbM)
    {
        $this->dbM = $dbM;
    }

    /**
     * @param string $guid
     * @return UserEntity|null
     */
    public function findUserByGuid($guid)
    {
        $criteria = [
            'userGuid' => $guid,
        ];
        $user = $this->dbM->repository()->user()->findOneBy($criteria);

        return $user instanceof User ? $user : null;
    }

    /**
     * @param UserModel $userModel
     * @return UserEntity
     */
    public function createUser(UserModel $userModel)
    {
        $user = $this->dbM->entity()->user();

        $user->setUserGuid($userModel->getUserGuid());
        $user->setUserName($userModel->getUsername());
        $user->setFirstName($userModel->getFirstname());
        $user->setLastName($userModel->getLastname());
        $user->setUserEmail($userModel->getEmail());

        $this->dbM->getEntityManager()->persist($user);
        $this->dbM->getEntityManager()->flush($user);

        return $user;
    }

    /**
     * @param SamlUser $user
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function updateUserLogin(SamlUser $user)
    {
        $tNow = new \DateTime();
        /** @var UserEntity $dbUser */
        $dbUser = $this->findUserByGuid($user->getUserSamlData()->getUserGuid());
        if (null === $dbUser) {
            // user does not exists in local database, add it
            $dbUser = $this->createUser($user->getUserSamlData());
        }

        $loginInterval = $tNow->modify('-1 day');
        $query = $this->dbM->getEntityManager()->createQueryBuilder();
        $query->select('u')
            ->from('LifeStyleSamlAuthBundle:User', 'u')
            ->leftJoin('u.userLoginHistory', 'uh')
            ->where('u.userGuid = :userGuid')
            ->andWhere('uh.lastLoginAt > :lastLogin')
            ->andWhere('uh.userIdentifier = :userId')
            ->setParameter('userGuid', $user->getUserSamlData()->getUserGuid())
            ->setParameter('userId', $user->getUserSamlData()->getUserIdentifier())
            ->setParameter('lastLogin', $loginInterval);
        $dbUserHistory = $query->getQuery()->getResult();

        if (count($dbUserHistory) == 0) {
            // last log entry is older than logging interval, or none exists -> log this login
            /** @var UserLoginHistory $historyEntry */
            $historyEntry = $this->dbM->entity()->userLoginHistory();
            $historyEntry->setLastLoginAt(new \DateTime());
            $historyEntry->setUserIdentifier($user->getUserSamlData()->getUserIdentifier());
            $historyEntry->setUser($dbUser);
            $dbUser->addUserLoginHistory($historyEntry);
            $dbUser->setUpdatedAt();
            $this->dbM->getEntityManager()->persist($dbUser);
        }

        $this->dbM->getEntityManager()->flush();
    }
}
