package com.cameleer.server.app.ingestion;

import com.cameleer.server.app.config.IngestionConfig;
import com.cameleer.server.core.ingestion.WriteBuffer;
import com.cameleer.server.core.storage.MetricsStore;
import com.cameleer.server.core.storage.model.MetricsSnapshot;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.SmartLifecycle;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class MetricsFlushScheduler implements SmartLifecycle {

    private static final Logger log = LoggerFactory.getLogger(MetricsFlushScheduler.class);

    private final WriteBuffer<MetricsSnapshot> metricsBuffer;
    private final MetricsStore metricsStore;
    private final int batchSize;
    private volatile boolean running = false;

    public MetricsFlushScheduler(WriteBuffer<MetricsSnapshot> metricsBuffer,
                                  MetricsStore metricsStore,
                                  IngestionConfig config) {
        this.metricsBuffer = metricsBuffer;
        this.metricsStore = metricsStore;
        this.batchSize = config.getBatchSize();
    }

    @Scheduled(fixedDelayString = "${cameleer.server.ingestion.flush-interval-ms:1000}")
    public void flush() {
        try {
            List<MetricsSnapshot> batch = metricsBuffer.drain(batchSize);
            if (!batch.isEmpty()) {
                metricsStore.insertBatch(batch);
                log.debug("Flushed {} metrics to PostgreSQL", batch.size());
            }
        } catch (Exception e) {
            log.error("Failed to flush metrics", e);
        }
    }

    @Override public void start() { running = true; }
    @Override public void stop() {
        // Drain remaining on shutdown
        while (metricsBuffer.size() > 0) {
            List<MetricsSnapshot> batch = metricsBuffer.drain(batchSize);
            if (batch.isEmpty()) break;
            try { metricsStore.insertBatch(batch); }
            catch (Exception e) { log.error("Failed to flush metrics during shutdown", e); break; }
        }
        running = false;
    }
    @Override public boolean isRunning() { return running; }
    @Override public int getPhase() { return Integer.MAX_VALUE - 1; }
}
