import { ClarizenApiError } from "./errors.js";
function appendQueryParam(params, key, value) {
    if (value === undefined)
        return;
    if (Array.isArray(value)) {
        for (const item of value) {
            params.append(key, String(item));
        }
        return;
    }
    params.set(key, String(value));
}
const MAX_ATTEMPTS = 3;
export class HttpClient {
    baseUrl;
    auth;
    constructor(baseUrl, auth) {
        this.baseUrl = baseUrl;
        this.auth = auth;
    }
    getBaseUrl() {
        return this.baseUrl;
    }
    setBaseUrl(baseUrl) {
        this.baseUrl = baseUrl.replace(/\/$/, "");
    }
    setAuth(auth) {
        this.auth = auth;
    }
    getAuth() {
        return this.auth;
    }
    authorizationHeader() {
        if (this.auth.type === "apiKey") {
            return `ApiKey ${this.auth.token}`;
        }
        if (this.auth.type === "session") {
            return `Session ${this.auth.sessionId}`;
        }
        return undefined;
    }
    async request(path, options = {}) {
        for (let attempt = 1;; attempt++) {
            try {
                return await this.executeOnce(path, options);
            }
            catch (error) {
                if ((error instanceof ClarizenApiError && error.isSessionTimeout()) ||
                    attempt >= MAX_ATTEMPTS) {
                    throw error;
                }
            }
        }
    }
    async executeOnce(path, options) {
        const method = options.method ?? "POST";
        const url = new URL(path, this.baseUrl);
        if (options.query) {
            for (const [key, value] of Object.entries(options.query)) {
                appendQueryParam(url.searchParams, key, value);
            }
        }
        const headers = {
            Accept: "application/json",
            "Accept-Encoding": "gzip",
        };
        const authHeader = this.authorizationHeader();
        if (authHeader) {
            headers.Authorization = authHeader;
        }
        const init = { method, headers };
        if (method !== "GET" && options.body !== undefined) {
            headers["Content-Type"] = "application/json";
            init.body = JSON.stringify(options.body);
        }
        const response = await fetch(url, init);
        const text = await response.text();
        if (!text) {
            if (!response.ok) {
                throw new ClarizenApiError(response.status, {
                    errorCode: "HttpError",
                    message: response.statusText,
                });
            }
            return {};
        }
        const data = JSON.parse(text);
        if (!response.ok || (data && typeof data === "object" && "errorCode" in data)) {
            const err = data;
            if (err.errorCode) {
                throw new ClarizenApiError(response.status || 400, err);
            }
        }
        return data;
    }
}
//# sourceMappingURL=http.js.map