<?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\JobBundle\Export;

use Chill\JobBundle\Entity\CSPerson;
use Chill\PersonBundle\Export\Helper\CustomizeListPersonHelperInterface;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * Class ListCSPerson.
 *
 * @author Mathieu Jaumotte mathieu.jaumotte@champs-libres.coop
 */
class AddCSPersonToPersonListHelper implements CustomizeListPersonHelperInterface
{
    public function __construct(private readonly TranslatorInterface $translator) {}

    private const CSPERSON_FIELDS = [
        'dateFinDernierEmploi',
        /*            'prescripteur__name',
            'prescripteur__email',
            'prescripteur__phone',*/
        'poleEmploiId',
        'cafId',
        'cafInscriptionDate',
        'dateContratIEJ',
        'cERInscriptionDate',
        'pPAEInscriptionDate',
        'pPAESignataire',
        'cERSignataire',
        'nEETCommissionDate',
        'fSEMaDemarcheCode',
        'enfantACharge',
        'nEETEligibilite',
        'situationProfessionnelle',
    ];

    public function alterKeys(array $existing): array
    {
        $ressources = array_map(static fn ($key) => 'ressources__'.$key, CSPerson::RESSOURCES);
        $moyenTransport = array_map(static fn ($key) => 'moyen_transport__'.$key, CSPerson::MOBILITE_MOYEN_TRANSPORT);
        $accompagnements = array_map(static fn ($key) => 'accompagnements__'.$key, CSPerson::ACCOMPAGNEMENTS);
        $permisConduire = array_map(static fn ($key) => 'permis_conduire__'.$key, CSPerson::PERMIS_CONDUIRE);
        $typeContrat = array_map(static fn ($key) => 'type_contrat__'.$key, CSPerson::TYPE_CONTRAT);

        return [
            ...$existing,
            ...self::CSPERSON_FIELDS,
            ...$ressources,
            ...$moyenTransport,
            ...$accompagnements,
            ...$permisConduire,
            ...$typeContrat,
        ];
    }

    public function alterSelect(QueryBuilder $qb, \DateTimeImmutable $computedDate): void
    {
        $qb
            ->leftJoin(CSPerson::class, 'cs_person', Query\Expr\Join::WITH, 'cs_person.person = person');

        foreach (self::CSPERSON_FIELDS as $f) {
            $qb->addSelect(sprintf('cs_person.%s as %s', $f, $f));
        }

        /*        $qb->addSelect('cs_person.situationProfessionnelle as situation_prof');

                $qb->addSelect('cs_person.nEETEligibilite as nEETEligibilite');*/

        $i = 0;

        foreach (CSPerson::RESSOURCES as $key) {
            $qb->addSelect("JSONB_EXISTS_IN_ARRAY(cs_person.ressources, :param_{$i}) AS ressources__".$key)
                ->setParameter('param_'.$i, $key);
            ++$i;
        }

        foreach (CSPerson::MOBILITE_MOYEN_TRANSPORT as $key) {
            $qb->addSelect("JSONB_EXISTS_IN_ARRAY(cs_person.mobiliteMoyenDeTransport, :param_{$i}) AS moyen_transport__".$key)
                ->setParameter('param_'.$i, $key);
            ++$i;
        }

        foreach (CSPerson::TYPE_CONTRAT as $key) {
            $qb->addSelect("JSONB_EXISTS_IN_ARRAY(cs_person.typeContrat, :param_{$i}) AS type_contrat__".$key)
                ->setParameter('param_'.$i, $key);
            ++$i;
        }

        foreach (CSPerson::ACCOMPAGNEMENTS as $key) {
            $qb->addSelect("JSONB_EXISTS_IN_ARRAY(cs_person.accompagnement, :param_{$i}) AS accompagnements__".$key)
                ->setParameter('param_'.$i, $key);
            ++$i;
        }

        foreach (CSPerson::PERMIS_CONDUIRE as $key) {
            $qb->addSelect("JSONB_EXISTS_IN_ARRAY(cs_person.permisConduire, :param_{$i}) AS permis_conduire__".$key)
                ->setParameter('param_'.$i, $key);
            ++$i;
        }
    }

    public function getLabels(string $key, array $values, array $data): ?callable
    {
        if (str_contains($key, '__')) {
            return function (string|bool|null $value) use ($key): string {
                if ('_header' === $value) {
                    [$domain, $v] = explode('__', $key);

                    return 'export.list.cs_person.'.$domain.'.'.$v;
                }

                if ('1' === $value || true === $value || 't' === $value) {
                    return 'x';
                }

                return '';
            };
        }

        return match ($key) {
            'nEETEligibilite' => function (string|bool|null $value): string {
                if ('_header' === $value) {
                    return 'export.list.cs_person.neet_eligibility';
                }

                if ('1' === $value || true === $value || 't' === $value) {
                    return 'x';
                }

                return '';
            },
            'situationProfessionnelle' => function ($value) {
                if ('_header' === $value) {
                    return 'export.list.cs_person.situation_professionelle';
                }

                return $value;
            },
            'cerinscriptiondate', 'ppaeinscriptiondate', 'neetcommissiondate', 'findernieremploidate', 'cafinscriptiondate', 'contratiejdate' => function ($value) use ($key) {
                if ('_header' === $value) {
                    return $this->translator->trans($key);
                }

                if (null === $value) {
                    return '';
                }
                // warning: won't work with DateTimeImmutable as we reset time a few lines later
                $date = \DateTime::createFromFormat('Y-m-d', $value);
                $hasTime = false;

                if (false === $date) {
                    $date = \DateTime::createFromFormat('Y-m-d H:i:s', $value);
                    $hasTime = true;
                }

                // check that the creation could occur.
                if (false === $date) {
                    throw new \Exception(sprintf('The value %s could not be converted to %s', $value, \DateTime::class));
                }

                if (!$hasTime) {
                    $date->setTime(0, 0, 0);
                }

                return $date;
            },
            default => function ($value) use ($key) {
                if ('_header' === $value) {
                    return $this->translator->trans($key);
                }

                return $value;
            },
        };
    }
}
