<?php

namespace App\Repository;

use App\Entity\Directory;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;

/**
 * @method Directory|null find($id, $lockMode = null, $lockVersion = null)
 * @method Directory|null findOneBy(array $criteria, array $orderBy = null)
 * @method Directory[]    findAll()
 * @method Directory[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class DirectoryRepository extends ServiceEntityRepository
{
    private array $fields;
    private QueryBuilder $qb;
    private ?QueryBuilder $qbsearch = null;

    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Directory::class);
        $this->fields = [
            'gender',
            'height',
            'weight',
            'phone',
            'address',
            'firstname',
            'lastname',
            'medicalFamilyHistory',
            'medicalHistory',
            'medicalAllergies',
            'medicalBloodGroup',
            'medicalDrugs',
            'medicalAlcohol',
            'medicalTreatment',
            'gangInfo'
        ]; //list fields we can search in
    }

    /**
     * Prepare user list (use -> getResult() to get results)
     *
     * @return this
     */
    public function list()
    {
        $this->qbsearch = null;
        $this->qb = $this->createQueryBuilder("d");
        return $this;
    }

    public function limit(int $limit)
    {
        $this->qb->setMaxResults($limit);
        return $this;
    }

    public function wanted()
    {
        $this->qb->andWhere('d.wanted = 1');
        return $this;
    }

    public function dead()
    {
        $this->qb->andWhere('d.dead = 1');
        return $this;
    }

    public function notDead()
    {
        $this->qb->andWhere('d.dead = 0');
        return $this;
    }

    public function wantedDisplay()
    {
        $this->qb->andWhere('d.wantedDisplay = 1');
        return $this;
    }

    public function wantedNotDisplay()
    {
        $this->qb->andWhere('d.wantedDisplay = 0');
        return $this;
    }

    public function order(array $order)
    {
        foreach ($order as $key => $value) {
            if ($key === array_key_first($order)) {
                $this->qb->orderBy('d.' . $key, $value);
            } else {
                $this->qb->addorderBy('d.' . $key, $value);
            }
        }
        return $this;
    }

    /**
     * Search a value in directories
     *
     * @param string|null $search
     * @return this
     */
    public function search(?string $search)
    {
        if (null === $search) {
            return $this;
        }

        if (null === $this->qbsearch) {
            $this->qbsearch = $this ->createQueryBuilder("s")
                                    ->where('s.firstname LIKE :searchkey')
                                    ->orWhere('s.lastname LIKE :searchkey')
                                    ->orWhere('s.id LIKE :searchkey');

            $searchTime = str_replace('/', '-', $search);
            if (($timestamp = strtotime($searchTime)) != false) {
                $this->qbsearch->orWhere('s.birthdate LIKE :searchkeydate')
                ->setParameter('searchkeydate', '%' . date('Y-m-d', $timestamp) . '%');
            }
        }


        foreach ($this->fields as $key => $value) {
            $this->qbsearch->orWhere('s.' . $value . ' LIKE :searchkey');
        }

        $this->qbsearch->setParameter('searchkey', '%' . $search . '%');

        return $this;
    }

    public function getResult()
    {
        if (null !== $this->qbsearch) {
            $this->qbsearch->andWhere($this->qb->expr()->in('s.id', $this->qb->getDQL()));
            return $this->qbsearch->getQuery()->getResult();
        }
        return $this->qb->getQuery()->getResult();
    }
}
