<?php
namespace Newland\Toubiz\Poi\Neos\Sitemap;

use Neos\ContentRepository\Domain\Model\NodeInterface;
use Neos\Flow\Mvc\Controller\ControllerContext;
use Neos\Neos\Domain\Model\Domain;
use Neos\Neos\Domain\Service\ContentContext;
use Newland\NeosCommon\Sitemap\SitemapProvider;
use Neos\Flow\Annotations as Flow;
use Newland\NeosCommon\Sitemap\SitemapUrl;
use Newland\NeosCommon\Service\ControllerContextFactory;
use Newland\Toubiz\Poi\Neos\Service\ArticleUrlService;
use Newland\Toubiz\Sync\Neos\Domain\Model\Article;
use Newland\Toubiz\Sync\Neos\Domain\Repository\ArticleRepository;

/**
 * @Flow\Scope("singleton")
 */
class PoiDetailSitemapProvider implements SitemapProvider
{

    /**
     * @var ArticleRepository
     * @Flow\Inject()
     */
    protected $articleRepository;

    /**
     * @var ArticleUrlService
     * @Flow\Inject()
     */
    protected $articleUrlService;

    /**
     * @Flow\Inject()
     * @var ControllerContextFactory
     */
    protected $contextFactory;

    /**
     * @param NodeInterface $site
     * @return SitemapUrl[]
     */
    public function getPages(NodeInterface $site): array
    {
        $pages = [];
        $context = $this->contextFactory->initializeFakeControllerContext($site);

        foreach ($this->articleRepository->findAll() as $article) {
            $url = $this->articleToSitemapUrl($article, $context, $this->domain($site));
            if ($url) {
                $pages[] = $url;
            }
        }

        return $pages;
    }

    private function articleToSitemapUrl(Article $article, ControllerContext $context, Domain $domain): ?SitemapUrl
    {
        $url = $this->articleUrlService->generateUrl($article, $context);
        if (!$url) {
            return null;
        }

        $url = $this->prependDomainIfRelative($url, $domain);
        return new SitemapUrl($url);
    }

    private function prependDomainIfRelative(string $url, Domain $domain): string
    {
        if (str_contains($url, 'http')) {
            return $url;
        }

        $domainWithScheme = clone $domain;
        $domainWithScheme->setScheme($domain->getScheme() ?? 'http');
        return ((string) $domainWithScheme) . '/' . ltrim($url, '/');
    }


    /**
     * @param NodeInterface $site
     * @return Domain
     */
    private function domain(NodeInterface $site): Domain
    {
        $contentContext = $site->getContext();
        if (!($contentContext instanceof ContentContext)) {
            return new Domain();
        }

        $domain = $contentContext->getCurrentSite()->getPrimaryDomain();
        return $domain ?? new Domain();
    }
}
