import { IUser, Client, IApplication, IResult, IUserGroup, ICredentials, IAuthentication, FetchClient } from '@c8y/client';

/**
 * Options for delete operations.
 */
type DeleteOptions = {
    /**
     * If true, ignores 404 Not Found errors when deleting.
     */
    ignoreNotFound?: boolean;
};
/**
 * Input types for deleteUser function.
 */
type DeleteUserInput = string | IUser | string[] | IUser[] | ((filter: IUser) => boolean);
/**
 * Creates a user with the specified global roles and optionally assigns applications.
 *
 * This function:
 * 1. Creates the user in Cumulocity
 * 2. Assigns the user to the specified global role groups
 * 3. Optionally assigns applications to the user (by name or IApplication object)
 *
 * @param client - The Cumulocity client instance
 * @param user - The user object to create (must include userName, email, etc.)
 * @param globalRoles - Array of global role names to assign to the user
 * @param applications - Optional array of application names (strings) or IApplication objects to assign
 * @returns Promise resolving to the created user result
 *
 * @throws Error if user creation fails or if roles/applications cannot be assigned
 *
 * @example
 * const userResult = await createUser(
 *   client,
 *   { userName: 'john.doe', email: 'john@example.com', password: 'SecurePass123!' },
 *   ['business'],
 *   ['cockpit', 'devicemanagement']
 * );
 */
declare function createUser(client: Client, user: IUser, globalRoles: string[], applications?: string[] | IApplication[]): Promise<IResult<IUser>>;
/**
 * Deletes one or more users from Cumulocity.
 *
 * Supports multiple input formats:
 * - Single username string
 * - Single IUser object (matched by id, userName, displayName, self, or email)
 * - Array of usernames or IUser objects
 * - Filter function to select users to delete
 *
 * When an IUser object is provided, the function matches it against existing users using
 * any available identifying properties (id, userName, displayName, self, email). This allows
 * for flexible matching even with partial user objects.
 *
 * @param client - The Cumulocity client instance
 * @param user - Username(s), IUser object(s), or filter function to identify users to delete
 * @param options - Optional configuration
 * @param options.ignoreNotFound - If true (default), ignores 404 errors when user is not found
 * @returns Promise that resolves when all users are deleted
 *
 * @throws Error if user is missing required properties or if deletion fails (unless ignoreNotFound is true)
 *
 * @example
 * // Delete single user by username
 * await deleteUser(client, 'john.doe');
 *
 * @example
 * // Delete multiple users
 * await deleteUser(client, ['user1', 'user2', 'user3']);
 *
 * @example
 * // Delete users matching a filter
 * await deleteUser(client, (user) => user.email?.includes('@example.com'));
 *
 * @example
 * // Delete user by partial IUser object
 * await deleteUser(client, { displayName: 'John Doe', email: 'john@example.com' });
 */
declare function deleteUser(client: Client, user: DeleteUserInput, options?: DeleteOptions): Promise<void>;
/**
 * Assigns one or more global roles to a user.
 *
 * This function adds the user to the specified global role groups, granting them
 * the permissions associated with those roles.
 *
 * @param client - The Cumulocity client instance
 * @param username - Username string or IUser object (must have userName property)
 * @param roles - Array of global role names to assign to the user
 * @returns Promise that resolves when all roles are assigned
 *
 * @throws Error if username is missing, roles array is empty, or if role assignment fails
 *
 * @example
 * await assignUserRoles(client, 'john.doe', ['business', 'admins']);
 *
 * @example
 * const user = await client.user.detail('john.doe');
 * await assignUserRoles(client, user.data, ['devicemanagement']);
 */
declare function assignUserRoles(client: Client, username: string | IUser, roles: string[]): Promise<void>;
/**
 * Removes all global roles currently assigned to a user.
 *
 * This function removes the user from all global role groups, effectively
 * revoking all role-based permissions.
 *
 * @param client - The Cumulocity client instance
 * @param username - Username string or IUser object (must have userName property)
 * @returns Promise that resolves when all roles are removed
 *
 * @throws Error if username is missing or if role removal fails
 *
 * @example
 * await clearUserRoles(client, 'john.doe');
 *
 * @example
 * const user = await client.user.detail('john.doe');
 * await clearUserRoles(client, user.data);
 */
