<?php
declare( strict_types=1 );

namespace BeyondSEO\Domain\Integrations\WordPress\Seo\Repo\InternalDB\WebPages;

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

use BeyondSEO\Domain\Common\Repo\InternalDB\InternalDBEntity;
use BeyondSEO\Domain\Common\Repo\InternalDB\Models\InternalDBMetaTagModel;
use BeyondSEO\Domain\Integrations\WordPress\Common\Entities\WPVariable;
use BeyondSEO\Domain\Integrations\WordPress\Common\Entities\WPVariables;
use BeyondSEO\Domain\Integrations\WordPress\Seo\Entities\WebPages\Content\Elements\MetaTags\WPWebPageMetaTag;
use BeyondSEO\Domain\Integrations\WordPress\Seo\Entities\WebPages\WPWebPage;
use BeyondSEODeps\DDD\Domain\Base\Entities\DefaultObject;
use BeyondSEODeps\DDD\Domain\Base\Entities\Entity;
use BeyondSEODeps\DDD\Domain\Base\Entities\LazyLoad\LazyLoad;
use BeyondSEODeps\DDD\Domain\Base\Repo\DB\Attributes\EntityCache;
use BeyondSEODeps\DDD\Domain\Base\Repo\DB\Doctrine\DoctrineQueryBuilder;
use BeyondSEODeps\DDD\Infrastructure\Cache\Cache;
use BeyondSEODeps\DDD\Infrastructure\Exceptions\BadRequestException;
use BeyondSEODeps\DDD\Infrastructure\Exceptions\InternalErrorException;
use BeyondSEODeps\Doctrine\DBAL\Exception;
use BeyondSEODeps\Doctrine\ORM\Mapping\MappingException;
use Psr\Cache\InvalidArgumentException;
use ReflectionException;

/**
 * Class InternalDBWPWebPageContent
 * @method WPWebPageMetaTag find(DoctrineQueryBuilder|string|int $idOrQueryBuilder, bool $useEntityRegistryCache = false, ?InternalDBMetaTagModel &$loadedOrmInstance = null, bool $deferredCaching = false, array $initiatorClasses = [] )
 * @property InternalDBMetaTagModel $ormInstance
 */
#[EntityCache(useExtendedRegistryCache: false, ttl: 300, cacheGroup: Cache::CACHE_GROUP_PHPFILES, cacheScopes: [])]
class InternalDBWPWebPageContent extends InternalDBEntity {
	public const BASE_ENTITY_CLASS = WPWebPageMetaTag::class;
	public const BASE_ORM_MODEL = InternalDBMetaTagModel::class;

    /**
     * @param WPWebPage $initiatingEntity
     * @param LazyLoad $lazyloadAttributeInstance
     *
     * @return WPWebPageMetaTag|null
     * @throws BadRequestException
     * @throws Exception
     * @throws InternalErrorException
     * @throws InvalidArgumentException
     * @throws MappingException
     * @throws ReflectionException
     */
    public function lazyload(
        DefaultObject &$initiatingEntity,
        LazyLoad &$lazyloadAttributeInstance
    ): ?WPWebPageMetaTag {
        $queryBuilder = self::createQueryBuilder();
        $queryBuilder
            ->where('metaTags.post_id = :post_id')
            ->setParameter('post_id', $initiatingEntity->id);

        return $this->find($queryBuilder, $lazyloadAttributeInstance->useCache);
        //return $this->mapToEntity($lazyloadAttributeInstance->useCache);
    }

	/**
	 * Applies update/delete restrictions based on Auth::instance()->getAccount
	 *
	 * @param DoctrineQueryBuilder $queryBuilder
	 *
	 * @return bool
	 * @noinspection PhpMissingParentCallCommonInspection*/
	public static function applyUpdateRightsQuery(DoctrineQueryBuilder &$queryBuilder): bool
	{
		return false;
	}

	/**
	 * @param bool $useEntityRegistryCache
	 *
	 * @return WPWebPageMetaTag
	 * @throws ReflectionException
	 */
	public function mapToEntity( bool $useEntityRegistryCache = false ): WPWebPageMetaTag
	{
		/** @var WPWebPageMetaTag $entity */
		$entity = parent::mapToEntity( $useEntityRegistryCache );

		$entity->id = $this->ormInstance->id;
		$entity->postId = $this->ormInstance->post_id;
		$entity->type = $this->ormInstance->type ?? WPWebPageMetaTag::TAG_TYPE_TITLE;
		$entity->content = $this->ormInstance->content;
		$entity->template = $this->ormInstance->template;
		$entity->autoGenerated = $this->ormInstance->auto_generated;
		if($this->ormInstance->variables) {
			$dbVariables = json_decode($this->ormInstance->variables);
			$variables = new WPVariables();
			if($dbVariables && !empty($dbVariables->elements)) {
				foreach($dbVariables->elements as $dbVariable) {
					$variable = new WPVariable($dbVariable->post_id, $dbVariable->key, $dbVariable->value);
					$variables->addVariable($variable);
				}
			}
			$entity->variables = $variables;
		}
		$entity->uniqueKey = $this->ormInstance->unique_key;

		return $entity;
	}

	/**
	 * @param Entity $entity
	 *
	 * @return bool
	 * @throws ReflectionException
	 */
	protected function mapToRepository(Entity &$entity): bool
	{
        /** @var WPWebPageMetaTag $entity */
		parent::mapToRepository($entity);
		$ormInstance = $this->ormInstance;

		if (isset($entity->id)) {
			$ormInstance->id = (int)$entity->id;
		}

		if (isset($entity->postId)) {
			$ormInstance->post_id = (int)$entity->postId;
		}

		$ormInstance->type = $entity->type ?? WPWebPageMetaTag::TAG_TYPE_TITLE;
		$ormInstance->content = $entity->content ?? '';
		$ormInstance->template = $entity->formatTemplate() ?? '';
		$ormInstance->auto_generated = $entity->autoGenerated ?? false;

		if (isset($entity->variables)) {
			$ormInstance->variables = json_encode($entity->variables);
		}

		$ormInstance->unique_key = $entity->uniqueKey();
		$this->ormInstance = $ormInstance;

		return true;
	}

    /**
     * Retrieves a WPWebPageMetaTag entity by its ID.
     *
     * @param int $postId The ID of the post to retrieve.
     * @param string $type The type of the meta tag to retrieve.
     * @param bool $useCache
     * @return mixed The WPWebPageMetaTag entity.
     * @throws BadRequestException
     * @throws InternalErrorException
     * @throws InvalidArgumentException
     * @throws ReflectionException
     * @throws Exception
     * @throws MappingException
     */
	public function getMetaTagByTypeAndId(int $postId, string $type, bool $useCache = false): WPWebPageMetaTag {
        $queryBuilder = self::createQueryBuilder();
		$queryBuilder
			->select('p')
			->from(InternalDBMetaTagModel::class, 'p')
			->where('p.post_id = :postId')
			->andWhere('p.type = :type')
			->setParameter('postId', $postId)
			->setParameter('type', $type);
        return $this->find($queryBuilder, $useCache);
	}
}