<?php
/**
 * Review Meta Handler
 *
 * @package Ugcify\Review
 */

namespace Ugcify\Review;

/**
 * Class ReviewMeta

 * phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared,PluginCheck.Security.DirectDB.UnescapedDBParameter,WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.SlowDBQuery.slow_db_query_meta_value
 */
class ReviewMeta {
	/**
	 * Add meta to review
	 *
	 * @param int    $review_id Review ID.
	 * @param string $meta_key Meta key.
	 * @param mixed  $meta_value Meta value.
	 * @return int|false Meta ID on success, false on failure.
	 */
	public function add_meta( $review_id, $meta_key, $meta_value ) {
		global $wpdb;
		$table = $wpdb->prefix . 'ugcify_review_meta';

		$result = $wpdb->insert(
			$table,
			array(
				'review_id'  => $review_id,
				'meta_key'   => $meta_key,
				'meta_value' => maybe_serialize( $meta_value ),
			),
			array( '%d', '%s', '%s' )
		);

		return $result ? $wpdb->insert_id : false;
	}

	/**
	 * Get meta for a review
	 *
	 * @param int    $review_id Review ID.
	 * @param string $meta_key Optional. Specific meta key to retrieve.
	 * @param bool   $single Optional. Return single value or array.
	 * @return mixed
	 */
	public function get_meta( $review_id, $meta_key = '', $single = false ) {
		if ( function_exists( 'apply_filters' ) ) {
			$pre = apply_filters( 'ugcify_review_meta_pre_get', null, $review_id, $meta_key, $single );
			if ( null !== $pre ) {
				return $pre;
			}
		}

		global $wpdb;

		if ( $meta_key ) {
			$results = $wpdb->get_col(
				$wpdb->prepare(
					"SELECT meta_value FROM {$wpdb->prefix}ugcify_review_meta WHERE review_id = %d AND meta_key = %s",
					$review_id,
					$meta_key
				)
			);

			if ( $single ) {
				return ! empty( $results ) ? maybe_unserialize( $results[0] ) : '';
			}

			return array_map( 'maybe_unserialize', $results );
		}

		// Get all meta for review.
		$results = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT meta_key, meta_value FROM {$wpdb->prefix}ugcify_review_meta WHERE review_id = %d",
				$review_id
			)
		);
		$meta    = array();

		foreach ( $results as $row ) {
			$meta[ $row->meta_key ][] = maybe_unserialize( $row->meta_value );
		}

		return $meta;
	}

	/**
	 * Update meta for a review
	 *
	 * @param int    $review_id Review ID.
	 * @param string $meta_key Meta key.
	 * @param mixed  $meta_value Meta value.
	 * @return bool
	 */
	public function update_meta( $review_id, $meta_key, $meta_value ) {
		global $wpdb;
		$table = $wpdb->prefix . 'ugcify_review_meta';

		// Check if meta exists.
		$meta_id = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT meta_id FROM {$wpdb->prefix}ugcify_review_meta WHERE review_id = %d AND meta_key = %s LIMIT 1",
				$review_id,
				$meta_key
			)
		);

		if ( $meta_id ) {
			// Update existing meta.
			$result = $wpdb->update(
				$table,
				array( 'meta_value' => maybe_serialize( $meta_value ) ),
				array(
					'review_id' => $review_id,
					'meta_key'  => $meta_key,
				),
				array( '%s' ),
				array( '%d', '%s' )
			);

			return false !== $result;
		}

		// Add new meta.
		return false !== $this->add_meta( $review_id, $meta_key, $meta_value );
	}

	/**
	 * Delete meta for a review
	 *
	 * @param int    $review_id Review ID.
	 * @param string $meta_key Optional. Specific meta key to delete.
	 * @return bool
	 */
	public function delete_meta( $review_id, $meta_key = '' ) {
		global $wpdb;
		$table = $wpdb->prefix . 'ugcify_review_meta';

		if ( $meta_key ) {
			$result = $wpdb->delete(
				$table,
				array(
					'review_id' => $review_id,
					'meta_key'  => $meta_key,
				),
				array( '%d', '%s' )
			);
		} else {
			// Delete all meta for review.
			$result = $wpdb->delete(
				$table,
				array( 'review_id' => $review_id ),
				array( '%d' )
			);
		}

		return false !== $result;
	}
}