declare function clearUserRoles(client: Client, username: string | IUser): Promise<void>;
/**
 * Generates a secure random password with mixed case letters, numbers, and special characters.
 *
 * The password includes:
 * - Uppercase and lowercase letters (50% chance for each letter)
 * - Numbers (from timestamp)
 * - Special characters (!@#$%^&*())
 *
 * @param length - The desired length of the password (default: 28, minimum: 8)
 * @returns A randomly generated password string
 *
 * @example
 * const password = generatePassword();
 * // Returns something like: "2Kl9j8Gh!4m2@x7n#5p3q8r9"
 *
 * @example
 * const shortPassword = generatePassword(12);
 * // Returns a 12-character password
 */
declare function generatePassword(length?: number): string;

/**
 * Creates a global role (user group) with the specified permissions.
 *
 * Global roles are user groups that define a set of permissions. This function:
 * 1. Creates a new user group with the specified name
 * 2. Assigns the specified role permissions to the group
 *
 * @param client - The Cumulocity client instance
 * @param roleOptions - Role name as string, or object with name and optional description
 * @param permissions - Array of permission (role) IDs or names to assign to this global role (e.g., ['ROLE_USER_MANAGEMENT', 'ROLE_INVENTORY_READ'])
 * @returns Promise resolving to the created user group result
 *
 * @throws Error if role creation fails or if any of the specified roles cannot be found
 *
 * @example
 * const roleResult = await createGlobalRole(
 *   client,
 *   { name: 'Custom Admin', description: 'Custom admin role with specific permissions' },
 *   ['ROLE_USER_MANAGEMENT', 'ROLE_INVENTORY_ADMIN']
 * );
 */
declare function createGlobalRole(client: Client, roleOptions: string | {
    name: string;
    description?: string;
}, permissions: string[]): Promise<IResult<IUserGroup>>;
/**
 * Deletes one or more global roles (user groups) by name.
 *
 * @param client - The Cumulocity client instance
 * @param roleNames - Single role name or array of role names to delete
 * @param options - Optional configuration
 * @param options.ignoreNotFound - If true (default), ignores 404 errors when role is not found
 * @returns Promise that resolves when all roles are deleted
 *
 * @throws Error if role names are missing or if deletion fails (unless ignoreNotFound is true)
 *
 * @example
 * // Delete single role
 * await deleteGlobalRoles(client, 'CustomRole');
 *
 * @example
 * // Delete multiple roles
 * await deleteGlobalRoles(client, ['Role1', 'Role2', 'Role3']);
 */
declare function deleteGlobalRoles(client: Client, roleNames: string | string[], options?: DeleteOptions): Promise<void>;

/**
 * Tenant ID of a Cumulocity tenant.
 * @example t123456
 */
type C8yTenant = string;
/**
 * Base URL of a Cumulocity tenant.
 * @example https://tenant.eu-latest.cumulocity.com
 */
type C8yBaseUrl = string;

interface C8yAuthOptions extends ICredentials {
    sendImmediately?: boolean;
    userAlias?: string;
    type?: string;
    xsrfToken?: string;
}
type C8yPactAuthObject = {
    user: string;
    userAlias?: string;
    type?: string;
    token?: string;
} | {
    userAlias: string;
    user?: string;
    type?: string;
    token?: string;
};
type C8yPactAuthObjectType = keyof C8yPactAuthObject;
declare const C8yPactAuthObjectKeys: C8yPactAuthObjectType[];
type C8yAuthOptionType = "BasicAuth" | "CookieAuth" | "BearerAuth" | undefined;
type C8yAuthentication = IAuthentication;
/**
 * Checks if the given object is a C8yAuthOptions.
 *
 * @param obj The object to check.
 * @param options Options to check for additional properties.
 * @returns True if the object is a C8yAuthOptions, false otherwise.
 */
