package com.goldenchart.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.ta4j.core.Rule;
import org.ta4j.core.Strategy;
import org.ta4j.core.TradingRecord;

/**
 * 포지션 종속성 선택에 따른 매매 시그널 판정 코어 컴포넌트.
 *
 * <h3>모드 설명</h3>
 * <ul>
 *   <li><b>LONG_ONLY</b> — Ta4j 표준 엄격 모드.
 *       {@code strategy.shouldEnter/shouldExit} 를 사용하므로,
 *       TradingRecord 에 열린 포지션이 없으면 매도 시그널을 내보내지 않는다.</li>
 *   <li><b>SIGNAL_ONLY</b> — 포지션 락 우회 모드.
 *       내부 Rule 인스턴스를 직접 호출({@code rule.isSatisfied(index)})하므로,
 *       이전 매수 기록 여부와 무관하게 지표 수식만 충족되면 시그널을 확정한다.</li>
 * </ul>
 */
@Component
@Slf4j
public class StrategySignalDeterminer {

    /**
     * positionMode 에 따라 포지션 제약 유무를 분기하여 시그널을 결정한다.
     *
     * @param strategy       Ta4j Strategy (entryRule / exitRule 포함)
     * @param tradingRecord  현재 TradingRecord 상태 (LONG_ONLY 모드에서 참조)
     * @param index          BarSeries 인덱스
     * @param positionMode   "LONG_ONLY" | "SIGNAL_ONLY" (null → LONG_ONLY 기본 적용)
     * @return "BUY" | "SELL" | "NONE"
     */
    public String determineSignal(Strategy strategy, TradingRecord tradingRecord,
                                  int index, String positionMode) {
        try {
            if ("SIGNAL_ONLY".equals(positionMode)) {
                return determineSignalOnly(strategy, index);
            }
            // LONG_ONLY (기본)
            return determineLongOnly(strategy, tradingRecord, index);
        } catch (Exception e) {
            log.warn("[SignalDeterminer] 시그널 판정 오류 idx={} mode={}: {}", index, positionMode, e.getMessage());
            return "NONE";
        }
    }

    // ── 보조 오버로드: Rule[] 직접 전달 (LiveStrategyEvaluator 호환) ─────────────

    /**
     * Rule 배열을 직접 받아 positionMode 에 따라 시그널 판정.
     * entryRule = rules[0], exitRule = rules[1]
     */
    public String determineSignalFromRules(Rule entryRule, Rule exitRule,
                                           TradingRecord tradingRecord,
                                           int index, String positionMode) {
        try {
            if ("SIGNAL_ONLY".equals(positionMode)) {
                boolean enterOk = entryRule != null && entryRule.isSatisfied(index);
                boolean exitOk  = exitRule  != null && exitRule.isSatisfied(index);
                if (enterOk) return "BUY";
                if (exitOk)  return "SELL";
                return "NONE";
            }
            // LONG_ONLY — tradingRecord 를 이용한 엄격 모드
            boolean enterOk = entryRule != null && entryRule.isSatisfied(index, tradingRecord);
            boolean exitOk  = exitRule  != null && exitRule.isSatisfied(index, tradingRecord);
            if (enterOk) return "BUY";
            if (exitOk)  return "SELL";
            return "NONE";
        } catch (Exception e) {
            log.warn("[SignalDeterminer] Rule 판정 오류 idx={} mode={}: {}", index, positionMode, e.getMessage());
            return "NONE";
        }
    }

    // ── Private ───────────────────────────────────────────────────────────────

    private String determineLongOnly(Strategy strategy, TradingRecord record, int index) {
        if (strategy.shouldEnter(index, record)) return "BUY";
        if (strategy.shouldExit(index, record))  return "SELL";
        return "NONE";
    }

    private String determineSignalOnly(Strategy strategy, int index) {
        if (strategy.getEntryRule().isSatisfied(index)) return "BUY";
        if (strategy.getExitRule().isSatisfied(index))  return "SELL";
        return "NONE";
    }
}
