<?php

declare(strict_types=1);

namespace App\Shared\Support;

final class BarcodeSupport
{
    /** @var array<string,string> */
    private const CODE39 = [
        '0' => 'nnnwwnwnn', '1' => 'wnnwnnnnw', '2' => 'nnwwnnnnw', '3' => 'wnwwnnnnn',
        '4' => 'nnnwwnnnw', '5' => 'wnnwwnnnn', '6' => 'nnwwwnnnn', '7' => 'nnnwnnwnw',
        '8' => 'wnnwnnwnn', '9' => 'nnwwnnwnn', 'A' => 'wnnnnwnnw', 'B' => 'nnwnnwnnw',
        'C' => 'wnwnnwnnn', 'D' => 'nnnnwwnnw', 'E' => 'wnnnwwnnn', 'F' => 'nnwnwwnnn',
        'G' => 'nnnnnwwnw', 'H' => 'wnnnnwwnn', 'I' => 'nnwnnwwnn', 'J' => 'nnnnwwwnn',
        'K' => 'wnnnnnnww', 'L' => 'nnwnnnnww', 'M' => 'wnwnnnnwn', 'N' => 'nnnnwnnww',
        'O' => 'wnnnwnnwn', 'P' => 'nnwnwnnwn', 'Q' => 'nnnnnnwww', 'R' => 'wnnnnnwwn',
        'S' => 'nnwnnnwwn', 'T' => 'nnnnwnwwn', 'U' => 'wwnnnnnnw', 'V' => 'nwwnnnnnw',
        'W' => 'wwwnnnnnn', 'X' => 'nwnnwnnnw', 'Y' => 'wwnnwnnnn', 'Z' => 'nwwnwnnnn',
        '-' => 'nwnnnnwnw', '.' => 'wwnnnnwnn', ' ' => 'nwwnnnwnn', '$' => 'nwnwnwnnn',
        '/' => 'nwnwnnnwn', '+' => 'nwnnnwnwn', '%' => 'nnnwnwnwn', '*' => 'nwnnwnwnn',
    ];

    public static function svgCode39(string $value, int $height = 54, int $narrow = 2, int $wide = 6, int $quiet = 10): string
    {
        $encoded = self::normalize($value);
        if ($encoded === '') {
            $encoded = 'NO-CODE';
        }
        $payload = '*' . $encoded . '*';

        $width = $quiet * 2;
        foreach (str_split($payload) as $char) {
            $pattern = self::CODE39[$char] ?? self::CODE39['-'];
            for ($i = 0; $i < strlen($pattern); $i++) {
                $width += ($pattern[$i] === 'w') ? $wide : $narrow;
            }
            $width += $narrow;
        }

        $x = $quiet;
        $bars = [];
        foreach (str_split($payload) as $char) {
            $pattern = self::CODE39[$char] ?? self::CODE39['-'];
            for ($i = 0; $i < strlen($pattern); $i++) {
                $lineWidth = ($pattern[$i] === 'w') ? $wide : $narrow;
                if ($i % 2 === 0) {
                    $bars[] = '<rect x="' . $x . '" y="0" width="' . $lineWidth . '" height="' . $height . '" fill="#111827" />';
                }
                $x += $lineWidth;
            }
            $x += $narrow;
        }

        return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' . $width . ' ' . $height . '" preserveAspectRatio="none" role="img" aria-label="barcode">' . implode('', $bars) . '</svg>';
    }

    private static function normalize(string $value): string
    {
        $value = strtoupper(trim($value));
        if ($value === '') {
            return '';
        }

        $normalized = '';
        foreach (preg_split('//u', $value, -1, PREG_SPLIT_NO_EMPTY) ?: [] as $char) {
            $normalized .= array_key_exists($char, self::CODE39) && $char !== '*' ? $char : '-';
        }
        return trim($normalized, '- ');
    }
}
