// This file is auto-generated by @hey-api/openapi-ts
import { createSseClient } from "../core/serverSentEvents.gen.js";
import { buildUrl, createConfig, createInterceptors, getParseAs, mergeConfigs, mergeHeaders, setAuthParams, } from "./utils.gen.js";
export const createClient = (config = {}) => {
    let _config = mergeConfigs(createConfig(), config);
    const getConfig = () => ({ ..._config });
    const setConfig = (config) => {
        _config = mergeConfigs(_config, config);
        return getConfig();
    };
    const interceptors = createInterceptors();
    const beforeRequest = async (options) => {
        const opts = {
            ..._config,
            ...options,
            fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
            headers: mergeHeaders(_config.headers, options.headers),
            serializedBody: undefined,
        };
        if (opts.security) {
            await setAuthParams({
                ...opts,
                security: opts.security,
            });
        }
        if (opts.requestValidator) {
            await opts.requestValidator(opts);
        }
        if (opts.body && opts.bodySerializer) {
            opts.serializedBody = opts.bodySerializer(opts.body);
        }
        // remove Content-Type header if body is empty to avoid sending invalid requests
        if (opts.serializedBody === undefined || opts.serializedBody === "") {
            opts.headers.delete("Content-Type");
        }
        const url = buildUrl(opts);
        return { opts, url };
    };
    const request = async (options) => {
        // @ts-expect-error
        const { opts, url } = await beforeRequest(options);
        const requestInit = {
            redirect: "follow",
            ...opts,
            body: opts.serializedBody,
        };
        let request = new Request(url, requestInit);
        for (const fn of interceptors.request._fns) {
            if (fn) {
                request = await fn(request, opts);
            }
        }
        // fetch must be assigned here, otherwise it would throw the error:
        // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
        const _fetch = opts.fetch;
        let response = await _fetch(request);
        for (const fn of interceptors.response._fns) {
            if (fn) {
                response = await fn(response, request, opts);
            }
        }
        const result = {
            request,
            response,
        };
        if (response.ok) {
            if (response.status === 204 || response.headers.get("Content-Length") === "0") {
                return opts.responseStyle === "data"
                    ? {}
                    : {
                        data: {},
                        ...result,
                    };
            }
            const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
            let data;
            switch (parseAs) {
                case "arrayBuffer":
                case "blob":
                case "formData":
                case "json":
                case "text":
                    data = await response[parseAs]();
                    break;
                case "stream":
                    return opts.responseStyle === "data"
                        ? response.body
                        : {
                            data: response.body,
                            ...result,
                        };
            }
            if (parseAs === "json") {
                if (opts.responseValidator) {
                    await opts.responseValidator(data);
                }
                if (opts.responseTransformer) {
                    data = await opts.responseTransformer(data);
                }
            }
            return opts.responseStyle === "data"
                ? data
                : {
                    data,
                    ...result,
                };
        }
        const textError = await response.text();
        let jsonError;
        try {
            jsonError = JSON.parse(textError);
        }
        catch {
            // noop
        }
        const error = jsonError ?? textError;
        let finalError = error;
        for (const fn of interceptors.error._fns) {
            if (fn) {
                finalError = (await fn(error, response, request, opts));
            }
        }
        finalError = finalError || {};
        if (opts.throwOnError) {
            throw finalError;
        }
        // TODO: we probably want to return error and improve types
        return opts.responseStyle === "data"
            ? undefined
            : {
                error: finalError,
                ...result,
            };
    };
    const makeMethod = (method) => {
        const fn = (options) => request({ ...options, method });
        fn.sse = async (options) => {
            const { opts, url } = await beforeRequest(options);
            return createSseClient({
                ...opts,
                body: opts.body,
                headers: opts.headers,
                method,
                url,
            });
        };
        return fn;
    };
    return {
        buildUrl,
        connect: makeMethod("CONNECT"),
        delete: makeMethod("DELETE"),
        get: makeMethod("GET"),
        getConfig,
        head: makeMethod("HEAD"),
        interceptors,
        options: makeMethod("OPTIONS"),
        patch: makeMethod("PATCH"),
        post: makeMethod("POST"),
        put: makeMethod("PUT"),
        request,
        setConfig,
        trace: makeMethod("TRACE"),
    };
};
