<?php
/**
 * Custom capabilities for granular access control.
 *
 * @package SuiteMkt3k
 */

namespace SuiteMkt3k\Security;

defined( 'ABSPATH' ) || exit;

final class Capabilities {

	public const MANAGE        = 'manage_suitemkt3k';
	public const EDIT_CAMPAIGN = 'edit_suitemkt3k_campaigns';
	public const VIEW_STATS    = 'view_suitemkt3k_stats';
	public const EDIT_SETTINGS = 'edit_suitemkt3k_settings';

	public static function all(): array {
		return array( self::MANAGE, self::EDIT_CAMPAIGN, self::VIEW_STATS, self::EDIT_SETTINGS );
	}

	public static function register(): void {
		add_filter( 'map_meta_cap', array( __CLASS__, 'map_meta_cap' ), 10, 4 );
	}

	public static function add_to_administrators(): void {
		$role = get_role( 'administrator' );
		if ( ! $role ) {
			return;
		}
		foreach ( self::all() as $cap ) {
			if ( ! $role->has_cap( $cap ) ) {
				$role->add_cap( $cap );
			}
		}
	}

	public static function remove_from_all_roles(): void {
		foreach ( wp_roles()->roles as $role_key => $role_data ) {
			$role = get_role( $role_key );
			if ( ! $role ) {
				continue;
			}
			foreach ( self::all() as $cap ) {
				$role->remove_cap( $cap );
			}
		}
	}

	/**
	 * Map meta caps to primitive caps. Defensive: never let unauthenticated requests pass.
	 *
	 * @param string[] $caps
	 * @param string   $cap
	 * @param int      $user_id
	 * @param mixed[]  $args
	 * @return string[]
	 */
	public static function map_meta_cap( array $caps, string $cap, int $user_id, array $args ): array {
		if ( ! in_array( $cap, self::all(), true ) ) {
			return $caps;
		}
		if ( 0 === $user_id ) {
			return array( 'do_not_allow' );
		}
		// Administrators always have access even if caps were not granted during
		// manual/SQL activation (common on locked-down hosts).
		if ( user_can( $user_id, 'manage_options' ) ) {
			return array( 'manage_options' );
		}
		return $caps;
	}

	public static function ensure( string $cap = self::MANAGE ): void {
		if ( ! current_user_can( $cap ) ) {
			wp_die(
				esc_html__( 'You do not have permission to access this resource.', 'suitemkt3k' ),
				esc_html__( 'Forbidden', 'suitemkt3k' ),
				array( 'response' => 403 )
			);
		}
	}
}