declare function isAuthOptions(obj: any): obj is C8yAuthOptions;
declare function toC8yAuthentication(obj: C8yAuthOptions | IAuthentication | undefined): C8yAuthentication | undefined;
declare function getAuthType(auth?: C8yAuthOptions | C8yPactAuthObject | string): C8yAuthOptionType;
declare function hasAuthentication(client: C8yClient | Client | FetchClient): boolean;
declare function toPactAuthObject(obj: C8yAuthOptions | IAuthentication | ICredentials): C8yPactAuthObject;
declare function isPactAuthObject(obj: any): obj is C8yPactAuthObject;
declare function normalizeAuthHeaders(headers: {
    [key: string]: any;
}): {
    [key: string]: any;
};
declare function getAuthOptionsFromEnv(env: any): C8yAuthOptions | undefined;
declare function authWithTenant(env: any, options: C8yAuthOptions): C8yAuthOptions;
declare function getAuthOptionsFromBasicAuthHeader(authHeader: string): {
    user: string;
    password: string;
} | undefined;
/**
 * Extracts the authentication options from a JWT token.
 * @param jwtToken The JWT token to extract the authentication options from.
 * @returns The extracted authentication options.
 */
declare function getAuthOptionsFromJWT(jwtToken: string): C8yAuthOptions;
/**
 * Extracts the tenant from the basic auth object.
 * @param auth The basic auth object containing the user property.
 * @returns The tenant or undefined if not found.
 */
declare function tenantFromBasicAuth(auth: {
    user?: string | undefined;
} | string): string | undefined;
declare function encodeBase64(str: string): string;
declare function decodeBase64(base64: string): string;

/**
 * Matcher for matching objects against a schema. If the object does not match
 * the schema an Error will be thrown.
 */
interface C8ySchemaMatcher {
    /**
     * Matches the given object against the given schema. Throws an error when
     * schema does not match. Strict matching controls whether additional properties
     * are allowed in the object.
     *
     * @param obj Object to match.
     * @param schema Schema to match obj against.
     * @param strictMatching If true, additional properties are not allowed.
     */
    match(obj: any, schema: any, strictMatching?: boolean): boolean;
}

/**
 * Options used to configure c8yclient command.
 */
type C8yClientOptions = Partial<Cypress.Loggable> & Partial<Cypress.Timeoutable> & Partial<Pick<Cypress.Failable, "failOnStatusCode">> & Partial<{
    auth: IAuthentication;
    baseUrl: C8yBaseUrl;
    client: Client;
    preferBasicAuth: boolean;
    skipClientAuthentication: boolean;
    failOnPactValidation: boolean;
    ignorePact: boolean;
    schema: any;
    matchSchemaAndObject: boolean;
    record: C8yPactRecord;
    schemaMatcher: C8ySchemaMatcher;
    strictMatching: boolean;
    /** Custom ID to identify this request in logs. If not provided, a unique ID will be generated. */
    requestId: string;
}>;
/**
 * Wrapper for Client to pass auth and options without extending Client.
 * Using underscore to avoid name clashes with Client and misunderstandings reading the code.
 */
interface C8yClient {
    _auth?: C8yAuthentication;
    _options?: C8yClientOptions;
    _client?: Client;
}

/**
 * ID representing a pact object. Should be unique.
 * @example api__get__permission_failure_tests
 */
type C8yPactID = string;
/**
 * The request stored in a C8yPactRecord.
 */
type C8yPactRequest = Partial<Cypress.RequestOptions> & {
    $body?: any;
};
/**
 * The response stored in a C8yPactRecord.
 */
interface C8yPactResponse<T> {
    allRequestResponses?: any[];
    body?: T;
    duration?: number;
    headers?: {
        [key: string]: string | string[];
    };
    isOkStatusCode?: boolean;
    status?: number;
    statusText?: string;
    method?: string;
    $body?: any;
}
/**
 * The C8yPactRecord contains all information about a recorded request. It contains
 * the request and response as well as configuration options, auth information and
 * the created object id.
 */
