package com.goldenchart.config;

import com.goldenchart.entity.GcAppSettings;
import com.goldenchart.entity.GcWatchlist;
import com.goldenchart.repository.GcWatchlistRepository;
import com.goldenchart.service.AppSettingsService;
import com.goldenchart.service.LiveStrategyEvaluator;
import com.goldenchart.service.StrategyConditionTimeframeService;
import com.goldenchart.websocket.DynamicSubscriptionManager;
import com.goldenchart.websocket.UpbitWebSocketClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * 서버 기동 시 isLiveCheck=true 인 모든 종목을 업비트 WS·Ta4jStorage 에 고정 구독한다.
 * (재시작 후에도 실시간 전략 평가가 끊기지 않도록)
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class LiveStrategyStartupRunner implements ApplicationRunner {

    private final AppSettingsService         appSettingsService;
    private final GcWatchlistRepository           watchlistRepo;
    private final DynamicSubscriptionManager      subscriptionManager;
    private final LiveStrategyEvaluator            liveStrategyEvaluator;
    private final StrategyConditionTimeframeService conditionTimeframes;
    private final UpbitWebSocketClient     upbitWebSocketClient;

    @Override
    public void run(ApplicationArguments args) {
        // 디바이스별 전역 설정이 켜져 있고 전략이 지정된 경우, DB 관심종목 전체 고정 구독
        int pinned = 0;
        for (GcWatchlist w : watchlistRepo.findAll()) {
            Long userId = w.getUserId();
            String deviceId = w.getDeviceId();
            if (userId == null && deviceId == null) continue;
            GcAppSettings app = appSettingsService.getEntity(userId, deviceId);
            if (!Boolean.TRUE.equals(app.getLiveStrategyCheck()) || app.getLiveStrategyId() == null) {
                continue;
            }
            pinStrategyTimeframes(w.getSymbol(), app.getLiveStrategyId());
            liveStrategyEvaluator.invalidateCache(w.getSymbol());
            pinned++;
        }
        if (pinned > 0) {
            log.info("[LiveStrategyStartup] 관심종목 기준 마켓 {}개 고정 구독 완료", pinned);
        }
        // WS 연결 직후 addMarket 이 구독 패킷을 놓치는 경우 대비
        upbitWebSocketClient.resubscribeAll();
    }

    private void pinStrategyTimeframes(String market, Long strategyId) {
        subscriptionManager.ensureMarketPinned(market, "1m");
        for (String ct : conditionTimeframes.collectForStrategy(strategyId)) {
            if (!"1m".equals(ct)) {
                subscriptionManager.ensureMarketPinned(market, ct);
            }
        }
    }
}
