<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig;

use CpCreation\VitiCore\Contact\Model\Contact;

final class LegalContentRenderer
{
    private const string TOKEN_PATTERN = '/\{\{\s*(contact\.[a-zA-Z][a-zA-Z0-9]*)\s*\}\}/';

    public function render(?string $content, Contact $contact): string
    {
        if (null === $content || '' === mb_trim($content)) {
            return '';
        }

        return preg_replace_callback(
            self::TOKEN_PATTERN,
            fn(array $matches): string => $this->renderToken($matches[1], $matches[0], $contact),
            $content,
        ) ?? $content;
    }

    private function renderToken(string $token, string $original, Contact $contact): string
    {
        $value = match ($token) {
            'contact.company' => (string) $contact->getCompany(),
            'contact.companyUpper' => mb_strtoupper((string) $contact->getCompany()),
            'contact.firstname' => (string) $contact->getFirstname(),
            'contact.lastname' => (string) $contact->getLastname(),
            'contact.fullName' => $this->join($contact->getFirstname(), $contact->getLastname()),
            'contact.address' => (string) $contact->getAddress(),
            'contact.postal' => (string) $contact->getPostal(),
            'contact.city' => (string) $contact->getCity(),
            'contact.fullAddress' => $this->join($contact->getAddress(), $contact->getPostal(), $contact->getCity()),
            'contact.phone', 'contact.phone1' => (string) $contact->getPhone1(),
            'contact.email', 'contact.emailFrom' => (string) $contact->getEmailFrom(),
            'contact.editorCompany' => (string) $contact->getEditorCompany(),
            'contact.editorAddress' => (string) $contact->getEditorAddress(),
            'contact.editorPostal' => (string) $contact->getEditorPostal(),
            'contact.editorCity' => (string) $contact->getEditorCity(),
            'contact.editorFullAddress' => $this->join(
                $contact->getEditorAddress(),
                $contact->getEditorPostal(),
                $contact->getEditorCity(),
            ),
            'contact.editorRcs' => (string) $contact->getEditorRcs(),
            'contact.editorTva' => (string) $contact->getEditorTva(),
            default => null,
        };

        return null === $value ? $original : $this->escape($value);
    }

    private function join(?string ...$parts): string
    {
        return implode(' ', array_filter(
            array_map(static fn(?string $part): string => mb_trim((string) $part), $parts),
            static fn(string $part): bool => '' !== $part,
        ));
    }

    private function escape(string $value): string
    {
        return htmlspecialchars($value, \ENT_QUOTES | \ENT_SUBSTITUTE, 'UTF-8');
    }
}
