import { IAuthentication, Client, IResult, IFetchResponse, IResultList, IFetchOptions, ICredentials, FetchClient } from '@c8y/client';
import * as semver from 'semver';

/**
 * 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;

/**
 * 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;
}

/**
 * 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;
}
/**
 * A C8ySchemaGenerator is used to generate json schemas from json objects.
 */
interface C8ySchemaGenerator {
    /**
     * Generates a json schema for the given object.
     *
     * @param obj The object to generate the schema for.
     * @param options The options passed to the schema generator.
     */
    generate: (obj: any, options?: any) => Promise<any>;
}

/**
 * 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;
}
/**
 * Converts the given object to a Cypress.Response.
 * @param obj The object to convert.
 * @param duration The duration of the request.
 * @param fetchOptions The fetch options used for the request.
 * @param url The URL of the request.
 * @param schema The schema of the response.
 */
declare function toCypressResponse(obj: IFetchResponse | IResult<any> | IResultList<any> | C8yPactRecord | Partial<Response>, duration?: number, fetchOptions?: IFetchOptions, url?: RequestInfo | URL, schema?: any): Cypress.Response<any> | undefined;
/**
 * Checks if the given object is a window.Response.
 * @param obj The object to check.
 */
declare function isWindowFetchResponse(obj: any): obj is Response;
/**
 * Checks if the given object is an IResult.
 * @param obj The object to check.
 */
declare function isIResult(obj: any): obj is IResult<any>;
/**
 * Checks if the given object is a CypressError.
 * @param error The object to check.
 * @returns True if the object is a CypressError, false otherwise.
 */
declare function isCypressError(error: any): boolean;

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;

type RequireConfigKeys = "shell" | "system";
type RequireConfigVersions = (string | null)[];
/**
 * A configuration option for required versions to run an annotated test. Supported versions are `system` and `shell`.
 * Each version is defined by and array of semver ranges or `null` to allow versions without specifying a range.
 */
type C8yRequireConfigOption = RequireConfigVersions | {
    shell?: RequireConfigVersions;
    system?: RequireConfigVersions;
};
/**
 * Checks if the given version satisfies the requirements provided as an array of semver ranges.
 * If no required ranges are provided or range is empty, `true` is returned.
 * @param version - The version to check as a string or SemVer object.
 * @param requires - The required versions as semver ranges or `null` to allow version without specifying a range.
 * @returns `true` if the version satisfies the requirements, `false` otherwise.
 */
declare function isVersionSatisfyingRequirements(version?: string | semver.SemVer, requires?: RequireConfigVersions): boolean;
/**
 * Returns the required semver ranges that are satisfied by the given version.
 * @param version - The version to check as a string or SemVer object.
 * @param requires - The required versions as semver ranges or `null` to allow version without specifying a range.
 * @returns The ranges that are satisfied by the version.
 */
declare function getRangesSatisfyingVersion(version: semver.SemVer | string, requires?: RequireConfigVersions): string[];
/**
 * Returns the minimum satisfying version for the given version and required ranges. If there is
 * more than one range that is satisfied by the version, the minimum version is returned.
 * @param version - The version to check as a string or SemVer object.
 * @param ranges - The required versions as semver ranges or `null` to allow version without specifying a range.
 * @returns The minimum satisfying version.
 */
declare function getMinSatisfyingVersion(version: string | semver.SemVer, ranges: RequireConfigVersions): semver.SemVer | undefined;
/**
 * Returns all minimum satisfying versions for the given version and required ranges.
 * @param version - The version to check as a string or SemVer object.
 * @param ranges - The required versions as semver ranges or `null` to allow version without specifying a range.
 * @returns All minimum satisfying versions for the given ranges sorted in ascending order.
 */
declare function getMinSatisfyingVersions(version: string | semver.SemVer, ranges: RequireConfigVersions): semver.SemVer[];
/**
 * Returns the minimized version string for the given version. Trailing `.0` patch versions or
 * `.0.0` minor versions and patch versions are omitted. If the version is a prerelease or build version,
 * the full version is returned.
 * @param version - The version to minimize as a string or SemVer object.
 * @returns The minimized version string.
 */
