import logger from "../Logger";
import OneUptimeDate from "../../../Types/Date";
import { CheckOn } from "../../../Types/Monitor/CriteriaFilter";
import Typeof from "../../../Types/Typeof";
import MonitorCriteriaMessageFormatter from "./MonitorCriteriaMessageFormatter";
import MonitorCriteriaDataExtractor from "./MonitorCriteriaDataExtractor";
import MonitorCriteriaExpectationBuilder from "./MonitorCriteriaExpectationBuilder";
import MetricUnitUtil from "../../../Utils/MetricUnitUtil";
export default class MonitorCriteriaObservationBuilder {
    static describeFilterObservation(input) {
        const { criteriaFilter } = input;
        switch (criteriaFilter.checkOn) {
            case CheckOn.ResponseTime:
                return MonitorCriteriaObservationBuilder.describeResponseTimeObservation(input);
            case CheckOn.ResponseStatusCode:
                return MonitorCriteriaObservationBuilder.describeResponseStatusCodeObservation(input);
            case CheckOn.ResponseHeader:
                return MonitorCriteriaObservationBuilder.describeResponseHeaderObservation(input);
            case CheckOn.ResponseHeaderValue:
                return MonitorCriteriaObservationBuilder.describeResponseHeaderValueObservation(input);
            case CheckOn.ResponseBody:
                return MonitorCriteriaObservationBuilder.describeResponseBodyObservation(input);
            case CheckOn.IsOnline:
                return MonitorCriteriaObservationBuilder.describeIsOnlineObservation(input);
            case CheckOn.IsRequestTimeout:
                return MonitorCriteriaObservationBuilder.describeIsTimeoutObservation(input);
            case CheckOn.IncomingRequest:
                return MonitorCriteriaObservationBuilder.describeIncomingRequestObservation(input);
            case CheckOn.RequestBody:
                return MonitorCriteriaObservationBuilder.describeRequestBodyObservation(input);
            case CheckOn.RequestHeader:
                return MonitorCriteriaObservationBuilder.describeRequestHeaderObservation(input);
            case CheckOn.RequestHeaderValue:
                return MonitorCriteriaObservationBuilder.describeRequestHeaderValueObservation(input);
            case CheckOn.JavaScriptExpression:
                return MonitorCriteriaObservationBuilder.describeJavaScriptExpressionObservation(input);
            case CheckOn.CPUUsagePercent:
                return MonitorCriteriaObservationBuilder.describeCpuUsageObservation(input);
            case CheckOn.MemoryUsagePercent:
                return MonitorCriteriaObservationBuilder.describeMemoryUsageObservation(input);
            case CheckOn.DiskUsagePercent:
                return MonitorCriteriaObservationBuilder.describeDiskUsageObservation(input);
            case CheckOn.ServerProcessName:
                return MonitorCriteriaObservationBuilder.describeServerProcessNameObservation(input);
            case CheckOn.ServerProcessPID:
                return MonitorCriteriaObservationBuilder.describeServerProcessPidObservation(input);
            case CheckOn.ServerProcessCommand:
                return MonitorCriteriaObservationBuilder.describeServerProcessCommandObservation(input);
            case CheckOn.ExpiresInHours:
                return MonitorCriteriaObservationBuilder.describeCertificateExpiresInHoursObservation(input);
            case CheckOn.ExpiresInDays:
                return MonitorCriteriaObservationBuilder.describeCertificateExpiresInDaysObservation(input);
            case CheckOn.IsSelfSignedCertificate:
                return MonitorCriteriaObservationBuilder.describeIsSelfSignedObservation(input);
            case CheckOn.IsExpiredCertificate:
                return MonitorCriteriaObservationBuilder.describeIsExpiredObservation(input);
            case CheckOn.IsValidCertificate:
                return MonitorCriteriaObservationBuilder.describeIsValidObservation(input);
            case CheckOn.IsNotAValidCertificate:
                return MonitorCriteriaObservationBuilder.describeIsInvalidObservation(input);
            case CheckOn.ResultValue:
                return MonitorCriteriaObservationBuilder.describeResultValueObservation(input);
            case CheckOn.Error:
                return MonitorCriteriaObservationBuilder.describeErrorObservation(input);
            case CheckOn.ExecutionTime:
                return MonitorCriteriaObservationBuilder.describeExecutionTimeObservation(input);
            case CheckOn.ScreenSizeType:
                return MonitorCriteriaObservationBuilder.describeScreenSizeObservation(input);
            case CheckOn.BrowserType:
                return MonitorCriteriaObservationBuilder.describeBrowserObservation(input);
            case CheckOn.LogCount:
                return MonitorCriteriaObservationBuilder.describeLogCountObservation(input);
            case CheckOn.SpanCount:
                return MonitorCriteriaObservationBuilder.describeSpanCountObservation(input);
            case CheckOn.MetricValue:
                return MonitorCriteriaObservationBuilder.describeMetricValueObservation(input);
            case CheckOn.ExceptionCount:
                return MonitorCriteriaObservationBuilder.describeExceptionCountObservation(input);
            case CheckOn.SnmpIsOnline:
                return MonitorCriteriaObservationBuilder.describeSnmpIsOnlineObservation(input);
            case CheckOn.SnmpResponseTime:
                return MonitorCriteriaObservationBuilder.describeSnmpResponseTimeObservation(input);
            case CheckOn.SnmpOidExists:
                return MonitorCriteriaObservationBuilder.describeSnmpOidExistsObservation(input);
            case CheckOn.SnmpOidValue:
                return MonitorCriteriaObservationBuilder.describeSnmpOidValueObservation(input);
            default:
                return null;
        }
    }
    static describeResponseTimeObservation(input) {
        var _a;
        const probeResponse = MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
        if (!probeResponse) {
            return null;
        }
        const responseTime = (_a = probeResponse.responseTimeInMs) !== null && _a !== void 0 ? _a : undefined;
        if (responseTime === undefined || responseTime === null) {
            return "Response time metric was not recorded";
        }
        const formatted = MonitorCriteriaMessageFormatter.formatNumber(responseTime, {
            maximumFractionDigits: 2,
        });
        const evaluationWindow = MonitorCriteriaExpectationBuilder.getEvaluationWindowDescription(input.criteriaFilter);
        let message = `Response Time (in ms) was ${formatted !== null && formatted !== void 0 ? formatted : responseTime} ms`;
        if (evaluationWindow) {
            message += ` ${evaluationWindow}`;
        }
        return message;
    }
    static describeResponseStatusCodeObservation(input) {
        const probeResponse = MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
        if (!probeResponse) {
            return null;
        }
        if (probeResponse.responseCode === undefined) {
            return "Response status code was not recorded";
        }
        return `Response Status Code was ${probeResponse.responseCode}.`;
    }
    static describeResponseHeaderObservation(input) {
        const probeResponse = MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
        if (!probeResponse) {
            return null;
        }
        const headers = Object.keys(probeResponse.responseHeaders || {}).map((header) => {
            return header.toLowerCase();
        });
        if (!headers.length) {
            return "Response headers were empty.";
        }
        return `Response headers present: ${MonitorCriteriaMessageFormatter.formatList(headers)}.`;
    }
    static describeResponseHeaderValueObservation(input) {
        const probeResponse = MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
        if (!probeResponse) {
            return null;
        }
        const headerValues = Object.values(probeResponse.responseHeaders || {}).map((value) => {
            return value.toLowerCase();
        });
        if (!headerValues.length) {
            return "Response header values were empty.";
        }
        return `Response header values: ${MonitorCriteriaMessageFormatter.formatList(headerValues)}.`;
    }
    static describeResponseBodyObservation(input) {
        const probeResponse = MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
        if (!probeResponse) {
            return null;
        }
        if (!probeResponse.responseBody) {
            return "Response body was empty.";
        }
        let bodyAsString;
        if (typeof probeResponse.responseBody === Typeof.Object) {
            try {
                bodyAsString = JSON.stringify(probeResponse.responseBody);
            }
            catch (err) {
                logger.error(err);
                bodyAsString = "[object]";
            }
        }
        else {
            bodyAsString = probeResponse.responseBody;
        }
        return `Response body sample: ${MonitorCriteriaMessageFormatter.formatSnippet(bodyAsString)}.`;
    }
    static describeIsOnlineObservation(input) {
        const probeResponse = MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
        if (probeResponse && probeResponse.isOnline !== undefined) {
            return `Monitor reported ${probeResponse.isOnline ? "online" : "offline"} status at ${OneUptimeDate.getDateAsLocalFormattedString(probeResponse.monitoredAt)}.`;
        }
        const serverResponse = MonitorCriteriaDataExtractor.getServerMonitorResponse(input.dataToProcess);
        if (serverResponse) {
            const lastHeartbeat = serverResponse.requestReceivedAt;
            const timeNow = serverResponse.timeNow || OneUptimeDate.getCurrentDate();
            const minutesSinceHeartbeat = OneUptimeDate.getDifferenceInMinutes(lastHeartbeat, timeNow);
            const formattedMinutes = MonitorCriteriaMessageFormatter.formatNumber(minutesSinceHeartbeat, {
                maximumFractionDigits: 2,
            });
            return `Server heartbeat last received ${formattedMinutes !== null && formattedMinutes !== void 0 ? formattedMinutes : minutesSinceHeartbeat} minutes ago.`;
        }
        return null;
    }
    static describeIsTimeoutObservation(input) {
        const probeResponse = MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
        if (probeResponse && probeResponse.isTimeout !== undefined) {
            return probeResponse.isTimeout
                ? "Request timed out."
                : "Request completed before timeout.";
        }
        return "Timeout information was unavailable.";
    }
    static describeIncomingRequestObservation(input) {
        const incomingRequest = MonitorCriteriaDataExtractor.getIncomingMonitorRequest(input.dataToProcess);
        if (!incomingRequest) {
            return null;
        }
        const lastHeartbeat = incomingRequest.incomingRequestReceivedAt;
        const checkedAt = incomingRequest.checkedAt || OneUptimeDate.getCurrentDate();
        const minutesSinceHeartbeat = OneUptimeDate.getDifferenceInMinutes(lastHeartbeat, checkedAt);
        const formattedMinutes = MonitorCriteriaMessageFormatter.formatNumber(minutesSinceHeartbeat, {
            maximumFractionDigits: 2,
        });
        return `Last incoming request was ${formattedMinutes !== null && formattedMinutes !== void 0 ? formattedMinutes : minutesSinceHeartbeat} minutes ago (checked at ${OneUptimeDate.getDateAsLocalFormattedString(checkedAt)}).`;
    }
    static describeRequestBodyObservation(input) {
        const incomingRequest = MonitorCriteriaDataExtractor.getIncomingMonitorRequest(input.dataToProcess);
        if (!incomingRequest) {
            return null;
        }
        const requestBody = incomingRequest.requestBody;
        if (!requestBody) {
            return "Request body was empty.";
        }
        let requestBodyAsString;
        if (typeof requestBody === Typeof.Object) {
            try {
                requestBodyAsString = JSON.stringify(requestBody);
            }
            catch (err) {
                logger.error(err);
                requestBodyAsString = "[object]";
            }
        }
        else {
            requestBodyAsString = requestBody;
        }
        return `Request body sample: ${MonitorCriteriaMessageFormatter.formatSnippet(requestBodyAsString)}.`;
    }
    static describeRequestHeaderObservation(input) {
        const incomingRequest = MonitorCriteriaDataExtractor.getIncomingMonitorRequest(input.dataToProcess);
        if (!incomingRequest) {
            return null;
        }
        const headers = Object.keys(incomingRequest.requestHeaders || {}).map((header) => {
            return header.toLowerCase();
        });
        if (!headers.length) {
            return "Request headers were empty.";
        }
        return `Request headers present: ${MonitorCriteriaMessageFormatter.formatList(headers)}.`;
    }
    static describeRequestHeaderValueObservation(input) {
        const incomingRequest = MonitorCriteriaDataExtractor.getIncomingMonitorRequest(input.dataToProcess);
        if (!incomingRequest) {
            return null;
        }
        const headerValues = Object.values(incomingRequest.requestHeaders || {}).map((value) => {
            return value.toLowerCase();
        });
        if (!headerValues.length) {
            return "Request header values were empty.";
        }
        return `Request header values: ${MonitorCriteriaMessageFormatter.formatList(headerValues)}.`;
    }
    static describeJavaScriptExpressionObservation(input) {
        if (!input.criteriaFilter.value) {
            return "JavaScript expression evaluated to false.";
        }
        return `JavaScript expression "${input.criteriaFilter.value}" evaluated to false.`;
    }
    static describeCpuUsageObservation(input) {
        const serverResponse = MonitorCriteriaDataExtractor.getServerMonitorResponse(input.dataToProcess);
        if (!serverResponse) {
            return null;
        }
        const cpuMetrics = serverResponse.basicInfrastructureMetrics;
        if (!cpuMetrics || !cpuMetrics.cpuMetrics) {
            return "CPU usage metrics were unavailable.";
        }
        const cpuPercent = MonitorCriteriaMessageFormatter.formatPercentage(cpuMetrics.cpuMetrics.percentUsed);
        const coreInfo = cpuMetrics.cpuMetrics.cores
            ? ` across ${cpuMetrics.cpuMetrics.cores} core${cpuMetrics.cpuMetrics.cores > 1 ? "s" : ""}`
            : "";
        return `CPU Usage (in %) was ${cpuPercent !== null && cpuPercent !== void 0 ? cpuPercent : "unavailable"}${coreInfo}.`;
    }
    static describeMemoryUsageObservation(input) {
        const serverResponse = MonitorCriteriaDataExtractor.getServerMonitorResponse(input.dataToProcess);
        if (!serverResponse) {
            return null;
        }
        const memoryMetrics = serverResponse.basicInfrastructureMetrics;
        if (!memoryMetrics || !memoryMetrics.memoryMetrics) {
            return "Memory usage metrics were unavailable.";
        }
        const percentUsed = MonitorCriteriaMessageFormatter.formatPercentage(memoryMetrics.memoryMetrics.percentUsed);
        const used = MonitorCriteriaMessageFormatter.formatBytes(memoryMetrics.memoryMetrics.used);
        const total = MonitorCriteriaMessageFormatter.formatBytes(memoryMetrics.memoryMetrics.total);
        return `Memory Usage (in %) was ${percentUsed !== null && percentUsed !== void 0 ? percentUsed : "unavailable"} (${used !== null && used !== void 0 ? used : "?"} used of ${total !== null && total !== void 0 ? total : "?"}).`;
    }
    static describeDiskUsageObservation(input) {
        var _a, _b;
        const serverResponse = MonitorCriteriaDataExtractor.getServerMonitorResponse(input.dataToProcess);
        if (!serverResponse) {
            return null;
        }
        const diskPath = ((_a = input.criteriaFilter.serverMonitorOptions) === null || _a === void 0 ? void 0 : _a.diskPath) || "/";
        const diskMetric = serverResponse.basicInfrastructureMetrics;
        if (!diskMetric || !((_b = diskMetric.diskMetrics) === null || _b === void 0 ? void 0 : _b.length)) {
            return `Disk metrics for path ${diskPath} were unavailable.`;
        }
        const matchedDisk = diskMetric.diskMetrics.find((disk) => {
            return (disk.diskPath.trim().toLowerCase() === diskPath.trim().toLowerCase());
        });
        if (!matchedDisk) {
            return `Disk metrics did not include path ${diskPath}.`;
        }
        const percentUsedValue = MonitorCriteriaMessageFormatter.computeDiskUsagePercent(matchedDisk);
        const percentUsed = MonitorCriteriaMessageFormatter.formatPercentage(percentUsedValue !== null && percentUsedValue !== void 0 ? percentUsedValue : undefined);
        const used = MonitorCriteriaMessageFormatter.formatBytes(matchedDisk.used);
        const total = MonitorCriteriaMessageFormatter.formatBytes(matchedDisk.total);
        const free = MonitorCriteriaMessageFormatter.formatBytes(matchedDisk.free);
        return `Disk Usage (in %) on disk ${diskPath} was ${percentUsed !== null && percentUsed !== void 0 ? percentUsed : "unavailable"} (${used !== null && used !== void 0 ? used : "?"} used of ${total !== null && total !== void 0 ? total : "?"}, free ${free !== null && free !== void 0 ? free : "?"}).`;
    }
    static describeServerProcessNameObservation(input) {
        var _a;
        const serverResponse = MonitorCriteriaDataExtractor.getServerMonitorResponse(input.dataToProcess);
        if (!serverResponse) {
            return null;
        }
        const thresholdName = ((_a = input.criteriaFilter.value) !== null && _a !== void 0 ? _a : "")
            .toString()
            .trim()
            .toLowerCase();
        const processes = serverResponse.processes || [];
        const matchingProcesses = processes.filter((process) => {
            return process.name.trim().toLowerCase() === thresholdName;
        });
        if (matchingProcesses.length > 0) {
            const summary = matchingProcesses
                .map((process) => {
                return `${process.name} (pid ${process.pid})`;
            })
                .join(", ");
            return `Process ${input.criteriaFilter.value} is running (${summary}).`;
        }
        const processSummary = MonitorCriteriaMessageFormatter.describeProcesses(processes);
        if (processSummary) {
            return `Process ${input.criteriaFilter.value} was not running. Active processes: ${processSummary}.`;
        }
        return `Process ${input.criteriaFilter.value} was not running.`;
    }
    static describeServerProcessPidObservation(input) {
        var _a;
        const serverResponse = MonitorCriteriaDataExtractor.getServerMonitorResponse(input.dataToProcess);
        if (!serverResponse) {
            return null;
        }
        const thresholdPid = ((_a = input.criteriaFilter.value) !== null && _a !== void 0 ? _a : "")
            .toString()
            .trim()
            .toLowerCase();
        const processes = serverResponse.processes || [];
        const matchingProcesses = processes.filter((process) => {
            return process.pid.toString().trim().toLowerCase() === thresholdPid;
        });
        if (matchingProcesses.length > 0) {
            const summary = matchingProcesses
                .map((process) => {
                return `${process.name} (pid ${process.pid})`;
            })
                .join(", ");
            return `Process with PID ${input.criteriaFilter.value} is running (${summary}).`;
        }
        const processSummary = MonitorCriteriaMessageFormatter.describeProcesses(processes);
        if (processSummary) {
            return `Process with PID ${input.criteriaFilter.value} was not running. Active processes: ${processSummary}.`;
        }
        return `Process with PID ${input.criteriaFilter.value} was not running.`;
    }
    static describeServerProcessCommandObservation(input) {
        var _a;
        const serverResponse = MonitorCriteriaDataExtractor.getServerMonitorResponse(input.dataToProcess);
        if (!serverResponse) {
            return null;
        }
        const thresholdCommand = ((_a = input.criteriaFilter.value) !== null && _a !== void 0 ? _a : "")
            .toString()
            .trim()
            .toLowerCase();
        const processes = serverResponse.processes || [];
        const matchingProcesses = processes.filter((process) => {
            return process.command.trim().toLowerCase() === thresholdCommand;
        });
        if (matchingProcesses.length > 0) {
            const summary = matchingProcesses
                .map((process) => {
                return `${process.command} (pid ${process.pid})`;
            })
                .join(", ");
            return `Process with command ${input.criteriaFilter.value} is running (${summary}).`;
        }
        const processSummary = MonitorCriteriaMessageFormatter.describeProcesses(processes);
        if (processSummary) {
            return `Process with command ${input.criteriaFilter.value} was not running. Active processes: ${processSummary}.`;
        }
        return `Process with command ${input.criteriaFilter.value} was not running.`;
    }
    static describeCertificateExpiresInHoursObservation(input) {
        const sslResponse = MonitorCriteriaDataExtractor.getSslResponse(input.dataToProcess);
        if (!sslResponse || !sslResponse.expiresAt) {
            return "SSL certificate expiration time was unavailable.";
        }
        const hoursRemaining = OneUptimeDate.getHoursBetweenTwoDates(OneUptimeDate.getCurrentDate(), sslResponse.expiresAt);
        const formattedHours = MonitorCriteriaMessageFormatter.formatNumber(hoursRemaining, {
            maximumFractionDigits: 2,
        });
        return `SSL certificate expires at ${OneUptimeDate.getDateAsLocalFormattedString(sslResponse.expiresAt)} (${formattedHours !== null && formattedHours !== void 0 ? formattedHours : hoursRemaining} hours remaining).`;
    }
    static describeCertificateExpiresInDaysObservation(input) {
        const sslResponse = MonitorCriteriaDataExtractor.getSslResponse(input.dataToProcess);
        if (!sslResponse || !sslResponse.expiresAt) {
            return "SSL certificate expiration time was unavailable.";
        }
        const daysRemaining = OneUptimeDate.getDaysBetweenTwoDates(OneUptimeDate.getCurrentDate(), sslResponse.expiresAt);
        const formattedDays = MonitorCriteriaMessageFormatter.formatNumber(daysRemaining, {
            maximumFractionDigits: 2,
        });
        return `SSL certificate expires at ${OneUptimeDate.getDateAsLocalFormattedString(sslResponse.expiresAt)} (${formattedDays !== null && formattedDays !== void 0 ? formattedDays : daysRemaining} days remaining).`;
    }
    static describeIsSelfSignedObservation(input) {
        const sslResponse = MonitorCriteriaDataExtractor.getSslResponse(input.dataToProcess);
        if (!sslResponse || sslResponse.isSelfSigned === undefined) {
            return "SSL certificate self-signed status was unavailable.";
        }
        return sslResponse.isSelfSigned
            ? "SSL certificate is self signed."
            : "SSL certificate is not self signed.";
    }
    static describeIsExpiredObservation(input) {
        const sslResponse = MonitorCriteriaDataExtractor.getSslResponse(input.dataToProcess);
        if (!sslResponse || !sslResponse.expiresAt) {
            return "SSL certificate expiration time was unavailable.";
        }
        const isExpired = OneUptimeDate.isBefore(sslResponse.expiresAt, OneUptimeDate.getCurrentDate());
        return isExpired
            ? "SSL certificate is expired."
            : "SSL certificate is not expired.";
    }
    static describeIsValidObservation(input) {
        const probeResponse = MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
        const sslResponse = probeResponse === null || probeResponse === void 0 ? void 0 : probeResponse.sslResponse;
        const isValid = Boolean(sslResponse &&
            (probeResponse === null || probeResponse === void 0 ? void 0 : probeResponse.isOnline) &&
            sslResponse.expiresAt &&
            !sslResponse.isSelfSigned &&
            OneUptimeDate.isAfter(sslResponse.expiresAt, OneUptimeDate.getCurrentDate()));
        if (!sslResponse) {
            return "SSL certificate details were unavailable.";
        }
        return isValid
            ? "SSL certificate is valid."
            : "SSL certificate is not valid.";
    }
    static describeIsInvalidObservation(input) {
        const probeResponse = MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
        const sslResponse = probeResponse === null || probeResponse === void 0 ? void 0 : probeResponse.sslResponse;
        const isInvalid = !sslResponse ||
            !(probeResponse === null || probeResponse === void 0 ? void 0 : probeResponse.isOnline) ||
            Boolean(sslResponse &&
                sslResponse.expiresAt &&
                (sslResponse.isSelfSigned ||
                    OneUptimeDate.isBefore(sslResponse.expiresAt, OneUptimeDate.getCurrentDate())));
        if (!sslResponse) {
            return "SSL certificate details were unavailable.";
        }
        return isInvalid
            ? "SSL certificate is not valid."
            : "SSL certificate is valid.";
    }
    static describeExecutionTimeObservation(input) {
        const syntheticResponses = MonitorCriteriaDataExtractor.getSyntheticMonitorResponses(input.dataToProcess);
        const executionTimes = syntheticResponses
            .map((response) => {
            return response.executionTimeInMS;
        })
            .filter((value) => {
            return typeof value === "number" && !isNaN(value);
        });
        if (executionTimes.length > 0) {
            const summary = MonitorCriteriaMessageFormatter.summarizeNumericSeries(executionTimes);
            if (summary) {
                return `Execution Time (in ms) recorded ${summary}.`;
            }
        }
        const customCodeResponse = MonitorCriteriaDataExtractor.getCustomCodeMonitorResponse(input.dataToProcess);
        if (customCodeResponse) {
            const formatted = MonitorCriteriaMessageFormatter.formatNumber(customCodeResponse.executionTimeInMS, { maximumFractionDigits: 2 });
            return `Execution Time (in ms) was ${formatted !== null && formatted !== void 0 ? formatted : customCodeResponse.executionTimeInMS} ms.`;
        }
        return "Execution time was unavailable.";
    }
    static describeResultValueObservation(input) {
        const syntheticResponses = MonitorCriteriaDataExtractor.getSyntheticMonitorResponses(input.dataToProcess);
        const resultValues = syntheticResponses
            .map((response) => {
            return MonitorCriteriaMessageFormatter.formatResultValue(response.result);
        })
            .filter((value) => {
            return value !== "undefined";
        });
        if (resultValues.length > 0) {
            const uniqueResults = Array.from(new Set(resultValues));
            return `Result Value samples: ${MonitorCriteriaMessageFormatter.formatList(uniqueResults)}.`;
        }
        const customCodeResponse = MonitorCriteriaDataExtractor.getCustomCodeMonitorResponse(input.dataToProcess);
        if (customCodeResponse && customCodeResponse.result !== undefined) {
            const formatted = MonitorCriteriaMessageFormatter.formatResultValue(customCodeResponse.result);
            return `Result Value was ${MonitorCriteriaMessageFormatter.formatSnippet(formatted)}.`;
        }
        return "Result value was unavailable.";
    }
    static describeErrorObservation(input) {
        var _a;
        const syntheticResponses = MonitorCriteriaDataExtractor.getSyntheticMonitorResponses(input.dataToProcess);
        const errors = syntheticResponses
            .map((response) => {
            return response.scriptError;
        })
            .filter((value) => {
            return Boolean(value);
        })
            .map((error) => {
            return MonitorCriteriaMessageFormatter.formatSnippet(error, 80);
        });
        if (errors.length > 0) {
            return `Script errors: ${MonitorCriteriaMessageFormatter.formatList(errors)}.`;
        }
        const customCodeResponse = MonitorCriteriaDataExtractor.getCustomCodeMonitorResponse(input.dataToProcess);
        if (customCodeResponse === null || customCodeResponse === void 0 ? void 0 : customCodeResponse.scriptError) {
            return `Script error: ${MonitorCriteriaMessageFormatter.formatSnippet(customCodeResponse.scriptError, 80)}.`;
        }
        if ((_a = customCodeResponse === null || customCodeResponse === void 0 ? void 0 : customCodeResponse.logMessages) === null || _a === void 0 ? void 0 : _a.length) {
            return `Script log messages: ${MonitorCriteriaMessageFormatter.formatList(customCodeResponse.logMessages)}.`;
        }
        return "No script errors were reported.";
    }
    static describeScreenSizeObservation(input) {
        const syntheticResponses = MonitorCriteriaDataExtractor.getSyntheticMonitorResponses(input.dataToProcess);
        if (!syntheticResponses.length) {
            return "Synthetic monitor results were unavailable.";
        }
        const screenSizes = Array.from(new Set(syntheticResponses.map((response) => {
            return response.screenSizeType;
        })));
        return `Synthetic monitor screen sizes: ${MonitorCriteriaMessageFormatter.formatList(screenSizes)}.`;
    }
    static describeBrowserObservation(input) {
        const syntheticResponses = MonitorCriteriaDataExtractor.getSyntheticMonitorResponses(input.dataToProcess);
        if (!syntheticResponses.length) {
            return "Synthetic monitor results were unavailable.";
        }
        const browsers = Array.from(new Set(syntheticResponses.map((response) => {
            return response.browserType;
        })));
        return `Synthetic monitor browsers: ${MonitorCriteriaMessageFormatter.formatList(browsers)}.`;
    }
    static describeLogCountObservation(input) {
        const logResponse = MonitorCriteriaDataExtractor.getLogMonitorResponse(input.dataToProcess);
        if (!logResponse) {
            return null;
        }
        return `Log count was ${logResponse.logCount}.`;
    }
    static describeSpanCountObservation(input) {
        const traceResponse = MonitorCriteriaDataExtractor.getTraceMonitorResponse(input.dataToProcess);
        if (!traceResponse) {
            return null;
        }
        return `Span count was ${traceResponse.spanCount}.`;
    }
    static describeExceptionCountObservation(input) {
        const exceptionResponse = MonitorCriteriaDataExtractor.getExceptionMonitorResponse(input.dataToProcess);
        if (!exceptionResponse) {
            return null;
        }
        return `Exception count was ${exceptionResponse.exceptionCount}.`;
    }
    static describeMetricValueObservation(input) {
        const metricValues = MonitorCriteriaDataExtractor.extractMetricValues({
            criteriaFilter: input.criteriaFilter,
            dataToProcess: input.dataToProcess,
            monitorStep: input.monitorStep,
        });
        if (!metricValues) {
            return null;
        }
        if (!metricValues.values.length) {
            return `Metric Value${metricValues.alias ? ` (${metricValues.alias})` : ""} returned no data points.`;
        }
        /*
         * Render the observation in the threshold's unit. The raw samples
         * arrive in the metric's legendUnit (or its native unit when no
         * legendUnit was set). If the user picked a different threshold
         * unit — e.g. "%" against a ratio metric whose native unit is the
         * dimensionless "1" — convert here so the message reads
         * "latest 5.85% expected to equal 2" rather than the confusing
         * "latest 0.0585 expected to equal 2".
         */
        const displayValues = MonitorCriteriaObservationBuilder.convertMetricValuesToThresholdUnit({
            values: metricValues.values,
            criteriaFilter: input.criteriaFilter,
            dataToProcess: input.dataToProcess,
            monitorStep: input.monitorStep,
            alias: metricValues.alias,
        });
        const summary = MonitorCriteriaMessageFormatter.summarizeNumericSeries(displayValues);
        if (!summary) {
            return null;
        }
        return `Metric Value${metricValues.alias ? ` (${metricValues.alias})` : ""} recorded ${summary}.`;
    }
    /*
     * Best-effort unit conversion for observation text. Mirrors the
     * sample→thresholdUnit conversion in MetricMonitorCriteria so the
     * "recorded" message and the breach comparison speak the same unit.
     * Returns the input array unchanged when units are missing or
     * incompatible — never throws.
     */
    static convertMetricValuesToThresholdUnit(input) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
        const thresholdUnit = (_a = input.criteriaFilter.metricMonitorOptions) === null || _a === void 0 ? void 0 : _a.thresholdUnit;
        if (!thresholdUnit) {
            return input.values;
        }
        const metricResponse = MonitorCriteriaDataExtractor.getMetricMonitorResponse(input.dataToProcess);
        if (!metricResponse) {
            return input.values;
        }
        const queryConfigs = ((_d = (_c = (_b = input.monitorStep.data) === null || _b === void 0 ? void 0 : _b.metricMonitor) === null || _c === void 0 ? void 0 : _c.metricViewConfig) === null || _d === void 0 ? void 0 : _d.queryConfigs) ||
            [];
        const formulaConfigs = ((_g = (_f = (_e = input.monitorStep.data) === null || _e === void 0 ? void 0 : _e.metricMonitor) === null || _f === void 0 ? void 0 : _f.metricViewConfig) === null || _g === void 0 ? void 0 : _g.formulaConfigs) ||
            [];
        const alias = input.alias;
        const matchedQuery = alias
            ? queryConfigs.find((q) => {
                var _a;
                return ((_a = q.metricAliasData) === null || _a === void 0 ? void 0 : _a.metricVariable) === alias;
            })
            : queryConfigs[0];
        const matchedFormula = !matchedQuery && alias
            ? formulaConfigs.find((f) => {
                var _a;
                return ((_a = f.metricAliasData) === null || _a === void 0 ? void 0 : _a.metricVariable) === alias;
            })
            : undefined;
        const rawMetricName = ((_j = (_h = matchedQuery === null || matchedQuery === void 0 ? void 0 : matchedQuery.metricQueryData) === null || _h === void 0 ? void 0 : _h.filterData) === null || _j === void 0 ? void 0 : _j.metricName) || undefined;
        const nativeUnitFromMap = rawMetricName
            ? (_k = metricResponse.nativeUnitsByMetricName) === null || _k === void 0 ? void 0 : _k[rawMetricName.toLowerCase()]
            : undefined;
        const sampleUnit = ((_l = matchedQuery === null || matchedQuery === void 0 ? void 0 : matchedQuery.metricAliasData) === null || _l === void 0 ? void 0 : _l.legendUnit) ||
            ((_m = matchedFormula === null || matchedFormula === void 0 ? void 0 : matchedFormula.metricAliasData) === null || _m === void 0 ? void 0 : _m.legendUnit) ||
            nativeUnitFromMap ||
            undefined;
        if (!sampleUnit || sampleUnit === thresholdUnit) {
            return input.values;
        }
        return input.values.map((v) => {
            return MetricUnitUtil.convertToMetricUnit({
                value: v,
                fromUnit: sampleUnit,
                metricUnit: thresholdUnit,
            });
        });
    }
    static getSnmpResponse(input) {
        const probeResponse = MonitorCriteriaDataExtractor.getProbeMonitorResponse(input.dataToProcess);
        return (probeResponse === null || probeResponse === void 0 ? void 0 : probeResponse.snmpResponse) || null;
    }
    static findSnmpOidResponse(input) {
        var _a, _b;
        const snmpResponse = MonitorCriteriaObservationBuilder.getSnmpResponse({
            dataToProcess: input.dataToProcess,
        });
        const oid = (_a = input.criteriaFilter.snmpMonitorOptions) === null || _a === void 0 ? void 0 : _a.oid;
        const oidResponse = oid
            ? (_b = snmpResponse === null || snmpResponse === void 0 ? void 0 : snmpResponse.oidResponses) === null || _b === void 0 ? void 0 : _b.find((response) => {
                return response.oid === oid;
            })
            : undefined;
        return { snmpResponse, oid, oidResponse };
    }
    static describeSnmpIsOnlineObservation(input) {
        const snmpResponse = MonitorCriteriaObservationBuilder.getSnmpResponse(input);
        if (!snmpResponse) {
            return "SNMP response was unavailable.";
        }
        if (snmpResponse.isOnline) {
            return "SNMP device is online.";
        }
        if (snmpResponse.failureCause) {
            return `SNMP device is offline: ${snmpResponse.failureCause}`;
        }
        return "SNMP device is offline.";
    }
    static describeSnmpResponseTimeObservation(input) {
        const snmpResponse = MonitorCriteriaObservationBuilder.getSnmpResponse(input);
        if (!snmpResponse ||
            snmpResponse.responseTimeInMs === null ||
            snmpResponse.responseTimeInMs === undefined) {
            return "SNMP response time was not recorded.";
        }
        const formatted = MonitorCriteriaMessageFormatter.formatNumber(snmpResponse.responseTimeInMs, { maximumFractionDigits: 2 });
        return `SNMP response time was ${formatted !== null && formatted !== void 0 ? formatted : snmpResponse.responseTimeInMs}ms.`;
    }
    static describeSnmpOidExistsObservation(input) {
        const { snmpResponse, oid, oidResponse } = MonitorCriteriaObservationBuilder.findSnmpOidResponse(input);
        if (!oid) {
            return "No OID is configured on this criteria.";
        }
        if (!snmpResponse) {
            return `SNMP response for OID ${oid} was unavailable.`;
        }
        if (!oidResponse || oidResponse.value === null) {
            return `SNMP OID ${oid} did not return a value.`;
        }
        return `SNMP OID ${oid} returned ${MonitorCriteriaObservationBuilder.formatSnmpValue(oidResponse.value)} (${oidResponse.type}).`;
    }
    static describeSnmpOidValueObservation(input) {
        const { snmpResponse, oid, oidResponse } = MonitorCriteriaObservationBuilder.findSnmpOidResponse(input);
        if (!oid) {
            return "No OID is configured on this criteria. Pick one from the OID dropdown in the criteria editor.";
        }
        if (!snmpResponse) {
            return `SNMP response for OID ${oid} was unavailable.`;
        }
        if (!oidResponse) {
            return `SNMP OID ${oid} was not returned by the device.`;
        }
        if (oidResponse.value === null) {
            return `SNMP OID ${oid} returned no value (${oidResponse.type}).`;
        }
        const formattedValue = MonitorCriteriaObservationBuilder.formatSnmpValue(oidResponse.value);
        const label = oidResponse.name
            ? `${oidResponse.name} (${oid})`
            : oid;
        return `SNMP OID ${label} value was ${formattedValue} (${oidResponse.type})`;
    }
    static formatSnmpValue(value) {
        if (typeof value === Typeof.Number) {
            const formatted = MonitorCriteriaMessageFormatter.formatNumber(value, {
                maximumFractionDigits: 2,
            });
            return formatted !== null && formatted !== void 0 ? formatted : String(value);
        }
        return String(value);
    }
}
//# sourceMappingURL=MonitorCriteriaObservationBuilder.js.map