/**
 * Helpers puros para el alta de organizaciones/usuarios en el Workspace (Hub).
 * Sin dependencias de entorno para poder testearse en aislamiento (Vitest).
 */

// Slug del tenant: mismas reglas que el Hub (TenantCreateDTO.slug → ^[a-z0-9-]+$).
export const TENANT_SLUG_RE = /^[a-z0-9-]+$/;

// Roles válidos para invitar un usuario. Son los que el Hub reconoce en su
// flujo de alta (ver ProvisionUserRequestDTO / create_invite). No inventar otros.
export const WORKSPACE_INVITE_ROLES = ['user', 'admin', 'supervisor', 'operador', 'visor'] as const;
export type WorkspaceInviteRole = (typeof WORKSPACE_INVITE_ROLES)[number];

/**
 * Deriva un slug candidato a partir del nombre de la organización:
 * minúsculas, sin acentos, espacios y símbolos → guiones.
 */
export function slugifyTenantName(name: string): string {
	return name
		.normalize('NFD')
		.replace(/[̀-ͯ]/g, '') // quita acentos (marcas combinantes Unicode)
		.toLowerCase()
		.replace(/[^a-z0-9]+/g, '-')
		.replace(/^-+|-+$/g, '')
		.slice(0, 100);
}

export type TenantFormValues = {
	name: string;
	slug: string;
	contact_email: string;
};

/**
 * Valida los campos obligatorios del alta de organización antes de llamar al Hub,
 * para dar feedback inmediato sin gastar un round-trip.
 * Devuelve un mensaje de error o null si es válido.
 */
export function validateTenantForm(values: TenantFormValues): string | null {
	if (!values.name || values.name.trim().length < 2) {
		return 'El nombre de la organización debe tener al menos 2 caracteres.';
	}
	if (!TENANT_SLUG_RE.test(values.slug)) {
		return 'El slug solo admite minúsculas, dígitos y guiones (sin espacios ni acentos).';
	}
	if (!values.contact_email || !values.contact_email.includes('@')) {
		return 'El email de contacto es obligatorio y debe ser válido.';
	}
	return null;
}

/**
 * Extrae un mensaje legible del cuerpo de error de FastAPI (Hub).
 * - 401/403 → mensaje de permisos.
 * - detail string → tal cual.
 * - detail array (422 Pydantic) → "campo: msg" del primer error.
 * - cualquier otro → mensaje genérico con el status.
 */
export function hubErrorMessage(body: unknown, status: number): string {
	const detail =
		body && typeof body === 'object' ? (body as { detail?: unknown }).detail : null;

	if (typeof detail === 'string' && detail.trim()) {
		return detail;
	}

	if (Array.isArray(detail) && detail.length > 0) {
		const first = detail[0] as { loc?: unknown[]; msg?: string };
		const loc = Array.isArray(first.loc) ? first.loc : [];
		const field = loc.length ? String(loc[loc.length - 1]) : '';
		const msg = first.msg ?? 'dato inválido';
		return field ? `${field}: ${msg}` : msg;
	}

	if (status === 401 || status === 403) {
		return 'No tienes permisos de administrador en el workspace para esta acción.';
	}

	return `El workspace respondió con un error (${status}).`;
}

/** True si el status del Hub indica falta de permisos/sesión. */
export function isForbiddenStatus(status: number): boolean {
	return status === 401 || status === 403;
}
