<?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\Templating\Entity;

use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * @implements ChillEntityRenderInterface<SocialAction>
 */
class SocialActionRender implements ChillEntityRenderInterface
{
    final public const AND_CHILDREN_MENTION = 'show_and_children_mention';

    final public const DEFAULT_ARGS = [
        self::SEPARATOR_KEY => ' > ',
        self::NO_BADGE => false,
        self::SHOW_AND_CHILDREN => false,
        self::AND_CHILDREN_MENTION => 'social_action.and children',
        self::SHOW_SOCIAL_ISSUE => false,
        self::SHOW_DEACTIVATED => false,
    ];

    /**
     * if true, the action will not be encapsulated into a "badge".
     */
    final public const NO_BADGE = 'no-badge';

    final public const SEPARATOR_KEY = 'default.separator';

    /**
     * Show a mention "and children" on each SocialAction, if the social action
     * has at least one child.
     */
    final public const SHOW_AND_CHILDREN = 'show_and_children';

    /**
     * Append the related social issue next to the social action name, in parenthesis.
     *
     * Currently only in string rendering.
     */
    final public const SHOW_SOCIAL_ISSUE = 'show_social_issue';

    /**
     * Append a mention "deactivated" next to the social action name, in parenthesis, if the social action is deactivated.
     *
     * Currently only in string rendering.
     */
    final public const SHOW_DEACTIVATED = 'show_deactivated';

    public function __construct(
        private readonly TranslatableStringHelper $translatableStringHelper,
        private readonly \Twig\Environment $engine,
        private readonly TranslatorInterface $translator,
        private readonly SocialIssueRender $socialIssueRender,
        private readonly ClockInterface $clock,
    ) {}

    public function renderBox($socialAction, array $options): string
    {
        $options = \array_merge(self::DEFAULT_ARGS, $options);
        // give some help to twig: an array of parents
        $parents = $this->buildParents($socialAction);

        return $this->engine->render('@ChillPerson/Entity/social_action.html.twig', [
            'socialAction' => $socialAction,
            'parents' => $parents,
            'options' => $options,
        ]);
    }

    public function renderString($socialAction, array $options): string
    {
        /** @var SocialAction $socialAction */
        $options = \array_merge(self::DEFAULT_ARGS, $options);
        $titles = [$this->translatableStringHelper->localize($socialAction->getTitle())];

        while ($socialAction->hasParent()) {
            $socialAction = $socialAction->getParent();
            $titles[] = $this->translatableStringHelper->localize(
                $socialAction->getTitle()
            );
        }

        $titles = \array_reverse($titles);

        $title = \implode($options[self::SEPARATOR_KEY], $titles);

        if ($options[self::SHOW_AND_CHILDREN] && $socialAction->hasChildren()) {
            $title .= ' ('.$this->translator->trans($options[self::AND_CHILDREN_MENTION]).')';
        }

        if ($options[self::SHOW_SOCIAL_ISSUE]) {
            $title .= ' ('.$this->socialIssueRender->renderString($socialAction->getIssue(), []).')';
        }

        if ($options[self::SHOW_DEACTIVATED] && $socialAction->isDesactivated(\DateTime::createFromImmutable($this->clock->now()))) {
            $title .= ' ('.$this->translator->trans('Disabled').')';
        }

        return $title;
    }

    public function supports($entity, array $options): bool
    {
        return $entity instanceof SocialAction;
    }

    protected function buildParents($socialAction): array
    {
        $parents = [];

        while ($socialAction->hasParent()) {
            $socialAction = $parents[] = $socialAction->getParent();
        }

        return $parents;
    }
}
