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

use Chill\MainBundle\DataFixtures\ORM\LoadCenters;
use Chill\MainBundle\DataFixtures\ORM\LoadPostalCodes;
use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\PostalCode;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use libphonenumber\PhoneNumberUtil;
use Nelmio\Alice\Loader\NativeLoader;
use Nelmio\Alice\ObjectSet;

class LoadThirdParty extends Fixture implements DependentFixtureInterface
{
    private readonly PhoneNumberUtil $phoneNumberUtil;

    public function __construct()
    {
        $this->phoneNumberUtil = PhoneNumberUtil::getInstance();
    }

    public function getDependencies(): array
    {
        return [
            LoadCenters::class,
            LoadPostalCodes::class,
        ];
    }

    public function load(ObjectManager $manager): void
    {
        $thirdParties = $this->getThirdParties()->getObjects();

        foreach ($thirdParties as $name => $thirdParty) {
            if ('a' === $name[0]) {
                // this is an address
                continue;
            }
            $thirdParty->setCreatedAt(new \DateTimeImmutable('today'));

            foreach ($this->getCenters() as $center) {
                $thirdParty->addCenter($center);
            }

            $manager->persist($thirdParty);
        }

        $manager->flush();
    }

    private function getCenters(): \Iterator
    {
        $references = \array_map(
            static fn ($a) => $a['ref'],
            LoadCenters::$centers
        );
        $number = random_int(1, \count($references));

        if (1 === $number) {
            yield $this->getReference($references[array_rand($references)], Center::class);
        } else {
            foreach (array_rand($references, $number) as $index) {
                yield $this->getReference($references[$index], Center::class);
            }
        }
    }

    private function getPostalCode(): PostalCode
    {
        $ref = LoadPostalCodes::$refs[array_rand(LoadPostalCodes::$refs)];

        return $this->getReference($ref, PostalCode::class);
    }

    private function getThirdParties(): ObjectSet
    {
        $loader = new NativeLoader();

        return $loader->loadData([
            Address::class => [
                'address{1..75}' => [
                    'street' => '<fr_FR:streetName()>',
                    'streetNumber' => '<fr_FR:buildingNumber()>',
                    'validFrom' => '<dateTimeBetween(\'-1 year\', \'now\')>',
                    'postCode' => $this->getPostalCode(),
                ],
            ],
            ThirdParty::class => [
                'thirdparty{1..75}' => [
                    'name' => '<fr_FR:company()>',
                    'telephone' => $this->phoneNumberUtil->getExampleNumber('FR'),
                    'email' => '<email()>',
                    'comment' => '<fr_FR:realTextBetween(10, 500)>',
                    'address' => '@address<current()>',
                ],
            ],
        ]);
    }
}
