"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GenerateOptionsSignal = void 0;
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 GenerateOptionsSignal {
    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);
        }
        // Pick up to 2 tokens per supported network, then cap at MAX_DAILY_RECORDS.
        const selected = (0, MarketDataUtils_js_1.pickUpToNPerNetwork)(tokens, 2).slice(0, MAX_DAILY_RECORDS);
        return selected.map((token) => this.buildSignal(token));
    }
    buildSignal(token) {
        const basePrice = token.priceUsd ?? (0, random_js_1.randomFloat)(0.01, 500, 6);
        const sentiment = this.sentimentScore(basePrice);
        const side = sentiment >= 0 ? "CALL" : "PUT";
        const strikeOffset = (0, random_js_1.randomFloat)(2, 12, 2);
        const strikePrice = side === "CALL" ? Number((basePrice * (1 + strikeOffset / 100)).toFixed(6)) : Number((basePrice * (1 - strikeOffset / 100)).toFixed(6));
        const expiryDays = (0, random_js_1.randomInt)(1, 14);
        const premiumEstimate = Number((basePrice * (0, random_js_1.randomFloat)(1.5, 4.5, 2) / 100).toFixed(6));
        const breakEvenPrice = side === "CALL" ? strikePrice + premiumEstimate : strikePrice - premiumEstimate;
        const capital = (0, random_js_1.randomInt)(500, 5000);
        const confidenceScore = Math.min(10, Math.max(5, Math.abs(sentiment) + 4));
        return {
            tokenName: token.name,
            symbol: token.symbol,
            network: token.valerisNetwork,
            contractAddress: token.contractAddress,
            category: "Trading Options",
            side,
            strategyName: side === "CALL" ? "Bull Call Setup" : "Bear Put Setup",
            entryPrice: Number(basePrice.toFixed(6)),
            targetPrice: strikePrice,
            riskLevel: side === "CALL" ? "Medium" : "High",
            suggestedAmountUsd: capital,
            executionWindow: `${expiryDays} day${expiryDays === 1 ? "" : "s"}`,
            reasoning: this.buildReasoning(token, side, basePrice, strikePrice, expiryDays),
            confidenceScore,
            strikePrice,
            optionExpiry: `${expiryDays} day${expiryDays === 1 ? "" : "s"}`,
            premiumEstimate,
            breakEvenPrice: Number(breakEvenPrice.toFixed(6))
        };
    }
    sentimentScore(basePrice) {
        // Synthetic market sentiment: -5 (bearish) to +5 (bullish).
        // Higher-priced large-cap assets get a slight bullish bias in this heuristic.
        const priceBias = basePrice > 1 ? 0.5 : -0.5;
        return (0, random_js_1.randomFloat)(-5, 5, 2) + priceBias;
    }
    buildReasoning(token, side, basePrice, strikePrice, expiryDays) {
        const direction = side === "CALL" ? "upside" : "downside";
        return [
            `${token.name} (${token.symbol}) on ${token.valerisNetwork} is flashing a short-term ${direction} options signal.`,
            ` Spot price is around $${basePrice.toFixed(4)} with a ${side} strike near $${strikePrice.toFixed(4)}.`,
            ` The setup targets movement within ~${expiryDays} day${expiryDays === 1 ? "" : "s"},`,
            ` making it attractive for traders looking for defined-risk directional exposure.`
        ].join("");
    }
}
exports.GenerateOptionsSignal = GenerateOptionsSignal;
