<?php

declare(strict_types=1);

namespace App\Domain\Meta\ValueObject;

readonly class MetaData
{
    public function __construct(
        public ?string $title = null,
        public ?string $description = null,
        public ?array $keywords = null,
        public ?string $ogTitle = null,
        public ?string $ogDescription = null,
        public ?string $ogImage = null,
        public ?string $ogType = null,
        public ?string $twitterCard = null,
        public ?string $twitterSite = null,
        public ?string $canonical = null,
        public ?array $customMeta = null,
    ) {}

    public static function fromArray(array $data): self
    {
        return new self(
            title: $data['title'] ?? null,
            description: $data['description'] ?? null,
            keywords: isset($data['keywords']) ? (is_array($data['keywords']) ? $data['keywords'] : explode(',', $data['keywords'])) : null,
            ogTitle: $data['og_title'] ?? null,
            ogDescription: $data['og_description'] ?? null,
            ogImage: $data['og_image'] ?? null,
            ogType: $data['og_type'] ?? null,
            twitterCard: $data['twitter_card'] ?? null,
            twitterSite: $data['twitter_site'] ?? null,
            canonical: $data['canonical'] ?? null,
            customMeta: isset($data['custom_meta']) ? (is_array($data['custom_meta']) ? $data['custom_meta'] : json_decode($data['custom_meta'], true)) : null,
        );
    }

    public function merge(MetaData $other): self
    {
        return new self(
            title: $other->title ?? $this->title,
            description: $other->description ?? $this->description,
            keywords: $other->keywords ?? $this->keywords,
            ogTitle: $other->ogTitle ?? $this->ogTitle,
            ogDescription: $other->ogDescription ?? $this->ogDescription,
            ogImage: $other->ogImage ?? $this->ogImage,
            ogType: $other->ogType ?? $this->ogType,
            twitterCard: $other->twitterCard ?? $this->twitterCard,
            twitterSite: $other->twitterSite ?? $this->twitterSite,
            canonical: $other->canonical ?? $this->canonical,
            customMeta: array_merge($this->customMeta ?? [], $other->customMeta ?? []),
        );
    }

    public function toArray(): array
    {
        return array_filter([
            'title' => $this->title,
            'description' => $this->description,
            'keywords' => $this->keywords ? implode(',', $this->keywords) : null,
            'og_title' => $this->ogTitle,
            'og_description' => $this->ogDescription,
            'og_image' => $this->ogImage,
            'og_type' => $this->ogType,
            'twitter_card' => $this->twitterCard,
            'twitter_site' => $this->twitterSite,
            'canonical' => $this->canonical,
            'custom_meta' => $this->customMeta ? json_encode($this->customMeta) : null,
        ], fn($value) => $value !== null);
    }

    public function isEmpty(): bool
    {
        return $this->title === null
            && $this->description === null
            && empty($this->keywords)
            && $this->ogTitle === null
            && $this->ogDescription === null
            && $this->ogImage === null
            && empty($this->customMeta);
    }

    public function render(): string
    {
        if ($this->isEmpty()) {
            return '';
        }

        $html = [];

        // Basic Meta Tags
        if ($this->title) {
            $html[] = '<title>' . htmlspecialchars($this->title, ENT_QUOTES, 'UTF-8') . '</title>';
        }

        if ($this->description) {
            $html[] = '<meta name="description" content="' . htmlspecialchars($this->description, ENT_QUOTES, 'UTF-8') . '">';
        }

        if ($this->keywords) {
            $html[] = '<meta name="keywords" content="' . htmlspecialchars(implode(', ', $this->keywords), ENT_QUOTES, 'UTF-8') . '">';
        }

        if ($this->canonical) {
            $html[] = '<link rel="canonical" href="' . htmlspecialchars($this->canonical, ENT_QUOTES, 'UTF-8') . '">';
        }

        // Open Graph
        if ($this->ogTitle) {
            $html[] = '<meta property="og:title" content="' . htmlspecialchars($this->ogTitle, ENT_QUOTES, 'UTF-8') . '">';
        }

        if ($this->ogDescription) {
            $html[] = '<meta property="og:description" content="' . htmlspecialchars($this->ogDescription, ENT_QUOTES, 'UTF-8') . '">';
        }

        if ($this->ogImage) {
            $html[] = '<meta property="og:image" content="' . htmlspecialchars($this->ogImage, ENT_QUOTES, 'UTF-8') . '">';
        }

        if ($this->ogType) {
            $html[] = '<meta property="og:type" content="' . htmlspecialchars($this->ogType, ENT_QUOTES, 'UTF-8') . '">';
        }

        // Twitter
        if ($this->twitterCard) {
            $html[] = '<meta name="twitter:card" content="' . htmlspecialchars($this->twitterCard, ENT_QUOTES, 'UTF-8') . '">';
        }

        if ($this->twitterSite) {
            $html[] = '<meta name="twitter:site" content="' . htmlspecialchars($this->twitterSite, ENT_QUOTES, 'UTF-8') . '">';
        }

        // Custom Meta
        if ($this->customMeta) {
            foreach ($this->customMeta as $name => $content) {
                if (str_starts_with($name, 'og:')) {
                    $html[] = '<meta property="' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '" content="' . htmlspecialchars($content, ENT_QUOTES, 'UTF-8') . '">';
                } else {
                    $html[] = '<meta name="' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '" content="' . htmlspecialchars($content, ENT_QUOTES, 'UTF-8') . '">';
                }
            }
        }

        return implode("\n", $html);
    }
}
