<?php

namespace App\Policy\Simulation;

use App\Appointment\Entity\Appointment;
use App\Policy\Entity\Policy;
use Doctrine\ORM\EntityManagerInterface;

/**
 * نمونهٔ نوبت‌های واقعیِ گذشته برای آزمایش یک قانون.
 *
 * نمونه به **دامنهٔ خود قانون** محدود می‌شود: قانون لیزر روی ۵۰ نوبت دندانپزشکی
 * «۰٪ تحت تأثیر» می‌دهد، و آن عدد گمراه‌کننده‌تر از نداشتن گزارش است.
 */
final class SimulationSampler
{
    public const DEFAULT_SIZE = 50;
    /** سقف نمونه — گزارش بزرگ‌تر نه خوانده می‌شود نه در `report` جا می‌شود. */
    public const MAX_SIZE     = 50;

    public function __construct(
        private readonly EntityManagerInterface $em,
    ) {}

    /** @return Appointment[] جدیدترین اول */
    public function recentAppointments(Policy $policy, int $size = self::DEFAULT_SIZE): array
    {
        $size = max(1, min($size, self::MAX_SIZE));


        $qb = $this->em->createQueryBuilder()
            ->select('a')
            ->from(Appointment::class, 'a')
            ->where('a.entityType = :type')
            ->andWhere('a.entityId = :id')
            ->andWhere('a.status IN (:statuses)')
            ->setParameter('type', $policy->getEntityType())
            ->setParameter('id', $policy->getEntityId())
            ->setParameter('statuses', [Appointment::STATUS_CONFIRMED, Appointment::STATUS_COMPLETED])
            ->orderBy('a.slotStart', 'DESC')
            ->setMaxResults($size);

        if ($policy->getAddress() !== null) {
            $qb->andWhere('a.addressId = :address')->setParameter('address', $policy->getAddress()->getId());
        }

        if ($policy->getServiceItem() !== null) {
            $qb->andWhere('a.serviceItem = :service')->setParameter('service', $policy->getServiceItem());
        }

        if ($policy->getCatalogCategory() !== null) {
            $qb->join('a.serviceItem', 'si')
                ->andWhere('si.catalogCategory = :category')
                ->setParameter('category', $policy->getCatalogCategory());
        }

        return $qb->getQuery()->getResult();
    }
}
