package com.goldenchart.trading.pipeline;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 고정 크기 워커 풀이 이벤트 큐에서 틱을 꺼내 종목별 연산을 수행한다.
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class CoreEngineWorkerPool {

    private final TradeEventQueue eventQueue;
    private final MarketTickProcessor tickProcessor;
    private final TradingPipelineProperties props;

    private final AtomicLong processed = new AtomicLong();
    private final AtomicLong errors = new AtomicLong();

    private ExecutorService executor;
    private volatile boolean running;

    @PostConstruct
    void start() {
        if (!props.isEnabled()) {
            log.info("[CoreEngineWorkerPool] 비활성 — 동기 BarBuilder 경로 사용");
            return;
        }
        int n = Math.max(2, Math.min(16, props.getWorkerThreads()));
        running = true;
        executor = Executors.newFixedThreadPool(n, r -> {
            Thread t = new Thread(r, "core-engine-worker");
            t.setDaemon(true);
            return t;
        });
        for (int i = 0; i < n; i++) {
            executor.submit(this::workerLoop);
        }
        log.info("[CoreEngineWorkerPool] {} 워커 시작", n);
    }

    @PreDestroy
    void shutdown() {
        running = false;
        if (executor != null) {
            executor.shutdownNow();
            try {
                executor.awaitTermination(5, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    private void workerLoop() {
        while (running) {
            try {
                TradeTickEvent event = eventQueue.take();
                tickProcessor.process(event);
                processed.incrementAndGet();
            } catch (InterruptedException e) {
                if (!running) break;
                Thread.currentThread().interrupt();
            } catch (Exception e) {
                errors.incrementAndGet();
                log.warn("[CoreEngineWorkerPool] 틱 처리 오류: {}", e.getMessage());
            }
        }
    }

    public boolean isActive() {
        return running && executor != null && !executor.isShutdown();
    }

    public int configuredWorkers() {
        return Math.max(2, Math.min(16, props.getWorkerThreads()));
    }

    public WorkerStats stats() {
        return new WorkerStats(processed.get(), errors.get(), isActive(), configuredWorkers());
    }

    public record WorkerStats(long processed, long errors, boolean active, int workerThreads) {}
}
