<?php

namespace SugarCalendarBookings\Support\Database\Relations;

// phpcs:ignore WPForms.PHP.UseStatement.UnusedUseStatement
use SugarCalendarBookings\Support\Database\AbstractModel;

/**
 * Belongs to (inverse one-to-one or many) relation class.
 *
 * @since 1.0.0
 */
class BelongsToRelation extends AbstractRelation {

	/**
	 * Foreign key on the parent model.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	protected $foreign_key;

	/**
	 * Owner key on the related model.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	protected $owner_key;

	/**
	 * Constructor.
	 *
	 * @since 1.0.0
	 *
	 * @param AbstractModel               $parent      Parent model instance.
	 * @param class-string<AbstractModel> $related     Related model class.
	 * @param string                      $foreign_key Foreign key.
	 * @param string                      $owner_key   Owner key.
	 */
	public function __construct( $parent, $related, $foreign_key, $owner_key ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.parentFound

		parent::__construct( $parent, $related );

		$this->foreign_key = $foreign_key;
		$this->owner_key   = $owner_key;
	}

	/**
	 * Get the foreign key.
	 *
	 * @since 1.0.0
	 *
	 * @return string
	 */
	public function get_foreign_key() {

		return $this->foreign_key;
	}

	/**
	 * Get the owner key.
	 *
	 * @since 1.0.0
	 *
	 * @return string
	 */
	public function get_owner_key() {

		return $this->owner_key;
	}

	/**
	 * Associate the parent model with a related model.
	 *
	 * Sets the parent's foreign key to the related model's owner key.
	 *
	 * @since 1.0.0
	 *
	 * @param AbstractModel|int $related Related model instance or owner key value.
	 *
	 * @return AbstractModel The parent model instance (for chaining).
	 */
	public function associate( $related ) {

		$owner_key_value = $related instanceof AbstractModel
			? $related->{$this->owner_key}
			: $related;

		$this->parent->{$this->foreign_key} = $owner_key_value;

		return $this->parent;
	}

	/**
	 * Dissociate the parent model from a related model.
	 *
	 * @since 1.0.0
	 *
	 * @return AbstractModel The parent model instance (for chaining).
	 */
	public function dissociate() {

		$this->parent->{$this->foreign_key} = null;

		return $this->parent;
	}
}
