<?php

namespace KupShop\GraphQLBundle\ApiShared\Types\Section;

use KupShop\GraphQLBundle\ApiAdmin\Annotation\Module;
use KupShop\GraphQLBundle\ApiShared\ApiUtil;
use KupShop\GraphQLBundle\ApiShared\Types\Content\EditableContent;
use KupShop\GraphQLBundle\ApiShared\Types\Enums\SectionBehaviourEnum;
use KupShop\GraphQLBundle\ApiShared\Types\Enums\SectionVisibilityEnum;
use KupShop\GraphQLBundle\ApiShared\Types\Product\Photo;
use KupShop\GraphQLBundle\ApiShared\Types\Seo;
use KupShop\KupShopBundle\Util\StringUtil;
use Symfony\Component\Routing\RouterInterface;
use TheCodingMachine\GraphQLite\Annotations\Field;
use TheCodingMachine\GraphQLite\Annotations\Type;

/**
 * @Type()
 */
class Section
{
    protected \KupShop\CatalogBundle\Entity\Section $section;
    private ?\Closure $filter;

    public function __construct(\KupShop\CatalogBundle\Entity\Section $section, ?\Closure $filter = null)
    {
        $this->section = $section;
        $this->filter = $filter;
    }

    /**
     * ID.
     *
     * @Field
     */
    public function getId(): int
    {
        return $this->section->getId();
    }

    /**
     * Název.
     *
     * @Field
     */
    public function getName(): string
    {
        return $this->section->getName();
    }

    /**
     * Krátký název.
     *
     * @Field
     */
    public function getNameShort(): string
    {
        return $this->section->getNameShort();
    }

    #[Field(description: 'Anotace.')]
    #[Module(\Modules::PRODUCTS_SECTIONS, \Modules::SUB_ANNOTATION)]
    public function getAnnotation(): ?string
    {
        return $this->section->getAnnotation();
    }

    #[Field(description: 'Zobrazovat produkty z podsekcí.')]
    public function getBehaviour(): SectionBehaviourEnum
    {
        return SectionBehaviourEnum::from($this->section->getBehaviour());
    }

    #[Field(description: 'Zobrazovat ve vyhledávíní.')]
    public function getShowInSearch(): ?bool
    {
        return $this->section->getShowInSearch() === 'Y';
    }

    /**
     * Viditelná.
     *
     * @Field
     */
    public function getVisible(): bool
    {
        return $this->section->isVisible();
    }

    #[Field(description: 'Viditelnost.')]
    public function getVisibility(): SectionVisibilityEnum
    {
        return SectionVisibilityEnum::from($this->section->getFigure());
    }

    /**
     * URL adresa.
     *
     * @Field
     */
    public function getUrl(): string
    {
        $url = $this->section->getUrl();
        if (StringUtil::isAbsoluteUrl($url)) {
            return $url;
        }

        return path('page_not_found', ['path' => $url], RouterInterface::ABSOLUTE_URL);
    }

    /**
     * Obrázek.
     *
     * @Field
     */
    public function getPhoto(): ?Photo
    {
        if ($photo = $this->section->getPhoto()) {
            return new Photo($photo);
        }

        return null;
    }

    /**
     * Sekce má nebo nemá podsekce.
     *
     * @Field
     */
    public function getHasChildren(): bool
    {
        $sections = $this->section->getChildren();
        if ($this->filter) {
            $sections = call_user_func($this->filter, $sections);

            return !empty($sections);
        }

        return !$sections->isEmpty();
    }

    /**
     * Sekce je virtuální.
     *
     * @Field
     */
    public function getIsVirtual(): bool
    {
        return $this->section->isVirtual();
    }

    /**
     * Nadřazená sekce.
     *
     * @Field()
     */
    public function getParent(): ?Section
    {
        return $this->section->getParent() ? new self($this->section->getParent()) : null;
    }

    /**
     * Nadřazené sekce.
     *
     * @Field()
     *
     * @return Section[]
     */
    public function getParents(): array
    {
        return ApiUtil::wrapItems($this->section->getParents(), Section::class);
    }

    /**
     * Podsekce.
     *
     * @Field()
     *
     * @return Section[]
     */
    public function getChildren(): array
    {
        $result = [];

        $sections = $this->section->getChildren();
        if ($this->filter) {
            $sections = call_user_func($this->filter, $sections);
        }

        foreach ($sections as $section) {
            $result[] = new Section($section, $this->filter);
        }

        return $result;
    }

    #[Field(description: 'Popis.', prefetchMethod: 'prefetchSectionsBlocks')]
    public function getDescription(array $data): EditableContent
    {
        return new EditableContent(
            $this->getBlockId(),
            $data[$this->getBlockId()] ?? [],
            'sections',
            $this->section->getId(),
        );
    }

    #[Field(description: 'SEO.')]
    public function getSeo(): Seo
    {
        return new Seo(
            [
                'title' => $this->section->getMetaTitle(),
                'description' => $this->section->getMetaDescription(),
                'keywords' => $this->section->getMetaKeywords(),
            ]
        );
    }

    public function prefetchSectionsBlocks(array $sections): array
    {
        return ApiUtil::fetchBlocksByRootIds(
            array_filter(array_map(fn (Section $section) => $section->getBlockId(), $sections))
        );
    }

    public function getBlockId(): ?int
    {
        return $this->section->getIdBlock();
    }
}
