<?php

namespace App\Services;

use App\Models\FormNotificationTranslation;
use App\Services\TranslationDiff\BaseTranslationDiffService;

/**
 * Builds a user-friendly diff between two FormNotificationTranslation rows.
 * Strips HTML from the message body (keeping placeholders like {all_fields})
 * and emits one entry per changed property under the "Notifications" group.
 */
class FormNotificationTranslationDiffService extends BaseTranslationDiffService
{
    private const GROUP = 'Notifications';

    public function diff(
        FormNotificationTranslation $franchiseTranslation,
        FormNotificationTranslation $globalTranslation,
        ?string $notificationLabel = null
    ): array {
        $name = $notificationLabel ?: 'Notification';
        $changes = [];

        $simple = [
            'subject' => 'subject',
        ];
        foreach ($simple as $attr => $word) {
            $old = $franchiseTranslation->getAttribute($attr);
            $new = $globalTranslation->getAttribute($attr);
            if (!$this->stringDiffers($old, $new)) {
                continue;
            }
            $changes[] = $this->makeChange(
                self::GROUP . " — {$name} {$word} changed",
                $old,
                $new
            );
        }

        $oldMessage = $this->stripHtml($franchiseTranslation->getAttribute('message'));
        $newMessage = $this->stripHtml($globalTranslation->getAttribute('message'));
        if ($this->stringDiffers($oldMessage, $newMessage)) {
            $changes[] = $this->makeChange(
                self::GROUP . " — {$name} message changed",
                $oldMessage,
                $newMessage
            );
        }

        return $changes;
    }

    /**
     * Convert an HTML body to readable plain text. Block tags become line
     * breaks and `<br>` becomes a newline; everything else is stripped while
     * placeholders like {all_fields} are preserved verbatim.
     */
    private function stripHtml(mixed $html): string
    {
        if ($html === null) {
            return '';
        }

        $text = (string) $html;
        $text = preg_replace('/<\s*br\s*\/?\s*>/i', "\n", $text) ?? $text;
        $text = preg_replace('/<\/(p|div|li|h[1-6]|tr)[^>]*>/i', "\n", $text) ?? $text;
        $text = strip_tags($text);
        $text = html_entity_decode($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $text = preg_replace("/[ \t]+\n/", "\n", $text) ?? $text;
        $text = preg_replace("/\n{3,}/", "\n\n", $text) ?? $text;

        return trim($text);
    }

    private function stringDiffers(mixed $a, mixed $b): bool
    {
        if ($a === null && $b === null) {
            return false;
        }
        return (string) $a !== (string) $b;
    }

    private function makeChange(string $label, mixed $old, mixed $new): array
    {
        return [
            'field' => $label,
            'label' => $label,
            'old' => $old,
            'new' => $new,
            'changed' => true,
            'type' => 'text',
        ];
    }

    protected function includedFields(): array
    {
        return [];
    }

    protected function fieldLabels(): array
    {
        return [];
    }
}
