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

use Chill\MainBundle\Repository\UserRepositoryInterface;
use Chill\MainBundle\Templating\Entity\UserRender;

class UserHelper
{
    public function __construct(private readonly UserRender $userRender, private readonly UserRepositoryInterface $userRepository) {}

    /**
     * Return a callable that will transform a value into a string representing a user.
     *
     * The callable may receive as argument:
     *
     * - an int or a string, the id of the user;
     * - a string containing a json which will be decoded, and will have this structure: array{uid: int, d: string}. The job and scopes will be shown at this date
     *
     * @param string $key    the key of the content
     * @param array  $values the list of values
     * @param string $header the header's content
     */
    public function getLabel($key, array $values, string $header): callable
    {
        return function (int|string|null $value) use ($header) {
            if ('_header' === $value) {
                return $header;
            }

            if (null === $value) {
                return '';
            }

            if (is_numeric($value)) {
                $uid = $value;
                $date = null;
            } else {
                $decode = json_decode($value, true, 512, JSON_THROW_ON_ERROR);
                $uid = $decode['uid'];

                if (null === $uid) {
                    return '';
                }

                $date = new \DateTimeImmutable($decode['d']);
            }

            if (null === $user = $this->userRepository->find($uid)) {
                return '';
            }

            return $this->userRender->renderString($user, ['at' => $date]);
        };
    }

    /**
     * Return a callable that will transform a value into a string representing a user.
     *
     *  The callable may receive as argument:
     *
     *  - an int or a string, the id of the user;
     *
     * @param string $key    the key of the element
     * @param array  $values a list of values
     * @param string $header the header's content
     */
    public function getLabelMulti($key, array $values, string $header): callable
    {
        return function ($value) use ($header) {
            if ('_header' === $value) {
                return $header;
            }

            if (null === $value) {
                return '';
            }

            $decoded = json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR);

            if (0 === \count($decoded)) {
                return '';
            }
            $asStrings = [];

            if (array_key_exists('uid', $decoded) || is_numeric($decoded)) {
                // this is a single value. We have to wrap it into an array
                $decoded = [$decoded];
            }

            foreach ($decoded as $userId) {
                if (is_array($userId)) {
                    $uid = $userId['uid'];
                    $date = new \DateTimeImmutable($userId['d']);
                } else {
                    $uid = $userId;
                    $date = null;
                }

                if (null === $uid) {
                    continue;
                }

                $user = $this->userRepository->find($uid);

                if (null === $user) {
                    continue;
                }

                $asStrings[$uid] = $this->userRender->renderString($user, ['absence' => false, 'at' => $date]);
            }

            return implode('|', $asStrings);
        };
    }
}
