<?php

namespace App\Shared\EventSubscriber;

use App\Shared\Util\PersianText;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * ارقام فارسی/عربی را در بدنهٔ JSON درخواست‌های API به لاتین ترجمه می‌کند.
 *
 * پنل ادمین ورودی‌ها را در مبدأ نرمال می‌کند، ولی `nobat724_front` و
 * `clinic-pro-tauri` هم همین API را صدا می‌زنند؛ این لایه تضمین می‌کند هیچ
 * کلاینتی نتواند رقم فارسی وارد دیتابیس کند.
 *
 * فقط ترجمهٔ رقم انجام می‌شود — کاراکتر غیرعددی حذف نمی‌شود چون شبا حرف `IR`
 * دارد و تلفن ثابت خط تیره.
 */
class NumericFieldNormalizerSubscriber implements EventSubscriberInterface
{
    /** کلیدهایی که مقدارشان عددی است و باید نرمال شوند. */
    private const NUMERIC_KEYS = [
        'mobile', 'mobile_number', 'telephone', 'phone', 'notification_mobile',
        'national_code', 'postal_code',
        'card_number', 'account_number', 'sheba', 'shaba', 'iban',
        'price_rials', 'amount_rials', 'amount', 'free_visit_price_rials',
        'insurance_price_rials', 'patient_share_rials', 'visit_price_rials',
        'duration_minutes', 'duration', 'commission_percent', 'coverage',
        'coverage_percent', 'franchise', 'franchise_percent', 'ceiling', 'tax_percent',
        'base_insurance_discount_percent', 'supplementary_discount_percent',
    ];

    public static function getSubscribedEvents(): array
    {
        return [KernelEvents::REQUEST => ['onKernelRequest', 8]];
    }

    public function onKernelRequest(RequestEvent $event): void
    {
        $request = $event->getRequest();

        if (!str_starts_with($request->getPathInfo(), '/api/v1/')) {
            return;
        }
        if (!in_array($request->getMethod(), ['POST', 'PUT', 'PATCH'], true)) {
            return;
        }
        if (!str_contains((string) $request->headers->get('Content-Type'), 'json')) {
            return;
        }

        $content = $request->getContent();
        if ($content === '') {
            return;
        }

        $data = json_decode($content, true);
        if (!is_array($data)) {
            return;
        }

        $normalized = $this->normalizeTree($data);
        if ($normalized === $data) {
            return;
        }

        $request->initialize(
            $request->query->all(),
            $request->request->all(),
            $request->attributes->all(),
            $request->cookies->all(),
            $request->files->all(),
            $request->server->all(),
            json_encode($normalized, JSON_UNESCAPED_UNICODE),
        );
    }

    private function normalizeTree(array $data): array
    {
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $data[$key] = $this->normalizeTree($value);
                continue;
            }
            if (is_string($value) && in_array((string) $key, self::NUMERIC_KEYS, true)) {
                $data[$key] = PersianText::digits($value);
            }
        }

        return $data;
    }
}
