<?php

namespace App\Repository;

use App\Entity\Company;
use App\Entity\User;
use DateTime;
use DateTimeZone;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;

/**
 * @extends ServiceEntityRepository<User>
 */
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, User::class);
    }

    public function updateLastLogin(User $user): void
    {
        $currentTime = new DateTime('now', new DateTimeZone($_ENV['COMPANY_TIMEZONE']));
        $qb = $this->createQueryBuilder('u');
        $q = $qb->update(User::class, 'u')
               ->set('u.lastLogin', "'{$currentTime->format('Y-m-d H:i:s')}'")
               ->where('u.id = :id')
               ->setParameter('id', $user->getId()->toBinary())
               ->getQuery()
        ;

        $q->execute();
    }

    /**
     * Used to upgrade (rehash) the user's password automatically over time.
     */
    public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
        }

        $user->setPassword($newHashedPassword);
        $this->getEntityManager()->persist($user);
        $this->getEntityManager()->flush();
    }

    public function getCaseManagers(Company $company): array
    {
        return $this->createQueryBuilder('u')
            ->andWhere('u.roles LIKE :role')
            ->andWhere('u.company = :company')
            ->setParameter('role', '%ROLE_CASE_MANAGER%')
            ->setParameter('company', $company->getId()->toBinary())
            ->getQuery()
            ->getResult()
        ;
    }

    public function getTherapists(Company $company): array
    {
        return $this->createQueryBuilder('u')
            ->andWhere('u.roles LIKE :role')
            ->andWhere('u.company = :company')
            ->setParameter('role', '%ROLE_THERAPIST%')
            ->setParameter('company', $company->getId()->toBinary())
            ->getQuery()
            ->getResult()
        ;
    }

    public function getAdmins(Company $company): array
    {
        return $this->createQueryBuilder('u')
            ->andWhere('u.roles LIKE :role')
            ->andWhere('u.company = :company')
            ->setParameter('role', '%ROLE_ADMIN%')
            ->setParameter('company', $company->getId()->toBinary())
            ->getQuery()
            ->getResult()
        ;
    }

    public function getCompanyUsers(Company $company): array
    {
        return $this->createQueryBuilder('u')
            ->andWhere('u.company = :company')
            ->setParameter('company', $company->getId()->toBinary())
            ->orderBy('u.name', 'ASC')
            ->getQuery()
            ->getResult()
        ;
    }

    public function getCaseWorkers(): array
    {
        return $this->createQueryBuilder('u')
            ->andWhere('u.roles LIKE :role')
            ->setParameter('role', '%ROLE_CASE_WORKER%')
            ->orderBy('u.name', 'ASC')
            ->getQuery()
            ->getResult()
        ;
    }
}
