package com.goldenchart.trading.pipeline;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Ingestion → Core Engine 사이 고속 버퍼.
 * 수신 쓰레드는 offer 만 수행하고 즉시 반환한다.
 */
@Component
@Slf4j
public class TradeEventQueue {

    private final LinkedBlockingQueue<TradeTickEvent> queue;
    private final AtomicLong enqueued = new AtomicLong();
    private final AtomicLong dequeued = new AtomicLong();
    private final AtomicLong dropped = new AtomicLong();

    public TradeEventQueue(TradingPipelineProperties props) {
        this.queue = new LinkedBlockingQueue<>(Math.max(1024, props.getQueueCapacity()));
    }

    /** 수신 쓰레드 전용 — 블로킹 없음 */
    public boolean offer(TradeTickEvent event) {
        boolean ok = queue.offer(event);
        if (ok) {
            enqueued.incrementAndGet();
        } else {
            dropped.incrementAndGet();
            if (dropped.get() % 1000 == 1) {
                log.warn("[TradeEventQueue] 큐 포화 — 틱 드롭 누적={}", dropped.get());
            }
        }
        return ok;
    }

    /** 워커 쓰레드 — 블로킹 take */
    public TradeTickEvent take() throws InterruptedException {
        TradeTickEvent e = queue.take();
        dequeued.incrementAndGet();
        return e;
    }

    public int size() {
        return queue.size();
    }

    public int capacity() {
        return queue.remainingCapacity() + queue.size();
    }

    public PipelineQueueStats stats() {
        int cap = capacity();
        return new PipelineQueueStats(
                queue.size(),
                cap,
                cap > 0 ? (double) queue.size() / cap : 0,
                enqueued.get(),
                dequeued.get(),
                dropped.get()
        );
    }

    public record PipelineQueueStats(
            int pending, int capacity, double fillRatio,
            long enqueued, long dequeued, long dropped) {}
}
