<?php
/**
 * Copyright © Simplyin. All rights reserved.
 */
declare(strict_types=1);

namespace Simplyin\Payment\Block\Adminhtml\System\Config\Field;

use Magento\Backend\Block\Template\Context;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;
use Magento\Framework\Encryption\EncryptorInterface;

/**
 * Renders the saved API key as a length-proportional mask with only the last characters revealed
 * (e.g. ••••••••••h8), matching the WooCommerce plugin's preview intent.
 *
 * Only the revealed tail reaches the page source — the rest of the key is never emitted. The stored
 * value stays encrypted; the mask is a display placeholder recognised on save by
 * {@see \Simplyin\Payment\Model\Config\Backend\ApiKeyEncrypted} so an untouched field keeps the key.
 */
class ApiKeyMasked extends Field
{
    /** Bullet used to build the mask; a real API key never contains it. */
    public const MASK_CHAR = "\u{2022}";

    /** How many trailing characters of the key are shown in clear. */
    private const REVEAL = 2;

    /**
     * @param Context $context
     * @param EncryptorInterface $encryptor
     * @param array $data
     */
    public function __construct(
        Context $context,
        private readonly EncryptorInterface $encryptor,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }

    /**
     * Render the API key input with the stored key shown as a length-proportional mask.
     *
     * @param AbstractElement $element
     * @return string
     */
    protected function _getElementHtml(AbstractElement $element): string
    {
        $stored = (string)$element->getValue();
        if ($stored !== '') {
            $plain = (string)$this->encryptor->decrypt($stored);
            if ($plain !== '') {
                $element->setValue($this->mask($plain));
            }
        }

        return parent::_getElementHtml($element);
    }

    /**
     * Build a length-proportional mask revealing only the last {@see self::REVEAL} characters.
     *
     * @param string $plain
     * @return string
     */
    private function mask(string $plain): string
    {
        $length = mb_strlen($plain);
        if ($length <= self::REVEAL) {
            return str_repeat(self::MASK_CHAR, $length);
        }

        return str_repeat(self::MASK_CHAR, $length - self::REVEAL) . mb_substr($plain, -self::REVEAL);
    }
}
