<?php
namespace Prodigy\Includes\Models;

use Prodigy\Includes\Helpers\Prodigy_Logger;
use Prodigy\Includes\Prodigy;
use WP_Error;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class Tags
 */
class Prodigy_Tags {

	public Prodigy_Products $product_model;

	public const TAG_TERM_GROUP = 2;


	public function __construct() {
		$this->product_model = new Prodigy_Products();
	}

	/**
	 * @param int|null $post_id
	 * @param array    $input_tags
	 *
	 * @return false|void
	 */
	public function add_tags( ?int $post_id, array $input_tags ) {
		if ( $post_id === null ) {
			return false;
		}

		$current_tag_slugs = ( new Prodigy_Products() )->get_product_tags( $post_id );
		$current_tags      = $this->get_associated_tags( $current_tag_slugs );
		$new_tags          = $this->get_associated_tags( $input_tags );

		$to_remove = array_diff_key( $current_tags, $new_tags );
		$to_add    = array_diff_key( $new_tags, $current_tags );

		if ( ! empty( $to_remove ) ) {
			$this->delete_tags_for_product( $post_id, $to_remove );
			$this->delete_global_tags( $to_remove );
		}
		if ( ! empty( $to_add ) ) {
			$this->add_global_tags( $to_add );
			$this->add_tags_for_current_product( $post_id, $to_add );
		}
	}

	/**
	 * @param array $slugs
	 *
	 * @return array
	 */
	private function get_associated_tags( array $slugs ): array {
		$assocArray = array();
		foreach ( $slugs as $item ) {
			$assocArray[ $item['slug'] ] = $item;
		}

		return $assocArray;
	}

	/**
	 *
	 * @param int   $product_id
	 * @param array $tags
	 *
	 * @return bool|int|string|string[]|WP_Error|null
	 */
	public function delete_tags_for_product( int $product_id, array $tags ) {
		$result = false;
		foreach ( $tags as $tag ) {
			$term   = get_term_by( 'slug', $tag['slug'], Prodigy::get_prodigy_tag_type() );
			$result = wp_remove_object_terms( $product_id, $term->term_id, Prodigy::get_prodigy_tag_type() );
			if ( is_wp_error( $result ) ) {
				if ( PRODIGY_DEBUG_MODE ) {
					Prodigy_Logger::add_record( Prodigy_Logger::TYPE_ERROR, 'Error deleting tag: ' . $result->get_error_message() );
				}

				return new WP_Error( $result->get_error_message(), array( 'status' => $result->get_error_data()['status'] ?? \WP_Http::UNPROCESSABLE_ENTITY ) );
			}
		}

		return $result;
	}

	/**
	 * @param array $tags
	 *
	 * @return bool|WP_Error
	 */
	public function delete_global_tags( array $tags ) {
		$result = false;
		foreach ( $tags as $tag ) {
			if ( empty( ( new Prodigy_Products() )->has_products_tag( $tag['slug'] ) ) ) {
				$term = get_term_by( 'slug', $tag['slug'], Prodigy::get_prodigy_tag_type() );
				if ( is_object( $term ) ) {
					$is_deleted = wp_delete_term( $term->term_id, Prodigy::get_prodigy_tag_type() );
					if ( is_wp_error( $is_deleted ) ) {
						if ( PRODIGY_DEBUG_MODE ) {
							Prodigy_Logger::add_record( Prodigy_Logger::TYPE_ERROR, $is_deleted->get_error_message() );
						}

						return new WP_Error( $is_deleted->get_error_message(), array( 'status' => $is_deleted->get_error_data()['status'] ?? \WP_Http::UNPROCESSABLE_ENTITY ) );
					}
					$result = $this->delete_relationship_remote_tags( $term->term_id );
				}
			}
		}

		return $result;
	}

	/**
	 * @param int   $product_id
	 * @param array $tags
	 *
	 * @return array|bool|int|int[]|string|string[]|WP_Error|null
	 */
	public function add_tags_for_current_product( int $product_id, array $tags ) {
		$result = false;
		foreach ( $tags as $tag ) {
			$term = get_term_by( 'slug', $tag['slug'], Prodigy::get_prodigy_tag_type() );
			if ( empty( $term ) ) {
				continue;
			}

			$result = wp_add_object_terms( $product_id, $term->term_id, Prodigy::get_prodigy_tag_type() );
			if ( is_wp_error( $result ) ) {
				if ( PRODIGY_DEBUG_MODE ) {
					Prodigy_Logger::add_record( Prodigy_Logger::TYPE_ERROR, $result->get_error_message() );
				}

				return new WP_Error( $result->get_error_message(), array( 'status' => $result->get_error_data()['status'] ?? \WP_Http::UNPROCESSABLE_ENTITY ) );
			}
		}

		return $result;
	}

	/**
	 * @param array $tags
	 *
	 * @return bool|int|WP_Error
	 */
	public function add_global_tags( array $tags ) {
		$result = false;
		foreach ( $tags as $tag ) {
			if ( is_array( $tag ) && isset( $tag['name'] ) ) {
				$is_term_exist = term_exists( $tag['name'], Prodigy::get_prodigy_tag_type() );
				if ( isset( $is_term_exist ) ) {
					continue;
				}

				$term_result = wp_insert_term(
					$tag['name'],
					Prodigy::get_prodigy_tag_type(),
					array(
						'slug'       => $tag['slug'],
						'term_group' => self::TAG_TERM_GROUP,
					)
				);

				if ( is_wp_error( $term_result ) ) {
					if ( PRODIGY_DEBUG_MODE ) {
						Prodigy_Logger::add_record( Prodigy_Logger::TYPE_ERROR, $result->get_error_message() );
					}

					return new WP_Error( $term_result->get_error_message(), array( 'status' => $term_result->get_error_data()['status'] ?? \WP_Http::UNPROCESSABLE_ENTITY ) );
				}
				$result = $this->add_relationship_remote_tags( $term_result['term_id'], $tag['id'] );
			}
		}

		return $result;
	}

	/**
	 *
	 * @param array $data
	 *
	 * @return array|int[]|WP_Error
	 */
	public function add( $data ) {
		return wp_insert_term(
			$data['name'],
			Prodigy::get_prodigy_tag_type(),
			array(
				'slug'       => $data['slug'],
				'term_group' => self::TAG_TERM_GROUP,
			)
		);
	}

	/**
	 * @param array $data
	 * @param array $where
	 *
	 * @return array|WP_Error
	 */
	public function update( array $data, array $where ) {
		return wp_update_term(
			$where['term_id'],
			Prodigy::get_prodigy_tag_type(),
			array(
				'slug'       => $data['slug'],
				'name'       => $data['name'],
				'term_group' => self::TAG_TERM_GROUP,
			)
		);
	}

	/**
	 * @param int $term_id
	 *
	 * @return bool
	 */
	public function delete_relationship_remote_tags( int $term_id ): bool {
		return delete_term_meta( $term_id, Prodigy::PRODIGY_HOSTED_TAG_RELATION );
	}

	/**
	 * @param int $term_id
	 * @param int $remote_tag_id
	 *
	 * @return bool|int|WP_Error
	 */
	public function add_relationship_remote_tags( int $term_id, int $remote_tag_id ) {
		return add_term_meta( $term_id, Prodigy::PRODIGY_HOSTED_TAG_RELATION, $remote_tag_id, true );
	}
}
