<?php

declare(strict_types=1);

namespace App\Framework\View\Table\Formatters;

use App\Framework\View\Table\CellFormatter;

final readonly class MaskedFormatter implements CellFormatter
{
    public function __construct(
        private string $mask = '********',
        private int $visibleChars = 0,
        private bool $showLength = false
    ) {
    }

    public function format(mixed $value): string
    {
        if ($value === null || $value === '') {
            return '';
        }

        $stringValue = (string) $value;

        if ($this->visibleChars > 0) {
            $visiblePart = substr($stringValue, 0, $this->visibleChars);
            $maskedPart = str_repeat('*', max(0, strlen($stringValue) - $this->visibleChars));
            $result = $visiblePart . $maskedPart;
        } else {
            $result = $this->mask;
        }

        if ($this->showLength) {
            $result .= " (Length: " . strlen($stringValue) . ")";
        }

        return htmlspecialchars($result, ENT_QUOTES);
    }

    public static function full(): self
    {
        return new self('********');
    }

    public static function partial(int $visibleChars): self
    {
        return new self('********', $visibleChars);
    }

    public static function withLength(): self
    {
        return new self('********', 0, true);
    }

    public static function email(): CellFormatter
    {
        return new class () implements CellFormatter {
            public function format(mixed $value): string
            {
                if ($value === null || $value === '') {
                    return '';
                }

                $email = (string) $value;
                if (! str_contains($email, '@')) {
                    return '********';
                }

                [$local, $domain] = explode('@', $email, 2);
                $maskedLocal = substr($local, 0, 2) . str_repeat('*', max(0, strlen($local) - 2));

                return htmlspecialchars($maskedLocal . '@' . $domain, ENT_QUOTES);
            }
        };
    }
}
