<?php

declare(strict_types=1);

namespace App\Framework\Svg\Elements;

use App\Framework\Core\ValueObjects\Dimensions;
use App\Framework\Svg\ValueObjects\Geometry\Position;
use App\Framework\Svg\ValueObjects\Geometry\Radius;
use App\Framework\Svg\ValueObjects\Styling\Fill;
use App\Framework\Svg\ValueObjects\Styling\Stroke;
use App\Framework\Svg\ValueObjects\Transform\Transform;

/**
 * Value Object representing SVG rect element
 */
final readonly class RectElement implements SvgElement
{
    public function __construct(
        public Position $position,
        public Dimensions $dimensions,
        public Fill $fill,
        public ?Stroke $stroke = null,
        public ?Radius $rx = null,  // Horizontal border radius
        public ?Radius $ry = null,  // Vertical border radius
        public ?Transform $transform = null,
        public ?string $id = null,
        public ?string $class = null
    ) {
    }

    public function getElementType(): string
    {
        return 'rect';
    }

    public function getAttributes(): array
    {
        $attributes = [
            'x' => sprintf('%.2f', $this->position->x),
            'y' => sprintf('%.2f', $this->position->y),
            'width' => (string) $this->dimensions->width,
            'height' => (string) $this->dimensions->height,
            ...$this->fill->toSvgAttributes(),
        ];

        if ($this->stroke !== null && $this->stroke->isVisible()) {
            $attributes = [...$attributes, ...$this->stroke->toSvgAttributes()];
        }

        if ($this->rx !== null) {
            $attributes['rx'] = $this->rx->toSvgValue();
        }

        if ($this->ry !== null) {
            $attributes['ry'] = $this->ry->toSvgValue();
        }

        if ($this->transform !== null && $this->transform->hasTransformations()) {
            $attributes['transform'] = $this->transform->toSvgValue();
        }

        if ($this->id !== null) {
            $attributes['id'] = $this->id;
        }

        if ($this->class !== null) {
            $attributes['class'] = $this->class;
        }

        return $attributes;
    }

    public function hasTransform(): bool
    {
        return $this->transform !== null && $this->transform->hasTransformations();
    }

    public function getTransform(): ?Transform
    {
        return $this->transform;
    }

    public function toSvg(): string
    {
        $attributeString = $this->buildAttributeString($this->getAttributes());

        return "<rect {$attributeString} />";
    }

    private function buildAttributeString(array $attributes): string
    {
        $parts = [];
        foreach ($attributes as $key => $value) {
            $parts[] = sprintf('%s="%s"', $key, htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8'));
        }

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