interface C8yPactRecord {
    /**
     * Unique id of the record. Optional.
     */
    id?: C8yPactID;
    /**
     * Request of the record.
     */
    request: C8yPactRequest;
    /**
     * Response of the record.
     */
    response: C8yPactResponse<any>;
    /**
     * Modified response returned by interception RouteHandler.
     */
    modifiedResponse?: C8yPactResponse<any>;
    /**
     * Configuration options used for the request.
     */
    options?: C8yClientOptions;
    /**
     * Auth information used for the request. Can be Basic or Cookie auth. Contains username and possibly alias.
     */
    auth?: C8yPactAuthObject;
    /**
     * Id of an object created by the request. Used for mapping when running the recording.
     */
    createdObject?: string;
    /**
     * Converts the C8yPactRecord to a Cypress.Response object.
     */
    toCypressResponse(): Cypress.Response<any>;
    /**
     * Returns the date of the response.
     */
    date(): Date | null;
    /**
     * Returns if the record has a request header with the given key. Comparison is case-insensitive.
     */
    hasRequestHeader(key: string): boolean;
    /**
     * Returns the auth type of the record. Currently supports `BasicAuth`, `CookieAuth` or undefined.
     */
    authType(): "BasicAuth" | "CookieAuth" | "BearerAuth" | undefined;
}

declare function isURL(obj: any): obj is URL;
declare function relativeURL(url: URL | string): string | undefined;
declare function urlForBaseUrl(baseUrl: string, relativeOrAbsoluteUrl?: string): string | undefined;
declare function removeBaseUrlFromString(url: string, baseUrl?: C8yBaseUrl): string;
declare function removeBaseUrlFromRequestUrl(record: C8yPactRecord, baseUrl?: C8yBaseUrl): void;
declare function normalizeUrl(url: string): string;
declare function tenantUrl(baseUrl?: C8yBaseUrl, tenant?: C8yTenant): string | undefined;
declare function updateURLs(value: string, from: {
    baseUrl: C8yBaseUrl;
    tenant?: C8yTenant;
}, to: {
    baseUrl: C8yBaseUrl;
    tenant?: C8yTenant;
}): string;
/**
 * Checks if the given URL is an absolute URL.
 * @param url The URL to check.
 * @returns True if the URL is an absolute URL, false otherwise.
 */
declare function isAbsoluteURL(url: string): boolean;
/**
 * Validates the base URL and throws an error if the base URL is not an absolute URL. This
 * is required as commands expect an absolute URL as baseUrl. Will not fail for undefined values.
 * `Cypress.config().baseUrl` is validated by Cypress itself and throw an error.
 *
 * @param baseUrl The url to validate.
 */
declare function validateBaseUrl(baseUrl?: C8yBaseUrl): void;
/**
 * Normalizes a URL to ensure it has a protocol and proper trailing slash.
 * If no protocol is present, HTTPS is added by default.
 * If the URL has no path component, a trailing slash is appended.
 *
 * @param url - The URL string to normalize
 * @returns The normalized URL with HTTPS protocol and trailing slash if appropriate, or undefined for invalid input
 */
declare function normalizeBaseUrl(url: string | undefined): string | undefined;
/**
 * Converts the given URL to a string.
 * @param url The URL or RequestInfo to convert.
 * @returns The URL as a string.
 */
declare function toUrlString(url: RequestInfo | URL): string;

export { C8yPactAuthObjectKeys, assignUserRoles, authWithTenant, clearUserRoles, createGlobalRole, createUser, decodeBase64, deleteGlobalRoles, deleteUser, encodeBase64, generatePassword, getAuthOptionsFromBasicAuthHeader, getAuthOptionsFromEnv, getAuthOptionsFromJWT, getAuthType, hasAuthentication, isAbsoluteURL, isAuthOptions, isPactAuthObject, isURL, normalizeAuthHeaders, normalizeBaseUrl, normalizeUrl, relativeURL, removeBaseUrlFromRequestUrl, removeBaseUrlFromString, tenantFromBasicAuth, tenantUrl, toC8yAuthentication, toPactAuthObject, toUrlString, updateURLs, urlForBaseUrl, validateBaseUrl };
export type { C8yAuthOptionType, C8yAuthOptions, C8yAuthentication, C8yPactAuthObject, DeleteOptions, DeleteUserInput };
