<?php
/**
 * Card Oracle Easy Digital Downloads integration.
 *
 * Mirrors the WooCommerce bridge: each reading can be linked to an EDD
 * download via the _co_edd_download_id meta; until the current customer
 * has a completed payment containing that download, the reading
 * shortcode renders a "Buy this reading" gate instead of the selection
 * screen.
 *
 * @package CardOracle
 * @since   1.2.6
 */

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

/**
 * Class Card_Oracle_EDD
 *
 * Loaded unconditionally; every method that touches EDD APIs first checks
 * is_active() so the class is a no-op on non-EDD sites.
 *
 * @since 1.2.6
 */
class Card_Oracle_EDD {

	/**
	 * Whether Easy Digital Downloads is loaded on this site.
	 *
	 * @since 1.2.6
	 * @return bool
	 */
	public static function is_active() {
		return class_exists( 'Easy_Digital_Downloads' ) || function_exists( 'EDD' );
	}

	/**
	 * Get the EDD download linked to a reading, if any.
	 *
	 * @since 1.2.6
	 * @param int $reading_id Reading post ID.
	 * @return int Download post ID, or 0 when not linked.
	 */
	public static function get_linked_download_id( $reading_id ) {
		if ( ! function_exists( 'get_post_meta' ) ) {
			return 0;
		}
		$download_id = (int) get_post_meta( $reading_id, CO_EDD_DOWNLOAD_ID, true );
		return $download_id > 0 ? $download_id : 0;
	}

	/**
	 * Check whether the current customer has already purchased the linked download.
	 *
	 * Prefers edd_has_user_purchased() for logged-in users. EDD's API is
	 * user-id-centric, so guest checkouts aren't automatically unlocked here —
	 * customers will need to log in or create an account at checkout to gain
	 * access on subsequent visits.
	 *
	 * @since 1.2.6
	 * @param int $download_id EDD download post ID.
	 * @return bool True when a completed payment containing $download_id exists.
	 */
	public static function customer_has_purchased( $download_id ) {
		if ( ! self::is_active() || $download_id <= 0 ) {
			return false;
		}
		if ( ! function_exists( 'edd_has_user_purchased' ) ) {
			return false;
		}

		$user_id = function_exists( 'get_current_user_id' ) ? (int) get_current_user_id() : 0;
		if ( $user_id <= 0 ) {
			return false;
		}

		return (bool) edd_has_user_purchased( $user_id, array( $download_id ), null );
	}

	/**
	 * Render the "Buy this reading" gate HTML.
	 *
	 * @since 1.2.6
	 * @param int $reading_id  Reading post ID, used for context messaging.
	 * @param int $download_id EDD download post ID.
	 * @return string Gate HTML, or empty string when EDD isn't active or the download is missing.
	 */
	public static function render_purchase_gate( $reading_id, $download_id ) {
		if ( ! self::is_active() || $download_id <= 0 ) {
			return '';
		}
		if ( ! function_exists( 'get_post' ) ) {
			return '';
		}

		$download = get_post( $download_id );
		if ( ! $download || 'download' !== $download->post_type ) {
			return '';
		}

		$reading_title = function_exists( 'get_the_title' ) ? get_the_title( $reading_id ) : '';
		$permalink     = function_exists( 'get_permalink' ) ? get_permalink( $download_id ) : '';
		$add_to_cart   = $permalink;

		// edd_get_purchase_link returns a button shortcode-equivalent. Prefer it
		// when available so EDD's own styling/cart behaviour applies.
		$button_html = '';
		if ( function_exists( 'edd_get_purchase_link' ) ) {
			$button_html = edd_get_purchase_link(
				array(
					'download_id' => $download_id,
					'text'        => __( 'Buy this reading', 'card-oracle' ),
				)
			);
		}

		$price_html = function_exists( 'edd_price' ) ? '' : '';
		if ( function_exists( 'edd_currency_filter' ) && function_exists( 'edd_get_download_price' ) ) {
			$price_html = (string) edd_currency_filter( edd_format_amount( edd_get_download_price( $download_id ) ) );
		}

		ob_start();
		?>
		<div class="card-oracle-wc-gate card-oracle-edd-gate" data-reading-id="<?php echo esc_attr( $reading_id ); ?>" data-download-id="<?php echo esc_attr( $download_id ); ?>">
			<h3 class="card-oracle-wc-gate__heading">
				<?php
				printf(
					/* translators: %s: reading title */
					esc_html__( 'Unlock %s', 'card-oracle' ),
					esc_html( $reading_title )
				);
				?>
			</h3>
			<?php if ( '' !== $price_html ) : ?>
				<p class="card-oracle-wc-gate__price"><?php echo esc_html( $price_html ); ?></p>
			<?php endif; ?>
			<p class="card-oracle-wc-gate__cta">
				<?php if ( '' !== $button_html ) : ?>
					<?php echo wp_kses_post( $button_html ); ?>
				<?php else : ?>
					<a class="button card-oracle-wc-gate__button" href="<?php echo esc_url( $add_to_cart ); ?>">
						<?php esc_html_e( 'Buy this reading', 'card-oracle' ); ?>
					</a>
				<?php endif; ?>
			</p>
			<p class="card-oracle-wc-gate__hint description">
				<?php esc_html_e( 'After your purchase is complete, log in and return to this page to unlock your reading.', 'card-oracle' ); ?>
			</p>
		</div>
		<?php
		return (string) ob_get_clean();
	}

	/**
	 * Decide whether a reading should be gated for the current visitor.
	 *
	 * @since 1.2.6
	 * @param int $reading_id Reading post ID.
	 * @return string Gate HTML when blocked; empty string when the visitor may proceed.
	 */
	public static function maybe_render_gate( $reading_id ) {
		if ( ! self::is_active() ) {
			return '';
		}

		$download_id = self::get_linked_download_id( $reading_id );
		if ( $download_id <= 0 ) {
			return '';
		}

		if ( self::customer_has_purchased( $download_id ) ) {
			return '';
		}

		return self::render_purchase_gate( $reading_id, $download_id );
	}

	/**
	 * Build a list of published EDD downloads keyed by ID for the admin select.
	 *
	 * @since 1.2.6
	 * @return array<int|string, string>
	 */
	public static function get_downloads_for_select() {
		$options = array( '' => __( '— No EDD download —', 'card-oracle' ) );

		if ( ! self::is_active() || ! function_exists( 'get_posts' ) ) {
			return $options;
		}

		$downloads = get_posts(
			array(
				'post_type'      => 'download',
				'post_status'    => 'publish',
				'posts_per_page' => 200, // phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_posts_per_page -- admin select.
				'orderby'        => 'title',
				'order'          => 'ASC',
				'fields'         => 'ids',
				'no_found_rows'  => true,
			)
		);

		if ( ! empty( $downloads ) && function_exists( 'get_the_title' ) ) {
			foreach ( $downloads as $download_id ) {
				$options[ (string) $download_id ] = get_the_title( $download_id );
			}
		}

		return $options;
	}
}
