<?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\DataFixtures\ORM;

use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
use Chill\MainBundle\Entity\User;
use Chill\PersonBundle\DataFixtures\Helper\PersonRandomHelper;
use Chill\PersonBundle\Entity\Relationships\Relation;
use Chill\PersonBundle\Entity\Relationships\Relationship;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;

class LoadRelationships extends Fixture implements DependentFixtureInterface
{
    use PersonRandomHelper;

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

    public function getDependencies(): array
    {
        return [
            LoadPeople::class,
            LoadRelations::class,
        ];
    }

    public function load(ObjectManager $manager): void
    {
        /** @var array<int, array<int, 1>> $existing */
        $existing = [];

        for ($i = 0; 20 > $i; ++$i) {
            $user = $this->getRandomUser();
            $date = new \DateTimeImmutable();
            $relationship = (new Relationship())
                ->setFromPerson($this->getRandomPerson($this->em))
                ->setToPerson($this->getRandomPerson($this->em))
                ->setRelation($this->getReference(LoadRelations::RELATION_KEY.
                    random_int(0, \count(LoadRelations::RELATIONS) - 1), Relation::class))
                ->setReverse((bool) random_int(0, 1))
                ->setCreatedBy($user)
                ->setUpdatedBy($user)
                ->setCreatedAt($date)
                ->setUpdatedAt($date);

            // remove the potential duplicates
            $set = [
                min($relationship->getFromPerson()->getId(), $relationship->getToPerson()->getId()),
                max($relationship->getFromPerson()->getId(), $relationship->getToPerson()->getId()),
            ];

            if (\array_key_exists($set[0], $existing) && \array_key_exists($set[1], $existing[$set[0]])) {
                continue;
            }
            $existing[$set[0]][$set[1]] = 1;

            $manager->persist($relationship);
        }

        $manager->flush();
    }

    private function getRandomUser(): User
    {
        $userRef = array_rand(LoadUsers::$refs);

        return $this->getReference($userRef, User::class);
    }
}
