"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "PrusaLinkHttpClientBuilder", {
    enumerable: true,
    get: function() {
        return PrusaLinkHttpClientBuilder;
    }
});
const _defaulthttpclientbuilder = require("../../../shared/default-http-client.builder");
const _octoprintserviceconstants = require("../../octoprint/constants/octoprint-service.constants");
const _digestauthutil = require("./digest-auth.util");
const _nodecrypto = require("node:crypto");
class PrusaLinkHttpClientBuilder extends _defaulthttpclientbuilder.DefaultHttpClientBuilder {
    maxRetries = 1;
    username;
    password;
    authHeaderContext;
    onAuthError;
    onAuthSuccess;
    onRequestRetry;
    build() {
        if (!this.axiosOptions.baseURL) {
            throw new Error("Base URL is required");
        }
        const axiosInstance = super.build();
        if (this.username && this.password) {
            axiosInstance.interceptors.request.use(async (config)=>{
                if (this.authHeaderContext) {
                    const computedDigestHeader = this.generateDigestHeader(config.method?.toUpperCase() ?? "GET", config.url ?? "/");
                    config.headers[_octoprintserviceconstants.authorizationHeaderKey] = computedDigestHeader;
                }
                return config;
            });
            axiosInstance.interceptors.response.use((response)=>response, async (error)=>{
                const originalRequest = error.config;
                if (error.response?.status === 401 && this.username?.length && this.password?.length && (!originalRequest._retryCount || originalRequest._retryCount < this.maxRetries)) {
                    const wwwAuthHeader = error.response.headers[_octoprintserviceconstants.wwwAuthenticationHeaderKey];
                    if (wwwAuthHeader) {
                        if (typeof this.onAuthSuccess === "function") {
                            this.onAuthSuccess(wwwAuthHeader);
                        }
                        this.saveParsedAuthHeaderContext(wwwAuthHeader);
                        originalRequest._retryCount = (originalRequest._retryCount ?? 0) + 1;
                        if (typeof this.onRequestRetry === "function") {
                            this.onRequestRetry(error, originalRequest._retryCount);
                        }
                        return axiosInstance(originalRequest);
                    }
                }
                if (error.response?.status === 401 && this.onAuthError && typeof this.onAuthError === "function") {
                    this.onAuthError(error);
                }
                return Promise.reject(error);
            });
        }
        return axiosInstance;
    }
    withDigestAuth(username, password, onAuthError, onRequestRetry, onAuthSuccess) {
        if (!username?.length) {
            throw new Error("username may not be an empty string");
        }
        if (!password?.length) {
            throw new Error("password may not be an empty string");
        }
        if (onAuthError && typeof onAuthError !== "function") {
            throw new Error("onAuthError must be a function");
        }
        if (onAuthSuccess && typeof onAuthSuccess !== "function") {
            throw new Error("onAuthSuccess must be a function");
        }
        if (onRequestRetry && typeof onRequestRetry !== "function") {
            throw new Error("onRequestRetry must be a function");
        }
        this.username = username;
        this.password = password;
        this.onAuthError = onAuthError;
        this.onRequestRetry = onRequestRetry;
        this.onAuthSuccess = onAuthSuccess;
        return this;
    }
    withAuthHeader(authHeader) {
        if (!authHeader?.length) {
            throw new Error("Digest header may not be an empty string");
        }
        this.saveParsedAuthHeaderContext(authHeader);
        return this;
    }
    saveParsedAuthHeaderContext(authHeader) {
        const headerValue = authHeader.startsWith("Digest ") ? authHeader.substring(7) : authHeader;
        const authParams = Object.fromEntries(headerValue.split(", ").map((param)=>{
            const parts = param.split("=");
            if (parts.length === 2) {
                return [
                    parts[0],
                    parts[1].replace(/"/g, "")
                ];
            }
            return [
                parts[0],
                ""
            ];
        }));
        this.authHeaderContext = {
            realm: authParams.realm,
            nonce: authParams.nonce,
            qop: authParams.qop,
            hasQop: "qop" in authParams
        };
    }
    generateDigestHeader(method, uri) {
        if (!this.authHeaderContext || !this.username || !this.password) {
            throw new Error("Digest auth not properly configured");
        }
        const { realm, nonce, qop, hasQop } = this.authHeaderContext;
        return (0, _digestauthutil.generateDigestAuthHeader)({
            username: this.username,
            password: this.password,
            method,
            uri,
            realm,
            nonce,
            qop: hasQop ? qop : undefined,
            nc: hasQop ? "00000001" : undefined,
            cnonce: hasQop ? (0, _nodecrypto.randomBytes)(8).toString("hex") : undefined
        });
    }
}

//# sourceMappingURL=prusa-link-http-client.builder.js.map