<?php

namespace AutoAdmin\Bundle\Seo\Sitemap;

use AutoAdmin\Bundle\Content\Configuration\ConfigManager;
use AutoAdmin\Bundle\Content\Model\CreatedAtInterface;
use AutoAdmin\Bundle\Content\Model\TranslatableInterface;
use AutoAdmin\Bundle\Content\Model\UpdatedAtInterface;
use AutoAdmin\Bundle\Content\Repository\AbstractContentRepository;
use AutoAdmin\Bundle\Content\Routing\ContentRouter;
use AutoAdmin\Bundle\Seo\Model\SeoContentTranslationInterface;
use AutoAdmin\Bundle\Seo\Sitemap\Model\SitemapUrl;
use Doctrine\Persistence\ManagerRegistry;

/**
 * Try to generate sitemap from content entity config only
 */
class ConfigSitemapBuilder implements SitemapBuilderInterface
{
    public function __construct(
        private ConfigManager $configManager,
        private ManagerRegistry $doctrine,
        private ContentRouter $contentRouter,
    ) {
    }

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

        $sitemapConfig = $this->configManager->getSitemap();

        foreach ($sitemapConfig['config'] as $sectionSlug => $config) {
            if (!in_array($sectionSlug, $sections)) {
                $sections[] = $sectionSlug;
            }
        }

        foreach ($sitemapConfig['routes'] as $sectionSlug => $routeConfigs) {
            if (!in_array($sectionSlug, $sections)) {
                $sections[] = $sectionSlug;
            }
        }

        return $sections;
    }

    public function getUrls(): array
    {
        $safeUrlGen = ($cfg = $this->configManager->get('sitemap')) && $cfg['safe_url_generation'] === true;

        $urls = [];

        // after builders, generate content sitemap from config
        $sitemapConfig = $this->configManager->getSitemap();
        foreach ($sitemapConfig['config'] as $sectionSlug => $sectionConfig) {
            foreach ($sectionConfig['contents'] as $contentSlug) {
                $contentCfg = $this->configManager->getContentConfigForSlug($contentSlug);
                $contentClass = $contentCfg['class'];
                $contentRefl = new \ReflectionClass($contentClass);

                $repo = $this->doctrine->getRepository($contentClass);
                $contents = $this->resolveContent($repo, $contentRefl);
                $urlAction = !empty($contentCfg['action_chain']) ? 'chain' : 'view';
                $changeFreq = $sectionConfig['changefreq'];

                foreach ($contents as $content) {
                    $date = new \DateTime();
                    if ($content instanceof CreatedAtInterface) {
                        $date = $content->getCreatedAt();
                    } elseif ($content instanceof UpdatedAtInterface) {
                        $date = $content->getUpdatedAt();
                    }

                    if ($content instanceof TranslatableInterface
                        && ($tr = $content->getCurrentTranslation())
                        && $tr instanceof SeoContentTranslationInterface
                        && $tr->getSeoMetadata()?->isHideFromSitemap() === true
                    ) {
                        continue;
                    }

                    if ($safeUrlGen) {
                        $url = $this->contentRouter->generateSafe($content, $urlAction);
                    } else {
                        $url = $this->contentRouter->generate($content, $urlAction);
                    }

                    $sitemapUrl = new SitemapUrl($url, $date, $changeFreq);
                    $sitemapUrl->setSection($sectionSlug);
                    $urls[] = $sitemapUrl;
                }

//                dump($sectionSlug.'>'.$contentSlug . '('.count($contents).')');
            }
        }

        foreach ($sitemapConfig['routes'] as $sectionSlug => $routeConfigs) {
            foreach ($routeConfigs as $routeConfig) {
                $route = $routeConfig['route'];
                list($contentSlug, $action) = explode('_', $route, 2);
                $param = $routeConfig['param'];
                if (!empty($param['slugAdmin'])) {
                    $url = $this->contentRouter->generate($contentSlug, $action, $param ?? []);
                } else {
                    $url = $this->contentRouter->getRouter()->generate($route, $param ?? []);
                }

                $sitemapUrl = new SitemapUrl($url, new \DateTime(), SitemapUrl::DEFAULT_CHANGE_FREQ);
                $sitemapUrl->setSection($sectionSlug);
                $urls[] = $sitemapUrl;
            }
        }

        return $urls;
    }

    /**
     * @param \Doctrine\Persistence\ObjectRepository $repo
     * @param \ReflectionClass $contentRefl
     * @return mixed
     */
    public function resolveContent(\Doctrine\Persistence\ObjectRepository $repo, \ReflectionClass $contentRefl)
    {
        if ($repo instanceof AbstractContentRepository) {
            $qb = $repo->createAutoContentQueryBuilder();
        } else {
            $qb = $repo->createQueryBuilder('_');
        }

        $contents = $qb->getQuery()->getResult();

        return $contents;
    }
}