<?php
/**
 * Registers the bw_guide post type and bw_guide_tag taxonomy, and locks
 * hub-delivered guides read-only.
 */

defined( 'ABSPATH' ) || exit;

class BW_Guides_CPT {

	const POST_TYPE   = 'bw_guide';
	const TAXONOMY    = 'bw_guide_tag';
	const SOURCE_META = '_bw_guides_source';

	public function register() {
		add_action( 'init', array( $this, 'register_post_type' ) );
		add_action( 'init', array( $this, 'register_taxonomy' ) );
		add_filter( 'map_meta_cap', array( $this, 'lock_hub_guides' ), 10, 4 );
		add_filter( 'display_post_states', array( $this, 'post_states' ), 10, 2 );
		add_filter( 'post_row_actions', array( $this, 'row_actions' ), 10, 2 );
		add_action( 'save_post_' . self::POST_TYPE, array( $this, 'default_source_meta' ), 10, 2 );
	}

	public function register_post_type() {
		register_post_type(
			self::POST_TYPE,
			array(
				'labels'              => array(
					'name'               => __( 'Guides', 'bw-guides' ),
					'singular_name'      => __( 'Guide', 'bw-guides' ),
					'add_new'            => __( 'Add New Guide', 'bw-guides' ),
					'add_new_item'       => __( 'Add New Guide', 'bw-guides' ),
					'edit_item'          => __( 'Edit Guide', 'bw-guides' ),
					'new_item'           => __( 'New Guide', 'bw-guides' ),
					'view_item'          => __( 'View Guide', 'bw-guides' ),
					'search_items'       => __( 'Search Guides', 'bw-guides' ),
					'not_found'          => __( 'No guides found', 'bw-guides' ),
					'not_found_in_trash' => __( 'No guides found in Trash', 'bw-guides' ),
					'menu_name'          => __( 'Guides', 'bw-guides' ),
				),
				'description'         => __( 'Guides and documentation for this website.', 'bw-guides' ),
				'public'              => false,
				'exclude_from_search' => true,
				'publicly_queryable'  => false,
				'show_ui'             => true,
				'show_in_menu'        => false, // Placed under the custom Guides menu by BW_Guides_Admin.
				'show_in_rest'        => true,  // Required for the block editor.
				'supports'            => array( 'title', 'editor', 'excerpt' ),
				'has_archive'         => false,
				'rewrite'             => false,
			)
		);
	}

	public function register_taxonomy() {
		register_taxonomy(
			self::TAXONOMY,
			self::POST_TYPE,
			array(
				'labels'            => array(
					'name'          => __( 'Guide Tags', 'bw-guides' ),
					'singular_name' => __( 'Guide Tag', 'bw-guides' ),
					'menu_name'     => __( 'Tags', 'bw-guides' ),
				),
				'hierarchical'      => false,
				'public'            => false,
				'show_ui'           => true,
				'show_in_menu'      => false,
				'show_admin_column' => true,
				'show_in_rest'      => true,
			)
		);
	}

	/**
	 * Hub-delivered guides are read-only on this site: editing or deleting them
	 * is denied for everyone. (Tags and notes are saved through the plugin's own
	 * AJAX endpoints, and the sync engine writes via wp_update_post, which does
	 * not perform capability checks.)
	 */
	public function lock_hub_guides( $caps, $cap, $user_id, $args ) {
		if ( ! in_array( $cap, array( 'edit_post', 'delete_post' ), true ) || empty( $args[0] ) ) {
			return $caps;
		}
		$post = get_post( $args[0] );
		if ( $post && self::POST_TYPE === $post->post_type && 'hub' === get_post_meta( $post->ID, self::SOURCE_META, true ) ) {
			$caps[] = 'do_not_allow';
		}
		return $caps;
	}

	public function post_states( $states, $post ) {
		if ( $post && self::POST_TYPE === $post->post_type && 'hub' === get_post_meta( $post->ID, self::SOURCE_META, true ) ) {
			$states['bw_guides_hub'] = __( 'Bowden Works', 'bw-guides' );
		}
		return $states;
	}

	public function row_actions( $actions, $post ) {
		if ( $post && self::POST_TYPE === $post->post_type && 'publish' === $post->post_status ) {
			$url = admin_url( 'admin.php?page=bw-guides&guide=' . (int) $post->ID );
			$actions['bw_guides_read'] = '<a href="' . esc_url( $url ) . '">' . esc_html__( 'Read', 'bw-guides' ) . '</a>';
		}
		return $actions;
	}

	/**
	 * Guides created on this site default to source 'local'. Hub guides are
	 * inserted by the sync engine with the meta already set (via meta_input),
	 * so this never overwrites it.
	 */
	public function default_source_meta( $post_id, $post ) {
		if ( wp_is_post_revision( $post_id ) ) {
			return;
		}
		if ( ! get_post_meta( $post_id, self::SOURCE_META, true ) ) {
			update_post_meta( $post_id, self::SOURCE_META, 'local' );
		}
	}
}
