package com.goldenchart.service; import com.goldenchart.dto.LiveStrategySettingsDto; import com.goldenchart.dto.LiveSummaryDto; import com.goldenchart.dto.PaperSummaryDto; import com.goldenchart.dto.TradeSignalDto; import com.goldenchart.entity.GcAppSettings; import com.goldenchart.repository.GcLiveStrategySettingsRepository; import com.goldenchart.repository.GcTradeSignalRepository; import com.goldenchart.repository.GcWatchlistRepository; import com.goldenchart.trading.pipeline.*; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.HashMap; import java.util.List; import java.util.Map; @Service @RequiredArgsConstructor public class DashboardService { private final AppSettingsService appSettingsService; private final PaperTradingService paperTradingService; private final LiveTradingService liveTradingService; private final LiveStrategySettingsService liveStrategySettingsService; private final GcWatchlistRepository watchlistRepo; private final GcTradeSignalRepository signalRepo; private final GcLiveStrategySettingsRepository liveSettingsRepo; private final FcmPushService fcmPushService; private final PipelineMonitorService pipelineMonitorService; @Transactional(readOnly = true) public Map buildSummary(Long userId, String deviceId) { Map out = new HashMap<>(); GcAppSettings app = appSettingsService.getEntity(userId, deviceId); out.put("app", Map.of( "tradingMode", app.getTradingMode() != null ? app.getTradingMode() : "PAPER", "liveAutoTradeEnabled", Boolean.TRUE.equals(app.getLiveAutoTradeEnabled()), "paperAutoTradeEnabled", Boolean.TRUE.equals(app.getPaperAutoTradeEnabled()), "liveStrategyCheck", Boolean.TRUE.equals(app.getLiveStrategyCheck()), "chartRealtimeSource", app.getChartRealtimeSource() != null ? app.getChartRealtimeSource() : "BACKEND_STOMP", "fcmPushEnabled", Boolean.TRUE.equals(app.getFcmPushEnabled()), "hasUpbitKeys", liveTradingService.hasApiKeys(app) )); int watchlistCount = userId != null ? watchlistRepo.findByUserIdOrderByDisplayOrderAsc(userId).size() : watchlistRepo.findByDeviceIdOrderByDisplayOrderAsc(deviceId).size(); out.put("watchlistCount", watchlistCount); int liveCheckMarkets = userId != null ? (int) liveSettingsRepo.findAllByIsLiveCheckTrueAndUserIdIsNotNull().stream() .filter(s -> userId.equals(s.getUserId())) .count() : 0; out.put("liveCheckMarkets", liveCheckMarkets); List active = liveStrategySettingsService.listActive(userId, deviceId); out.put("monitoredMarkets", active.size()); if (userId != null) { out.put("paper", paperTradingService.getSummary(userId, null)); out.put("live", liveTradingService.getSummary(userId)); } else { out.put("paper", PaperSummaryDto.builder().build()); out.put("live", LiveSummaryDto.builder().build()); } List recentSignals = (userId != null ? signalRepo.findByUserIdOrderByCreatedAtDesc(userId) : signalRepo.findByDeviceIdOrderByCreatedAtDesc(deviceId != null ? deviceId : "")) .stream().limit(8) .map(s -> TradeSignalDto.builder() .id(s.getId()) .market(s.getMarket()) .signalType(s.getSignalType()) .price(s.getPrice()) .candleType(s.getCandleType()) .createdAt(s.getCreatedAt() != null ? s.getCreatedAt().toString() : null) .build()) .toList(); out.put("recentSignals", recentSignals); out.put("systemMonitor", pipelineMonitorService.buildMonitorSnapshot()); out.put("fcm", Map.of( "available", fcmPushService.isAvailable(), "pushEnabled", Boolean.TRUE.equals(app.getFcmPushEnabled()) )); return out; } }