<?php
/**
 * AJAX endpoints for tags and notes on the reading view.
 *
 * These exist because hub-delivered guides are locked read-only (no edit_post
 * capability), yet clients may still tag them and keep notes. Each endpoint
 * does its own nonce + capability + post-type check.
 */

defined( 'ABSPATH' ) || exit;

class BW_Guides_Ajax {

	const NONCE_ACTION = 'bw_guides_ajax';

	/**
	 * Every endpoint here WRITES. Tags are shared taxonomy terms, notes annotate
	 * the guide itself (not a per-user copy), and the update check runs a full
	 * sync that creates, updates and trashes posts. So these are gated by the
	 * MANAGE capability, never the READ one — that separation is what makes
	 * "let everyone read the documentation" a safe thing to turn on.
	 *
	 * @deprecated Use BW_Guides_Admin::manage_cap(). Kept so anything that
	 *             referenced the old constant still resolves to the same value.
	 */
	const CAP = 'edit_posts';

	/**
	 * @return string The (filterable) capability required to change guides.
	 */
	private static function cap() {
		return BW_Guides_Admin::manage_cap();
	}

	public function register() {
		add_action( 'wp_ajax_bw_guides_save_tags', array( $this, 'save_tags' ) );
		add_action( 'wp_ajax_bw_guides_save_note', array( $this, 'save_note' ) );
		add_action( 'wp_ajax_bw_guides_check_updates', array( $this, 'check_updates' ) );
	}

	/**
	 * Fired in the background when a Guides screen is opened. Runs a throttled
	 * sync (the manifest request is tiny; content only downloads when hashes
	 * differ) and tells the page whether anything — including the guide being
	 * read — just changed.
	 */
	public function check_updates() {
		check_ajax_referer( self::NONCE_ACTION, 'nonce' );
		if ( ! current_user_can( self::cap() ) ) {
			wp_send_json_error( array( 'message' => __( 'You are not allowed to do that.', 'bw-guides' ) ), 403 );
		}

		if ( '' === BW_Guides_Settings::site_key() || ! BW_Guides_Sync::needs_check() ) {
			wp_send_json_success( array( 'checked' => false ) );
		}

		$result = ( new BW_Guides_Sync() )->run();
		if ( is_wp_error( $result ) ) {
			// Stay silent here — sync errors surface on the settings screen.
			wp_send_json_success(
				array(
					'checked' => true,
					'changed' => false,
				)
			);
		}

		$changed = ( (int) $result['created'] + (int) $result['updated'] + (int) $result['trashed'] ) > 0;
		$payload = array(
			'checked' => true,
			'changed' => $changed,
		);

		// Single-guide view: did the guide being read just change under the reader?
		$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
		$seen    = isset( $_POST['seen_modified'] ) ? sanitize_text_field( wp_unslash( $_POST['seen_modified'] ) ) : '';
		if ( $changed && $post_id ) {
			$post = get_post( $post_id );
			if ( $post && BW_Guides_CPT::POST_TYPE === $post->post_type ) {
				$payload['guide_updated'] = ( '' !== $seen && $post->post_modified_gmt !== $seen && 'publish' === $post->post_status );
				$payload['guide_removed'] = ( 'trash' === $post->post_status );
			}
		}

		wp_send_json_success( $payload );
	}

	private function check_request() {
		check_ajax_referer( self::NONCE_ACTION, 'nonce' );
		if ( ! current_user_can( self::cap() ) ) {
			wp_send_json_error( array( 'message' => __( 'You are not allowed to do that.', 'bw-guides' ) ), 403 );
		}
		$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
		$post    = $post_id ? get_post( $post_id ) : null;
		if ( ! $post || BW_Guides_CPT::POST_TYPE !== $post->post_type ) {
			wp_send_json_error( array( 'message' => __( 'Guide not found.', 'bw-guides' ) ), 400 );
		}
		return $post;
	}

	public function save_tags() {
		$post = $this->check_request();

		$raw  = isset( $_POST['tags'] ) ? sanitize_text_field( wp_unslash( $_POST['tags'] ) ) : '';
		$tags = array_values( array_filter( array_map( 'trim', explode( ',', $raw ) ) ) );

		$result = wp_set_object_terms( $post->ID, $tags, BW_Guides_CPT::TAXONOMY );
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( array( 'message' => $result->get_error_message() ), 500 );
		}

		$terms = wp_get_object_terms( $post->ID, BW_Guides_CPT::TAXONOMY, array( 'fields' => 'names' ) );
		wp_send_json_success( array( 'tags' => is_wp_error( $terms ) ? array() : $terms ) );
	}

	public function save_note() {
		$post = $this->check_request();

		$note = isset( $_POST['note'] ) ? wp_kses_post( wp_unslash( $_POST['note'] ) ) : '';
		update_post_meta( $post->ID, '_bw_guides_notes', wp_slash( $note ) );

		wp_send_json_success( array( 'saved' => true ) );
	}
}
