"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.filterMarketsByQuery = exports.calculate24hHighLow = exports.calculateFundingCountdown = exports.getPerpsDexFromSymbol = exports.getPerpsDisplaySymbol = exports.shouldIncludeMarket = exports.matchesMarketPattern = exports.compileMarketPattern = exports.validateMarketPattern = exports.escapeRegex = exports.MAX_MARKET_PATTERN_LENGTH = void 0;
/**
 * Maximum length for market filter patterns (prevents DoS attacks)
 */
exports.MAX_MARKET_PATTERN_LENGTH = 100;
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
exports.escapeRegex = escapeRegex;
const validateMarketPattern = (pattern) => {
    if (!pattern || pattern.trim().length === 0) {
        throw new Error('Market pattern cannot be empty');
    }
    const normalizedPattern = pattern.trim();
    if (normalizedPattern.length > exports.MAX_MARKET_PATTERN_LENGTH) {
        throw new Error(`Market pattern exceeds maximum length (${exports.MAX_MARKET_PATTERN_LENGTH} chars): ${normalizedPattern}`);
    }
    const dangerousChars = /[\\()[\]{}^$+?.|]/u;
    if (dangerousChars.test(normalizedPattern)) {
        throw new Error(`Market pattern contains invalid regex characters: ${normalizedPattern}`);
    }
    const validPattern = /^[a-zA-Z0-9:_\-*]+$/u;
    if (!validPattern.test(normalizedPattern)) {
        throw new Error(`Market pattern contains invalid characters: ${normalizedPattern}`);
    }
    return true;
};
exports.validateMarketPattern = validateMarketPattern;
const compileMarketPattern = (pattern) => {
    const normalizedPattern = pattern.trim();
    (0, exports.validateMarketPattern)(normalizedPattern);
    if (normalizedPattern.endsWith(':*')) {
        const prefix = normalizedPattern.slice(0, -2);
        return new RegExp(`^${(0, exports.escapeRegex)(prefix)}:`, 'u');
    }
    if (!normalizedPattern.includes(':')) {
        return new RegExp(`^${(0, exports.escapeRegex)(normalizedPattern)}:`, 'u');
    }
    return normalizedPattern;
};
exports.compileMarketPattern = compileMarketPattern;
const matchesMarketPattern = (symbol, matcher) => {
    if (typeof matcher === 'string') {
        return symbol === matcher;
    }
    return matcher.test(symbol);
};
exports.matchesMarketPattern = matchesMarketPattern;
const shouldIncludeMarket = (symbol, dex, hip3Enabled, compiledEnabledPatterns, compiledBlockedPatterns) => {
    if (dex === null) {
        return true;
    }
    if (!hip3Enabled) {
        return false;
    }
    if (compiledEnabledPatterns.length > 0) {
        const whitelisted = compiledEnabledPatterns.some(({ matcher }) => (0, exports.matchesMarketPattern)(symbol, matcher));
        if (!whitelisted) {
            return false;
        }
    }
    if (compiledBlockedPatterns.length === 0) {
        return true;
    }
    const blacklisted = compiledBlockedPatterns.some(({ matcher }) => (0, exports.matchesMarketPattern)(symbol, matcher));
    return !blacklisted;
};
exports.shouldIncludeMarket = shouldIncludeMarket;
const getPerpsDisplaySymbol = (symbol) => {
    if (!symbol || typeof symbol !== 'string') {
        return symbol;
    }
    const colonIndex = symbol.indexOf(':');
    if (colonIndex > 0 && colonIndex < symbol.length - 1) {
        return symbol.substring(colonIndex + 1);
    }
    return symbol;
};
exports.getPerpsDisplaySymbol = getPerpsDisplaySymbol;
const getPerpsDexFromSymbol = (symbol) => {
    if (!symbol || typeof symbol !== 'string') {
        return null;
    }
    const colonIndex = symbol.indexOf(':');
    if (colonIndex > 0 && colonIndex < symbol.length - 1) {
        return symbol.substring(0, colonIndex);
    }
    return null;
};
exports.getPerpsDexFromSymbol = getPerpsDexFromSymbol;
const calculateFundingCountdown = (params) => {
    const now = new Date();
    const nowMs = now.getTime();
    if (params?.nextFundingTime && params.nextFundingTime > nowMs) {
        const msUntilFunding = params.nextFundingTime - nowMs;
        const hoursUntilFunding = msUntilFunding / (1000 * 60 * 60);
        if (hoursUntilFunding <= 1.1) {
            const totalSeconds = Math.floor(msUntilFunding / 1000);
            const hours = Math.floor(totalSeconds / 3600);
            const minutes = Math.floor((totalSeconds % 3600) / 60);
            const seconds = totalSeconds % 60;
            const formattedHours = String(hours).padStart(2, '0');
            const formattedMinutes = String(minutes).padStart(2, '0');
            const formattedSeconds = String(seconds).padStart(2, '0');
            return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
        }
    }
    const utcMinutes = now.getUTCMinutes();
    const utcSeconds = now.getUTCSeconds();
    const minutesUntilNextHour = 59 - utcMinutes;
    const secondsUntilNextHour = 60 - utcSeconds;
    const finalSeconds = secondsUntilNextHour === 60 ? 0 : secondsUntilNextHour;
    const finalMinutes = secondsUntilNextHour === 60
        ? minutesUntilNextHour + 1
        : minutesUntilNextHour;
    const finalHours = finalMinutes === 60 ? 1 : 0;
    const adjustedMinutes = finalMinutes === 60 ? 0 : finalMinutes;
    const formattedHours = String(finalHours).padStart(2, '0');
    const formattedMinutes = String(adjustedMinutes).padStart(2, '0');
    const formattedSeconds = String(finalSeconds).padStart(2, '0');
    return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
};
exports.calculateFundingCountdown = calculateFundingCountdown;
const calculate24hHighLow = (candleData) => {
    if (!candleData?.candles || candleData.candles.length === 0) {
        return { high: 0, low: 0 };
    }
    const now = Date.now();
    const twentyFourHoursAgo = now - 24 * 60 * 60 * 1000;
    let last24hCandles = candleData.candles.filter((candle) => candle.time >= twentyFourHoursAgo);
    if (last24hCandles.length === 0) {
        last24hCandles = [...candleData.candles];
    }
    const highs = last24hCandles.map((candle) => parseFloat(candle.high));
    const lows = last24hCandles.map((candle) => parseFloat(candle.low));
    return {
        high: Math.max(...highs),
        low: Math.min(...lows),
    };
};
exports.calculate24hHighLow = calculate24hHighLow;
const filterMarketsByQuery = (markets, searchQuery) => {
    if (!searchQuery?.trim()) {
        return markets;
    }
    const lowerQuery = searchQuery.toLowerCase().trim();
    return markets.filter((market) => market.symbol?.toLowerCase().includes(lowerQuery) ||
        market.name?.toLowerCase().includes(lowerQuery));
};
exports.filterMarketsByQuery = filterMarketsByQuery;
//# sourceMappingURL=marketUtils.cjs.map