<?php

namespace AutoAdmin\Bundle\Seo\Sitemap;

use AutoAdmin\Bundle\Seo\Sitemap\Model\SitemapUrl;
use Exception;
use Thepixeldeveloper\Sitemap\Extensions\Image;
use Thepixeldeveloper\Sitemap\Url;
use Thepixeldeveloper\Sitemap\Urlset;
use Traversable;

class SitemapManager
{
    /**
     * @var array<SitemapBuilderInterface>
     */
    private array $builders;

    public function __construct(
        Traversable $builders
    )
    {
        // builders tagged with "aa_seo.sitemap_builder"
        $this->builders = array_map([$this, 'addBuilder'], iterator_to_array($builders));
    }

    public function getSections(): array
    {
        $sections = [];

        foreach ($this->builders as $builder) {
            foreach ($builder->getSections() as $section) {
                if (!in_array($section, $sections)) {
                    $sections[] = $section;
                }
            }
        }

        return $sections;
    }

    /**
     * @throws Exception
     */
    public function build($host, $section = null): array
    {
        $urlSets = [];

        /** @var SitemapBuilderInterface $builder */
        foreach ($this->builders as $builder) {
            if ($section !== null && !in_array($section, $builder->getSections())) {
                continue;
            }
            $urls = $builder->getUrls($section);
            $urlAdded = [];

            /** @var SitemapUrl $url */
            foreach ($urls as $sitemapUrl) {
                if (in_array($sitemapUrl->getUrl(), $urlAdded)) {
                    continue;
                }

                $urlAdded[] = $sitemapUrl->getUrl();

                if (!$sitemapUrl instanceof SitemapUrl) {
                    throw new Exception(
                        'Sitemap urls must be represented by ' . SitemapUrl::class . '. "' . gettype($url) . '" given.'
                    );
                }

                $url = new Url($host . $sitemapUrl->getUrl());
                if ($sitemapUrl->getLastModification()) {
                    $url->setLastMod($sitemapUrl->getLastModification());
                }
                if ($sitemapUrl->getChangeFrequency()) {
                    $url->setChangeFreq($sitemapUrl->getChangeFrequency());
                }
                if ($sitemapUrl->getPriority()) {
                    $url->setPriority($sitemapUrl->getPriority());
                }

                if (!empty($images = $sitemapUrl->getImages())) {
                    foreach ($images as $image) {
                        if (is_string($image)) {
                            $url->addExtension(new Image($image));
                        } else {
                            // permit to use image object (\Thepixeldeveloper\Sitemap\Extensions\Image)
                            $url->addExtension($image);
                        }
                    }
                }

                if (!isset($urlSets[$section])) {
                    $urlSets[$section] = new Urlset();
                }
                $urlSets[$section]->add($url);
            }
        }

        return $urlSets;
    }

    protected function addBuilder(SitemapBuilderInterface $builder): SitemapBuilderInterface
    {
        return $builder;
    }
}
