<?php
declare( strict_types=1 );

namespace BeyondSEO\Domain\Integrations\WordPress\Seo\Entities\WebPages\Content\Elements\MetaTags;

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

use BeyondSEO\Domain\Integrations\WordPress\Common\Entities\Accounts\WPAccount;
use BeyondSEO\Domain\Integrations\WordPress\Common\Entities\WPVariables;
use BeyondSEO\Domain\Integrations\WordPress\Common\Repo\InternalDB\Accounts\Legacy\InternalDBWPLegacyAccount;
use BeyondSEO\Domain\Integrations\WordPress\Seo\Entities\WebPages\WPWebPage;
use BeyondSEO\Domain\Integrations\WordPress\Seo\Entities\Websites\WPWebsite;
use BeyondSEO\Domain\Integrations\WordPress\Seo\Repo\InternalDB\WebPages\InternalDBWPWebPage;
use BeyondSEO\Domain\Integrations\WordPress\Seo\Repo\InternalDB\Websites\InternalDBWPWebsite;
use BeyondSEODeps\DDD\Domain\Base\Entities\Entity;
use BeyondSEODeps\DDD\Domain\Base\Entities\LazyLoad\LazyLoad;
use BeyondSEODeps\DDD\Domain\Base\Entities\LazyLoad\LazyLoadRepo;
use BeyondSEODeps\DDD\Infrastructure\Validation\Constraints\Choice;

/**
 * Class WPWebPageMetaTag
 */
class WPWebPageMetaTag extends Entity {

	public const TAG_TYPE_TITLE = 'title';
	public const TAG_TYPE_SOCIAL_TITLE = 'social_title';
	public const TAG_TYPE_DESCRIPTION = 'description';
	public const TAG_TYPE_SOCIAL_DESCRIPTION = 'social_description';
	public const TAG_TYPE_KEYWORDS = 'keywords';

	/** @var int|null The ID of the meta-tag */
	public ?int $id = null;

    /** @var int The ID of the post that the meta-tag is for */
    public int $postId;

    /** @var WPWebPage|null The post that the meta-tag is for */
    #[LazyLoad(repoType: LazyLoadRepo::INTERNAL_DB, repoClass: InternalDBWPWebPage::class)]
    public ?WPWebPage $post = null;

	/** @var string The type of the meta-tag */
	#[Choice(choices: [
        self::TAG_TYPE_TITLE,
        self::TAG_TYPE_SOCIAL_TITLE,
        self::TAG_TYPE_DESCRIPTION,
        self::TAG_TYPE_SOCIAL_DESCRIPTION,
        self::TAG_TYPE_KEYWORDS,
    ])]
	public string $type;

	/** @var string The content of the meta-tag */
	public string $content;

	/** @var string|null The template of the meta-tag */
	public ?string $template;

	/** @var bool Whether the meta-tag should be auto-generated */
	public bool $autoGenerated = false;

	/** @var WPVariables|null The variables that can be used in the meta-tag */
	public ?WPVariables $variables = null;

	/** @var string|null The unique key of the meta-tag */
	public ?string $uniqueKey = null;

    /** @var WPWebsite|null The site that the meta-tag is for */
    #[LazyLoad(repoType: LazyLoadRepo::INTERNAL_DB, repoClass: InternalDBWPWebsite::class)]
    public ?WPWebsite $site = null;

    /** @var int|null The ID of the WordPress user that the meta-tag is for */
    public ?int $userId = null;

    /** @var WPAccount|null The WordPress user that the meta-tag is for */
    #[LazyLoad(repoType: LazyLoadRepo::INTERNAL_DB, repoClass: InternalDBWPLegacyAccount::class)]
    public ?WPAccount $user = null;

	/**
	 * WPWebPageMetaTag constructor.
	 */
	public function __construct(
		int $postId = 0,
		string $type = self::TAG_TYPE_TITLE,
		?string $content = '',
		?string $template = null,
		string|bool $autoGenerated = false,
		?WPVariables $variables = null
	) {
		$this->postId = $postId;
		$this->type = $type;
		$this->content = $content ?? '';
		$this->template = $template;
		$this->autoGenerated = (bool)$autoGenerated;
		$this->variables = $variables ?? new WPVariables();
		$this->formatTemplate();
		parent::__construct();
	}

	/**
	 * Format the template based on the variables
	 * @return string
	 */
	public function formatTemplate(): string
	{
		$this->template = '';
		if(!empty($this->variables)) {
            foreach ($this->variables->getAvailableVariables() as $variable) {
                $this->template .= ' ' . strtolower('{' . $variable->getKey() . '}');
            }
		}
		$this->template = trim($this->template);

		$this->uniqueKey = $this->uniqueKey();
		return $this->template;
	}

	/**
	 * Get the lower case type of the meta-tag
	 * @return string
	 */
	public function getLowerType(): string
	{
		return strtolower($this->type);
	}

	/**
	 * @return string
	 */
	public function uniqueKey(): string
	{
		$tagUniqueKey = $this->postId ? md5(($this->postId . $this->type)) : '';
		if($this->variables && $this->variables->count()) {
			$tagUniqueKey = $this->variables->uniqueKey();
		}
		if(!empty($tagUniqueKey)) {
			$tagUniqueKey = '_' . $tagUniqueKey;
		}
		return strtolower($this->postId . '_' . $this->type . $tagUniqueKey);
	}
}