<?php

namespace CustomPostOrder\Includes;

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

/**
 * Post type discovery, exclusions, and capability checks.
 */
class PostTypeHelper {

	/** @var list<string> */
	public const EXCLUDED_POST_TYPES = [
		'attachment',
		'revision',
		'nav_menu_item',
		'wp_block',
		'wp_template',
		'wp_template_part',
		'wp_navigation',
		'wp_global_styles',
		'wp_font_family',
		'wp_font_face',
		'customize_changeset',
		'oembed_cache',
		'user_request',
		'custom_css',
	];

	/** @var list<string> */
	public const ALLOWED_CAPABILITY_KEYS = [
		'edit_posts',
		'edit_others_posts',
		'edit_pages',
		'publish_posts',
		'manage_options',
	];

	/**
	 * @return list<\WP_Post_Type>
	 */
	public static function getAvailablePostTypeObjects(): array {
		$objects = get_post_types( [ 'public' => true ], 'objects' );
		$out     = [];

		foreach ( $objects as $name => $object ) {
			if ( ! $object instanceof \WP_Post_Type ) {
				continue;
			}
			if ( in_array( $name, self::EXCLUDED_POST_TYPES, true ) ) {
				continue;
			}
			if ( ! self::currentUserCanEditPostType( $name, $object ) ) {
				continue;
			}
			$out[ $name ] = $object;
		}

		/**
		 * Filter available post types for custom ordering.
		 *
		 * @param array<string, \WP_Post_Type> $out Post type objects keyed by slug.
		 */
		return apply_filters( 'wp_powersuite_custom_post_order_post_types', $out );
	}

	/**
	 * @return list<string>
	 */
	public static function getAvailablePostTypeSlugs(): array {
		return array_keys( self::getAvailablePostTypeObjects() );
	}

	public static function isSupportedPostType( string $post_type ): bool {
		$post_type = sanitize_key( $post_type );
		if ( $post_type === '' || ! post_type_exists( $post_type ) ) {
			return false;
		}
		if ( in_array( $post_type, self::EXCLUDED_POST_TYPES, true ) ) {
			return false;
		}

		return in_array( $post_type, self::getAvailablePostTypeSlugs(), true );
	}

	/**
	 * @param list<string> $selected
	 * @return list<string>
	 */
	public static function sanitizeSelectedPostTypes( array $selected ): array {
		$allowed = array_flip( self::getAvailablePostTypeSlugs() );
		$out     = [];

		foreach ( $selected as $type ) {
			$key = sanitize_key( (string) $type );
			if ( $key !== '' && isset( $allowed[ $key ] ) && ! in_array( $key, $out, true ) ) {
				$out[] = $key;
			}
		}

		return $out;
	}

	public static function currentUserCanEditPostType( string $post_type, ?\WP_Post_Type $object = null ): bool {
		$object = $object ?? get_post_type_object( $post_type );
		if ( ! $object instanceof \WP_Post_Type ) {
			return false;
		}

		$cap = $object->cap->edit_posts ?? 'edit_posts';
		return current_user_can( $cap );
	}

	public static function userCanReorderPostType( string $post_type, string $reorder_capability ): bool {
		if ( ! self::isSupportedPostType( $post_type ) ) {
			return false;
		}

		$reorder_capability = self::sanitizeCapabilityKey( $reorder_capability );
		if ( ! current_user_can( $reorder_capability ) ) {
			return false;
		}

		return self::currentUserCanEditPostType( $post_type );
	}

	public static function userCanEditPost( int $post_id ): bool {
		$post = get_post( $post_id );
		if ( ! $post instanceof \WP_Post ) {
			return false;
		}

		return current_user_can( 'edit_post', $post_id );
	}

	public static function sanitizeCapabilityKey( string $capability ): string {
		$capability = sanitize_key( $capability );
		if ( in_array( $capability, self::ALLOWED_CAPABILITY_KEYS, true ) ) {
			return $capability;
		}

		return 'edit_others_posts';
	}

	public static function isHierarchical( string $post_type ): bool {
		$object = get_post_type_object( $post_type );
		return $object instanceof \WP_Post_Type && $object->hierarchical;
	}
}
