/**
 * Maximum length for market filter patterns (prevents DoS attacks)
 */
export const MAX_MARKET_PATTERN_LENGTH = 100;
export const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
export const validateMarketPattern = (pattern) => {
    if (!pattern || pattern.trim().length === 0) {
        throw new Error('Market pattern cannot be empty');
    }
    const normalizedPattern = pattern.trim();
    if (normalizedPattern.length > MAX_MARKET_PATTERN_LENGTH) {
        throw new Error(`Market pattern exceeds maximum length (${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;
};
export const compileMarketPattern = (pattern) => {
    const normalizedPattern = pattern.trim();
    validateMarketPattern(normalizedPattern);
    if (normalizedPattern.endsWith(':*')) {
        const prefix = normalizedPattern.slice(0, -2);
        return new RegExp(`^${escapeRegex(prefix)}:`, 'u');
    }
    if (!normalizedPattern.includes(':')) {
        return new RegExp(`^${escapeRegex(normalizedPattern)}:`, 'u');
    }
    return normalizedPattern;
};
export const matchesMarketPattern = (symbol, matcher) => {
    if (typeof matcher === 'string') {
        return symbol === matcher;
    }
    return matcher.test(symbol);
};
export 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 }) => matchesMarketPattern(symbol, matcher));
        if (!whitelisted) {
            return false;
        }
    }
    if (compiledBlockedPatterns.length === 0) {
        return true;
    }
    const blacklisted = compiledBlockedPatterns.some(({ matcher }) => matchesMarketPattern(symbol, matcher));
    return !blacklisted;
};
export 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;
};
export 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;
};
export 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}`;
};
export 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),
    };
};
export 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));
};
//# sourceMappingURL=marketUtils.mjs.map