<?php

declare(strict_types=1);

namespace App\Framework\View\ValueObjects;

final readonly class HtmlAttributes
{
    /**
     * @param array<string, string|null> $attributes
     */
    public function __construct(
        public array $attributes = []
    ) {
    }

    public static function empty(): self
    {
        return new self([]);
    }

    public static function fromArray(array $attributes): self
    {
        return new self($attributes);
    }

    public function with(string $name, ?string $value = null): self
    {
        return new self([...$this->attributes, $name => $value]);
    }

    public function withFlag(string $name): self
    {
        return $this->with($name, null);
    }

    public function withId(string $id): self
    {
        return $this->with('id', $id);
    }

    public function withClass(string $class): self
    {
        return $this->with('class', $class);
    }

    public function withType(string $type): self
    {
        return $this->with('type', $type);
    }

    public function withName(string $name): self
    {
        return $this->with('name', $name);
    }

    public function withValue(string $value): self
    {
        return $this->with('value', $value);
    }

    public function withAction(string $action): self
    {
        return $this->with('action', $action);
    }

    public function withMethod(string $method): self
    {
        return $this->with('method', $method);
    }

    public function withDisabled(): self
    {
        return $this->withFlag('disabled');
    }

    public function withRequired(): self
    {
        return $this->withFlag('required');
    }

    public function withChecked(): self
    {
        return $this->withFlag('checked');
    }

    public function withReadonly(): self
    {
        return $this->withFlag('readonly');
    }

    public function withSelected(): self
    {
        return $this->withFlag('selected');
    }

    public function get(string $name): ?string
    {
        return $this->attributes[$name] ?? null;
    }

    public function has(string $name): bool
    {
        return array_key_exists($name, $this->attributes);
    }

    public function isFlag(string $name): bool
    {
        return $this->has($name) && $this->get($name) === null;
    }

    public function __toString(): string
    {
        if (empty($this->attributes)) {
            return '';
        }

        $parts = [];
        foreach ($this->attributes as $name => $value) {
            if ($value === null) {
                // Boolean/flag attribute without value
                $parts[] = $name;
            } else {
                // Attribute with value
                $escapedValue = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
                $parts[] = "{$name}=\"{$escapedValue}\"";
            }
        }

        return implode(' ', $parts);
    }
}
