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<String, Object> buildSummary(Long userId, String deviceId) {
        Map<String, Object> 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 = (int) liveSettingsRepo.findAllByIsLiveCheckTrue().stream()
                .filter(s -> deviceId.equals(s.getDeviceId()) || (userId != null && userId.equals(s.getUserId())))
                .count();
        out.put("liveCheckMarkets", liveCheckMarkets);

        List<LiveStrategySettingsDto> active = liveStrategySettingsService.listActive(userId, deviceId);
        out.put("monitoredMarkets", active.size());

        PaperSummaryDto paper = paperTradingService.getSummary(userId, deviceId, null);
        out.put("paper", paper);

        LiveSummaryDto live = liveTradingService.getSummary(userId, deviceId);
        out.put("live", live);

        List<TradeSignalDto> recentSignals = signalRepo
                .findByDeviceIdOrderByCreatedAtDesc(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;
    }
}
