<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\PersonBundle\Validator\Constraints\Household;

use Chill\MainBundle\Util\DateRangeCovering;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Templating\Entity\PersonRenderInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validate that a person does not belong to two household at
 * the same time.
 */
class HouseholdMembershipSequentialValidator extends ConstraintValidator
{
    public function __construct(private readonly PersonRenderInterface $render) {}

    public function validate($person, Constraint $constraint)
    {
        if (!$person instanceof Person) {
            throw new UnexpectedTypeException($person, Person::class);
        }

        $participations = $person->getHouseholdParticipationsShareHousehold();

        if (0 === $participations->count()) {
            return;
        }

        $covers = new DateRangeCovering(1, $participations->first()
            ->getStartDate()->getTimezone());

        foreach ($participations as $k => $p) {
            $covers->add($p->getStartDate(), $p->getEndDate(), $k);
        }

        $covers->compute();

        if ($covers->hasIntersections()) {
            foreach ($covers->getIntersections() as [$start, $end, $metadata]) {
                $participation = $participations[$metadata[0]];
                $nbHousehold = \count($metadata);

                $this->context
                    ->buildViolation($constraint->message)
                    ->setParameters([
                        '%person_name%' => $this->render->renderString(
                            $participation->getPerson(),
                            []
                        ),
                        // TODO when date is correctly i18n, fix this
                        '%from%' => $start->format('d-m-Y'),
                        '%nbHousehold%' => $nbHousehold,
                    ])
                    ->addViolation();
            }
        }
    }
}
