<?php

namespace App\Services\SEO;

use Illuminate\Support\HtmlString;

class MetaManager
{
    /**
     * @var array Each item is ['name' => ..., 'content' => ..., 'property' => ...]
     */
    protected array $tags = [];

    /**
     * Default base values
     */
    protected array $defaults = [];

    public function __construct(array $initial = [])
    {
        $this->getDefaults();
        $this->setDefaults();
        $this->setMany($initial);
    }

    /**
     * Set the default core meta tags.
     */
    protected function setDefaults(): void
    {
        $this->tags = [
            ['name' => 'title', 'content' => $this->defaults['title']],
            ['name' => 'description', 'content' => $this->defaults['description']],
            ['name' => 'keywords', 'content' => $this->defaults['keywords']],
            ['name' => 'robots', 'content' => 'index, follow'],

            ['property' => 'og:type', 'content' => $this->defaults['type']],
            ['property' => 'og:title', 'content' => $this->defaults['title']],
            ['property' => 'og:description', 'content' => $this->defaults['description']],
            ['property' => 'og:image', 'content' => $this->defaults['image']],
            ['property' => 'og:url', 'content' => $this->defaults['url']],
            ['property' => 'og:site_name', 'content' => getSiteName() ?? ''],

            ['name' => 'twitter:card', 'content' => 'summary_large_image'],
            ['name' => 'twitter:title', 'content' => $this->defaults['title']],
            ['name' => 'twitter:description', 'content' => $this->defaults['description']],
            ['name' => 'twitter:image', 'content' => $this->defaults['image']],
        ];
    }

    /**
     * Load default values from site options if available.
     */
    protected function getDefaults(): void
    {

        $this->defaults = [
            'title' => 'Default Site Title',
            'description' => 'Default site description for SEO and social previews.',
            'keywords' => 'laravel, ecommerce, shop',
            'image' => '/images/og-image.jpg',
            'url' => url()->current(),
            'type' => 'website',
        ];
    }
    /**
     * Add or update a meta tag.
     */
    public function set(string $identifier, string $content, string $type = 'name'): self
    {
        // Remove old entry if exists
        $this->tags = array_filter($this->tags, function ($tag) use ($identifier, $type) {
            return ($tag[$type] ?? null) !== $identifier;
        });

        $this->tags[] = [$type => $identifier, 'content' => $content];
        return $this;
    }

    /**
     * Bulk set many meta tags.
     */
    public function setMany(array $data): self
    {
        foreach ($data as $key => $value) {
            if (!empty($value)) {
                if (str_starts_with($key, 'og:')) {
                    $this->set($key, $value, 'property');
                } elseif (str_starts_with($key, 'twitter:')) {
                    $this->set($key, $value, 'name');
                } else {
                    $this->set($key, $value, 'name');
                }
            }
        }
        return $this;
    }

    /**
     * Remove a meta tag.
     */
    public function remove(string $identifier, string $type = 'name'): self
    {
        $this->tags = array_filter($this->tags, function ($tag) use ($identifier, $type) {
            return ($tag[$type] ?? null) !== $identifier;
        });
        return $this;
    }

    /**
     * Return all tags as array
     */
    public function all(): array
    {
        return array_values($this->tags);
    }

    /**
     * Render all meta tags as HTML
     */
    public function render(): HtmlString
    {
        $html = '';

        foreach ($this->tags as $tag) {
            $attr = isset($tag['name'])
                ? 'name="' . $tag['name'] . '"'
                : 'property="' . $tag['property'] . '"';

            $html .= "<meta {$attr} content=\"" . e($tag['content']) . "\">\n";
        }

        return new HtmlString($html);
    }

    /**
     * Get a single meta value (searches both name & property).
     */
    public function get(string $identifier): ?string
    {
        foreach ($this->tags as $tag) {
            if (($tag['name'] ?? null) === $identifier || ($tag['property'] ?? null) === $identifier) {
                return $tag['content'];
            }
        }
        return null;
    }

    /**
     * Magic to render directly in Blade: {!! seo() !!}
     */
    public function __toString(): string
    {
        return (string) $this->render();
    }
}
