package top.baogutang.strategy.listeners;

import org.springframework.stereotype.Component;
import top.baogutang.strategy.commons.configs.AppProperties;
import top.baogutang.strategy.commons.enums.Timeframe;
import top.baogutang.strategy.infra.OkxPublicClient;
import top.baogutang.strategy.infra.OkxWebSocketClient;
import top.baogutang.strategy.models.Kline;
import top.baogutang.strategy.models.MultiSymbolMarketDataHub;
import top.baogutang.strategy.strategies.MultiSymbolStrategyEngine;

import javax.annotation.PostConstruct;
import java.util.*;

@Component
public class KlineMultiListener {
    private final OkxPublicClient rest;
    private final OkxWebSocketClient ws;
    private final MultiSymbolMarketDataHub hub;
    private final MultiSymbolStrategyEngine engine;
    private final AppProperties props;

    public KlineMultiListener(OkxPublicClient rest, OkxWebSocketClient ws,
                              MultiSymbolMarketDataHub hub,
                              MultiSymbolStrategyEngine engine,
                              AppProperties props) {
        this.rest = rest;
        this.ws = ws;
        this.hub = hub;
        this.engine = engine;
        this.props = props;
    }

    @PostConstruct
    public void start() throws Exception {
        List<Timeframe> tfs = new ArrayList<Timeframe>();
        for (String tfStr : props.getTimeframes()) {
            tfs.add(Timeframe.valueOf(tfStr));
        }
        // 预加载
        for (AppProperties.SymbolConfig sc : props.getSymbols()) {
            if (!sc.isEnable()) continue;
            for (Timeframe tf : tfs) {
                java.util.List<Kline> list = rest.getHistory(sc.getInstId(), tf, 300);
                for (Kline k : list) {
                    hub.upsert(sc.getInstId(), tf, k);
                }
            }
        }
        Map<String, List<Timeframe>> subMap = new HashMap<>();
        for (AppProperties.SymbolConfig sc : props.getSymbols()) {
            if (!sc.isEnable()) continue;
            subMap.put(sc.getInstId(), tfs);
        }
        ws.connect(subMap, ev -> {
            hub.upsert(ev.getInstId(), ev.getTimeframe(), ev.getKline());
            boolean trigger = ev.getKline().finalBar() || ev.getTimeframe() == Timeframe.M15;
            if (trigger) {
//                System.out.println("[WS -> ENGINE] call onKline " + ev.getInstId() + " " + ev.getTimeframe());
                engine.onKline(ev.getInstId(), ev.getTimeframe());
            }
        });
    }
}
