<?php
/**
 * SEO Handler Context DTO
 *
 * Data Transfer Object that holds all shared dependencies for the SEO
 * Intelligence handler classes. Passed to each handler constructor so
 * all handlers share the same repository and service instances that were
 * initialised once by the facade.
 *
 * @package Wisewand
 * @since 2.8.2
 * @license GPL-2.0-or-later
 */

namespace Wisewand\Admin\SEO;

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

use Wisewand\Utils\Options;
use Wisewand\Utils\DataForSEO_Universal;
use Wisewand\Utils\Rate_Limiter;
use Wisewand\Logging\Logger;

/**
 * Shared dependency container for SEO handler classes
 *
 * Holds all repositories, service clients, and configuration values that
 * each domain handler needs. Using a DTO keeps handler constructors clean
 * and makes dependencies explicit.
 *
 * @package Wisewand
 * @since 2.8.2
 */
class SEO_Handler_Context {

	/**
	 * Plugin options wrapper
	 *
	 * @since 2.8.2
	 * @var Options
	 */
	public $options;

	/**
	 * Plugin logger
	 *
	 * @since 2.8.2
	 * @var Logger
	 */
	public $logger;

	/**
	 * DataForSEO API client (may be null if not configured)
	 *
	 * @since 2.8.2
	 * @var DataForSEO_Universal|null
	 */
	public $dataforseo_client;

	/**
	 * SEO analysis repository
	 *
	 * @since 2.8.2
	 * @var \Wisewand\Repositories\SEO_Analysis_Repository
	 */
	public $seo_repository;

	/**
	 * Competitor analysis repository
	 *
	 * @since 2.8.2
	 * @var \Wisewand\Repositories\Competitor_Repository
	 */
	public $competitor_repository;

	/**
	 * Saved keywords repository
	 *
	 * @since 2.8.2
	 * @var \Wisewand\Repositories\Keyword_Repository
	 */
	public $keyword_repository;

	/**
	 * Editorial calendar repository
	 *
	 * @since 2.8.2
	 * @var \Wisewand\Repositories\Calendar_Repository
	 */
	public $calendar_repository;

	/**
	 * Rate limiter for API calls
	 *
	 * @since 2.8.6
	 * @var Rate_Limiter
	 */
	public $rate_limiter;

	/**
	 * Normalised site domain (e.g. "example.com")
	 *
	 * @since 2.8.2
	 * @var string
	 */
	public $domain;

	// =========================================================================
	// LAZY SERVICE GETTERS (shared across handlers)
	// =========================================================================

	/**
	 * Cached Saved_Keywords_Manager instance
	 *
	 * @since 2.8.7
	 * @var \Wisewand\Utils\Saved_Keywords_Manager|null
	 */
	private $saved_keywords_manager = null;

	/**
	 * Cached Keyword_Cluster_Manager instance
	 *
	 * @since 2.8.7
	 * @var \Wisewand\Utils\Keyword_Cluster_Manager|null
	 */
	private $cluster_manager = null;

	/**
	 * Cached Keyword_Deduplication_Engine instance
	 *
	 * @since 2.8.7
	 * @var \Wisewand\Utils\Keyword_Deduplication_Engine|null
	 */
	private $deduplication_engine = null;

	/**
	 * Get (or create) the shared Saved_Keywords_Manager instance
	 *
	 * @since 2.8.7
	 *
	 * @return \Wisewand\Utils\Saved_Keywords_Manager
	 */
	public function get_saved_keywords_manager() {
		if ( null === $this->saved_keywords_manager ) {
			if ( ! class_exists( 'Wisewand\\Utils\\Saved_Keywords_Manager' ) ) {
				require_once WISEWAND_PLUGIN_DIR . 'includes/Utils/Saved_Keywords_Manager.php';
			}
			$this->saved_keywords_manager = new \Wisewand\Utils\Saved_Keywords_Manager(
				$this->options,
				$this->logger,
				$this->dataforseo_client,
				$this->keyword_repository,
				$this->calendar_repository
			);
		}
		return $this->saved_keywords_manager;
	}

	/**
	 * Get (or create) the shared Keyword_Cluster_Manager instance
	 *
	 * @since 2.8.7
	 *
	 * @return \Wisewand\Utils\Keyword_Cluster_Manager
	 */
	public function get_cluster_manager() {
		if ( null === $this->cluster_manager ) {
			if ( ! class_exists( 'Wisewand\\Utils\\Keyword_Cluster_Manager' ) ) {
				require_once WISEWAND_PLUGIN_DIR . 'includes/Utils/Keyword_Cluster_Manager.php';
			}
			$this->cluster_manager = new \Wisewand\Utils\Keyword_Cluster_Manager(
				$this->options,
				$this->logger
			);
		}
		return $this->cluster_manager;
	}

	/**
	 * Get (or create) the shared Keyword_Deduplication_Engine instance (default thresholds)
	 *
	 * @since 2.8.7
	 *
	 * @return \Wisewand\Utils\Keyword_Deduplication_Engine
	 */
	public function get_deduplication_engine() {
		if ( null === $this->deduplication_engine ) {
			if ( ! class_exists( 'Wisewand\\Utils\\Keyword_Deduplication_Engine' ) ) {
				require_once WISEWAND_PLUGIN_DIR . 'includes/Utils/Keyword_Deduplication_Engine.php';
			}
			$this->deduplication_engine = new \Wisewand\Utils\Keyword_Deduplication_Engine(
				$this->logger
			);
		}
		return $this->deduplication_engine;
	}

	/**
	 * Create a new context instance
	 *
	 * @since 2.8.2
	 *
	 * @param Options                                          $options              Plugin options wrapper.
	 * @param Logger                                           $logger               Plugin logger.
	 * @param DataForSEO_Universal|null                        $dataforseo_client    DataForSEO API client.
	 * @param \Wisewand\Repositories\SEO_Analysis_Repository  $seo_repository       SEO analysis repository.
	 * @param \Wisewand\Repositories\Competitor_Repository    $competitor_repository Competitor repository.
	 * @param \Wisewand\Repositories\Keyword_Repository       $keyword_repository   Keyword repository.
	 * @param \Wisewand\Repositories\Calendar_Repository      $calendar_repository  Calendar repository.
	 * @param Rate_Limiter                                     $rate_limiter         Rate limiter for API calls.
	 * @param string                                           $domain               Normalised site domain.
	 */
	public function __construct(
		Options $options,
		Logger $logger,
		$dataforseo_client,
		$seo_repository,
		$competitor_repository,
		$keyword_repository,
		$calendar_repository,
		Rate_Limiter $rate_limiter,
		string $domain
	) {
		$this->options              = $options;
		$this->logger               = $logger;
		$this->dataforseo_client    = $dataforseo_client;
		$this->seo_repository       = $seo_repository;
		$this->competitor_repository = $competitor_repository;
		$this->keyword_repository   = $keyword_repository;
		$this->calendar_repository  = $calendar_repository;
		$this->rate_limiter         = $rate_limiter;
		$this->domain               = $domain;
	}
}
