"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenerateAIStrategySignal = void 0;
const StrategyCatalog_js_1 = require("../../domain/services/StrategyCatalog.js");
const AppError_js_1 = require("../../shared/errors/AppError.js");
const random_js_1 = require("../../shared/utils/random.js");
const MarketDataUtils_js_1 = require("./shared/MarketDataUtils.js");
const MAX_DAILY_RECORDS = 10;
class GenerateAIStrategySignal {
    marketDataRepository;
    constructor(marketDataRepository) {
        this.marketDataRepository = marketDataRepository;
    }
    async execute(networkCode) {
        const tokens = await (0, MarketDataUtils_js_1.filterValerisTrendingTokens)((limit) => this.marketDataRepository.getTopTrendingTokens(limit), MAX_DAILY_RECORDS * 2, networkCode);
        if (tokens.length === 0) {
            const networkMsg = networkCode ? `for the selected network` : `on Lychee-supported networks`;
            throw new AppError_js_1.AppError(`No trending tokens ${networkMsg} are available right now.`, "NO_TRENDING_TOKENS", true);
        }
        return tokens.slice(0, MAX_DAILY_RECORDS).map((token) => this.buildSignal(token));
    }
    buildSignal(token) {
        const basePrice = token.priceUsd ?? (0, random_js_1.randomFloat)(0.01, 500, 6);
        const volatility = (0, random_js_1.randomFloat)(10, 80, 2);
        const trend = (0, random_js_1.randomFloat)(-15, 15, 2);
        const strategy = this.matchStrategy(basePrice, volatility, trend);
        const direction = trend >= 0 ? "BUY" : "SELL";
        const targetPrice = direction === "BUY"
            ? Number((basePrice * (1 + (0, random_js_1.randomFloat)(4, 18, 2) / 100)).toFixed(6))
            : Number((basePrice * (1 - (0, random_js_1.randomFloat)(4, 18, 2) / 100)).toFixed(6));
        const capital = (0, random_js_1.randomInt)(500, 5000);
        const windowDays = (0, random_js_1.randomInt)(1, 30);
        return {
            tokenName: token.name,
            symbol: token.symbol,
            network: token.valerisNetwork,
            contractAddress: token.contractAddress,
            category: "AI Strategy",
            side: direction,
            strategyName: strategy.name,
            aiStrategyName: strategy.name,
            entryPrice: Number(basePrice.toFixed(6)),
            targetPrice,
            riskLevel: volatility > 50 || Math.abs(trend) > 10 ? "High" : volatility > 30 ? "Medium" : "Low",
            suggestedAmountUsd: capital,
            executionWindow: `${windowDays} day${windowDays === 1 ? "" : "s"}`,
            reasoning: this.buildReasoning(token, strategy.name, basePrice, volatility, trend, windowDays),
            confidenceScore: Math.min(10, Math.max(4, 8 - volatility / 20 + Math.abs(trend) / 20)),
            pairs: this.buildPairs(token.symbol)
        };
    }
    matchStrategy(basePrice, volatility, trend) {
        // Simple rule-based matching between market profile and AI strategy catalogue.
        if (volatility > 60 && Math.abs(trend) < 5)
            return StrategyCatalog_js_1.AI_STRATEGIES.find((s) => s.name === "Grid Weaver") ?? (0, random_js_1.chooseOne)(StrategyCatalog_js_1.AI_STRATEGIES);
        if (trend > 8)
            return StrategyCatalog_js_1.AI_STRATEGIES.find((s) => s.name === "Momentum Surge") ?? (0, random_js_1.chooseOne)(StrategyCatalog_js_1.AI_STRATEGIES);
        if (trend < -8)
            return StrategyCatalog_js_1.AI_STRATEGIES.find((s) => s.name === "Mean Reversion Pro") ?? (0, random_js_1.chooseOne)(StrategyCatalog_js_1.AI_STRATEGIES);
        if (basePrice < 1 && volatility > 40)
            return StrategyCatalog_js_1.AI_STRATEGIES.find((s) => s.name === "Scalpel") ?? (0, random_js_1.chooseOne)(StrategyCatalog_js_1.AI_STRATEGIES);
        if (Math.abs(trend) < 3 && volatility < 30)
            return StrategyCatalog_js_1.AI_STRATEGIES.find((s) => s.name === "Yield Aggregator Auto") ?? (0, random_js_1.chooseOne)(StrategyCatalog_js_1.AI_STRATEGIES);
        if (volatility > 50)
            return StrategyCatalog_js_1.AI_STRATEGIES.find((s) => s.name === "Breakout Beast") ?? (0, random_js_1.chooseOne)(StrategyCatalog_js_1.AI_STRATEGIES);
        return (0, random_js_1.chooseOne)(StrategyCatalog_js_1.AI_STRATEGIES);
    }
    buildReasoning(token, strategyName, basePrice, volatility, trend, windowDays) {
        const trendWord = trend >= 0 ? "bullish" : "bearish";
        return [
            `${token.name} (${token.symbol}) on ${token.valerisNetwork} fits the `,
            `"${strategyName}" AI strategy. Current price ~$${basePrice.toFixed(4)}, `,
            `estimated volatility ${volatility.toFixed(1)}% and a ${trendWord} ${Math.abs(trend).toFixed(1)}% trend bias.`,
            ` The strategy is expected to remain active for ~${windowDays} day${windowDays === 1 ? "" : "s"},`,
            ` adjusting positions automatically based on live market conditions.`
        ].join("");
    }
    buildPairs(symbol) {
        const normalized = symbol.toUpperCase();
        const commonQuotes = ["USDT", "USDC", "BTC", "ETH", "BNB", "FDUSD"];
        const pairs = [];
        for (const quote of commonQuotes) {
            if (pairs.length >= 5)
                break;
            if (quote === normalized)
                continue;
            pairs.push(`${normalized}/${quote}`);
        }
        return pairs;
    }
}
exports.GenerateAIStrategySignal = GenerateAIStrategySignal;
