import {
	type AllRolesMap,
	type Role,
	PROJECT_OWNER_ROLE_SLUG,
	PROJECT_CHAT_USER_ROLE_SLUG,
} from '@n8n/permissions';
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import * as rolesApi from '@n8n/rest-api-client/api/roles';
import { useRootStore } from '@n8n/stores/useRootStore';
import type {
	CreateRoleDto,
	RoleAssignmentsResponse,
	RoleProjectMembersResponse,
	UpdateRoleDto,
} from '@n8n/api-types';
import { useSettingsStore } from './settings.store';

export const useRolesStore = defineStore('roles', () => {
	const rootStore = useRootStore();
	const settingsStore = useSettingsStore();

	const roles = ref<AllRolesMap>({
		global: [],
		project: [],
		credential: [],
		workflow: [],
	});
	const projectRoleOrder = ref<string[]>([
		'project:viewer',
		'project:chatUser',
		'project:editor',
		'project:admin',
	]);
	const projectRoleOrderMap = computed<Map<string, number>>(
		() => new Map(projectRoleOrder.value.map((role, idx) => [role, idx])),
	);

	const processedProjectRoles = computed<AllRolesMap['project']>(() =>
		roles.value.project
			.filter((role) => role.slug !== PROJECT_OWNER_ROLE_SLUG)
			.filter(
				(role) => settingsStore.isChatFeatureEnabled || role.slug !== PROJECT_CHAT_USER_ROLE_SLUG,
			)
			.sort(
				(a, b) =>
					(projectRoleOrderMap.value.get(a.slug) ?? Number.MAX_SAFE_INTEGER) -
					(projectRoleOrderMap.value.get(b.slug) ?? Number.MAX_SAFE_INTEGER),
			),
	);

	const processedCredentialRoles = computed<AllRolesMap['credential']>(() =>
		roles.value.credential.filter((role) => role.slug !== 'credential:owner'),
	);

	const processedWorkflowRoles = computed<AllRolesMap['workflow']>(() =>
		roles.value.workflow.filter((role) => role.slug !== 'workflow:owner'),
	);

	const fetchRoles = async () => {
		roles.value = await rolesApi.getRoles(rootStore.restApiContext);
	};

	const createProjectRole = async (body: CreateRoleDto): Promise<Role> => {
		return await rolesApi.createProjectRole(rootStore.restApiContext, body);
	};

	const fetchRoleBySlug = async (payload: { slug: string }): Promise<Role> => {
		return await rolesApi.getRoleBySlug(rootStore.restApiContext, payload);
	};

	const deleteProjectRole = async (slug: string): Promise<Role> => {
		return await rolesApi.deleteProjectRole(rootStore.restApiContext, slug);
	};

	const updateProjectRole = async (slug: string, body: UpdateRoleDto): Promise<Role> => {
		return await rolesApi.updateProjectRole(rootStore.restApiContext, slug, body);
	};

	const fetchRoleAssignments = async (slug: string): Promise<RoleAssignmentsResponse> => {
		return await rolesApi.getRoleAssignments(rootStore.restApiContext, slug);
	};

	const fetchRoleProjectMembers = async (
		slug: string,
		projectId: string,
	): Promise<RoleProjectMembersResponse> => {
		return await rolesApi.getRoleProjectMembers(rootStore.restApiContext, slug, projectId);
	};

	return {
		roles,
		processedProjectRoles,
		processedCredentialRoles,
		processedWorkflowRoles,
		fetchRoles,
		createProjectRole,
		fetchRoleBySlug,
		updateProjectRole,
		deleteProjectRole,
		fetchRoleAssignments,
		fetchRoleProjectMembers,
	};
});