declare function getMinimizedVersionString(version: string | semver.SemVer): string | undefined;
/**
 * Converts the given version to a semver compatible version string. This is for
 * example converting `1.2` to `1.2.0`.
 * @param version - The version to convert.
 * @returns The semver version string.
 */
declare function toSemverVersion(version: string): string | undefined;

declare function oauthLogin(auth: C8yAuthOptions, baseUrl?: C8yBaseUrl): Promise<C8yAuthOptions>;

declare function isURL(obj: any): obj is URL;
declare function relativeURL(url: URL | string): string | undefined;
declare function removeBaseUrlFromString(url: string, baseUrl?: C8yBaseUrl): string;
declare function normalizeUrl(url: string): string;
declare function tenantUrl(baseUrl?: C8yBaseUrl, tenant?: C8yTenant): string | undefined;
/**
 * 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;
/**
 * 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;

declare function safeStringify(obj: any, indent?: number): string;
declare function sanitizeStringifiedObject(obj: any): any;
/**
 * Gets the value of a case-insensitive key path from an object. The path is
 * assumed to be a dot-separated string. If the path is an array, it is assumed
 * to be a list of keys.
 *
 * This function supports deep access to cookie and set-cookie headers, e.g.
 * `requestHeaders.cookie.authorization`. Cookie headers are parsed and the value
 * of the specified cookie is returned. If the cookie is not found, undefined is returned.
 *
 * @example
 * get_i(obj, "obj.key.token")
 * get_i(obj, ["obj", "key", "token"])
 * get_i(obj, "obj.key[0].token")
 * get_i(obj, "obj.key.0.token")
 * get_i(obj, "requestHeaders.cookie.authorization")
 * get_i(obj, "requestHeaders.set-cookie.authorization")
 *
 * @param obj The object to query
 * @param keyPath The case-insensitive key path to find
 * @returns The value of the key path if found, undefined otherwise
 */
declare function get_i(obj: any, keyPath: string | string[]): any | undefined;
/**
 * Converts a value to an array. If the value is an array, it is returned as is.
 * @param value The value to convert to an array
 * @returns The value as an array if it is not already an array
 */
declare function to_array<T>(value: T | T[] | undefined): T[] | undefined;
/**
 * Converts a string value to a boolean. Supported values are "true", "false", "1", and "0".
 * @param input The input string to convert to a boolean
 * @param defaultValue The default value to return if the input is not a valid boolean string
 * @returns The boolean value of the input string or the default value if the input is not a valid boolean string
 */
declare function to_boolean(input: string, defaultValue: boolean): boolean;

/**
 * Global type augmentations for Response and Cypress.Response interfaces.
 * This module extends the global interfaces to add custom properties used by c8yclient.
 */
declare global {
    interface Response {
        data?: string | any;
        method?: string;
        responseObj?: Partial<Cypress.Response<any>>;
        requestBody?: string | any;
    }
    namespace Cypress {
        interface Response<T> {
            url?: string;
            requestBody?: string | any;
            method?: string;
            $body?: any;
        }
    }
}

export { C8yPactAuthObjectKeys, authWithTenant, decodeBase64, encodeBase64, getAuthOptionsFromBasicAuthHeader, getAuthOptionsFromEnv, getAuthOptionsFromJWT, getAuthType, getMinSatisfyingVersion, getMinSatisfyingVersions, getMinimizedVersionString, getRangesSatisfyingVersion, get_i, hasAuthentication, isAbsoluteURL, isAuthOptions, isCypressError, isIResult, isPactAuthObject, isURL, isVersionSatisfyingRequirements, isWindowFetchResponse, normalizeAuthHeaders, normalizeBaseUrl, normalizeUrl, oauthLogin, relativeURL, removeBaseUrlFromString, safeStringify, sanitizeStringifiedObject, tenantFromBasicAuth, tenantUrl, toC8yAuthentication, toCypressResponse, toPactAuthObject, toSemverVersion, to_array, to_boolean };
export type { C8yAuthOptionType, C8yAuthOptions, C8yAuthentication, C8yClient, C8yClientOptions, C8yPactAuthObject, C8yRequireConfigOption, C8ySchemaGenerator, C8ySchemaMatcher, RequireConfigKeys, RequireConfigVersions };
