<?php

namespace Limb_Chatbot\Includes\Services;

use Limb_Chatbot\Includes\Data_Objects\Lead;
use Limb_Chatbot\Includes\Traits\SingletonTrait;

/**
 * Centralized user-role catalog for chatbot access configuration.
 *
 * @since 1.0.0
 */
class User_Roles {
	use SingletonTrait;

	/**
	 * Plugin-native role: unrestricted access.
	 */
	public const ROLE_EVERYONE = 'everyone';
	/**
	 * Plugin-native role: users with captured lead/contact data.
	 */
	public const ROLE_CONTACTS = 'contact';
	/**
	 * Plugin-native role: non logged-in chatbot users.
	 */
	public const ROLE_VISITORS = 'visitor';

	public static function resolve_current_chatbot_user_roles( $chatbot_user ) {
		$roles = [];
		if ( ! $chatbot_user ) {
			return [ User_Roles::ROLE_VISITORS ];
		}

		$lead_count = Lead::count( [ 'chatbot_user_uuid' => $chatbot_user->get_uuid() ] );
		$is_contact = (int) $lead_count > 0;
		if ( $is_contact ) {
			$roles[] = User_Roles::ROLE_CONTACTS;
		}

		$wp_roles = [];
		if ( $chatbot_user->is_wp_user() ) {
			$wp_user = get_user_by( 'id', $chatbot_user->get_wp_user_id() );
			if ( $wp_user && ! empty( $wp_user->roles ) && is_array( $wp_user->roles ) ) {
				$wp_roles = array_values(
					array_filter(
						array_map(
							static function ( $role ) {
								return is_string( $role ) ? sanitize_key( $role ) : '';
							},
							$wp_user->roles
						)
					)
				);
			}
		}

		$roles = array_merge( $roles, $wp_roles );
		if ( ! $chatbot_user->is_wp_user() && ! $is_contact && empty( $wp_roles ) ) {
			$roles[] = User_Roles::ROLE_VISITORS;
		}

		return array_values( array_unique( $roles ) );
	}

	/**
	 * Normalize role slugs to canonical values.
	 *
	 * @param  array  $roles
	 *
	 * @return string[]
	 */
	public static function normalize_roles( array $roles ): array {
		return array_values( array_filter( array_unique( array_map(
			static function ( $role ) {
				return is_string( $role ) ? sanitize_key( $role ) : '';
			},
			$roles
		) ) ) );
	}

	/**
	 * Expand roles to include canonical + legacy aliases for matching.
	 *
	 * @param  array  $roles
	 *
	 * @return string[]
	 */
	public static function expand_roles_for_matching( array $roles ): array {
		return self::normalize_roles( $roles );
	}

	/**
	 * Get one role object by its key.
	 *
	 * @param  string  $key
	 *
	 * @return array<string,mixed>|null
	 */
	public function get_by_key( string $key ): ?array {
		$key = sanitize_key( $key );
		if ( '' === $key ) {
			return null;
		}

		foreach ( $this->get_items() as $role ) {
			if ( ! empty( $role['key'] ) && $role['key'] === $key ) {
				return $role;
			}
		}

		return null;
	}

	/**
	 * Get all available roles (plugin-native + WordPress roles).
	 *
	 * @return array<int, array<string,mixed>>
	 */
	public function get_items(): array {
		$roles = [
			[
				'key'              => self::ROLE_EVERYONE,
				'label'            => __( 'Everyone', 'limb-chatbot' ),
				'description'      => null,
				'is_plugin_native' => true,
				'select_all'       => true,
			],
			[
				'key'              => self::ROLE_CONTACTS,
				'label'            => __( 'Contacts', 'limb-chatbot' ),
				'description'      => __( 'Known leads', 'limb-chatbot' ),
				'is_plugin_native' => true,
				'select_all'       => false,
			],
			[
				'key'              => self::ROLE_VISITORS,
				'label'            => __( 'Visitors', 'limb-chatbot' ),
				'description'      => __( 'Non logged in', 'limb-chatbot' ),
				'is_plugin_native' => true,
				'select_all'       => false,
			],
		];

		$wp_roles = wp_roles();
		if ( $wp_roles && isset( $wp_roles->roles ) && is_array( $wp_roles->roles ) ) {
			foreach ( $wp_roles->roles as $role_key => $role_data ) {
				$role_key = sanitize_key( (string) $role_key );
				if ( '' === $role_key ) {
					continue;
				}

				$roles[] = [
					'key'              => $role_key,
					'label'            => (string) ( $role_data['name'] ?? $role_key ),
					'description'      => null,
					'is_plugin_native' => false,
					'select_all'       => false,
				];
			}
		}

		return $roles;
	}
}
