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

use Chill\MainBundle\Entity\User;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Embeddable]
class PrivateCommentEmbeddable
{
    /**
     * @var array<int, string>
     */
    #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, nullable: false, options: ['default' => '{}'])]
    private array $comments = [];

    public function getCommentForUser(User $user): string
    {
        return $this->comments[$user->getId()] ?? '';
    }

    public function getComments(): ?array
    {
        return $this->comments;
    }

    public function hasCommentForUser(User $user): bool
    {
        return \array_key_exists($user->getId(), $this->comments)
            && '' !== $this->comments[$user->getId()];
    }

    public function merge(PrivateCommentEmbeddable $newComment): self
    {
        $currentComments = $this->getComments() ?? [];

        $mergedComments = $newComment->getComments() + $currentComments;

        $this->setComments($mergedComments);

        return $this;
    }

    public function setCommentForUser(User $user, ?string $content): self
    {
        $this->comments[$user->getId()] = trim((string) $content);

        return $this;
    }

    public function setComments(array $comments)
    {
        $this->comments = $comments;

        return $this;
    }

    /**
     * Merges comments from the provided object into the current object.
     *
     * Identifies common user IDs between the current object's comments and the
     * newComment's comments. If a user ID exists in both, their comments are
     * concatenated with the provided separator. If a user ID exists only in the
     * newComment, their comment is added to the current object directly.
     *
     * @param self   $commentsToAppend the object containing the new comments to be merged
     * @param string $separator        the string used to separate concatenated comments
     */
    public function concatenateComments(self $commentsToAppend, string $separator = "\n\n-----------\n\n"): void
    {
        $commonUserIds = array_intersect(array_keys($this->comments), array_keys($commentsToAppend->getComments()));

        foreach ($commentsToAppend->getComments() as $userId => $comment) {
            if (in_array($userId, $commonUserIds, true)) {
                $this->comments[$userId] = $this->comments[$userId].$separator.$commentsToAppend->getComments()[$userId];
            } else {
                $this->comments[$userId] = $commentsToAppend->getComments()[$userId];
            }
        }
    }
}
