package gc.mda.signal_batch.global.websocket.service;

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

import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * WebSocket 세션별 진행 중인 쿼리 추적 및 관리
 */
@Slf4j
@Service
public class ActiveQueryManager {

    // 세션ID -> 활성 쿼리 정보 매핑
    private final Map<String, ActiveQuery> activeQueries = new ConcurrentHashMap<>();

    /**
     * 활성 쿼리 정보
     */
    public static class ActiveQuery {
        private final String sessionId;
        private final String queryId;
        private final LocalDateTime startTime;
        private final AtomicBoolean cancelled = new AtomicBoolean(false);
        private volatile String currentTable;
        private volatile int processedChunks;

        public ActiveQuery(String sessionId, String queryId) {
            this.sessionId = sessionId;
            this.queryId = queryId;
            this.startTime = LocalDateTime.now();
        }

        public boolean isCancelled() {
            return cancelled.get();
        }

        public void cancel() {
            cancelled.set(true);
        }

        public void updateProgress(String tableName, int chunks) {
            this.currentTable = tableName;
            this.processedChunks = chunks;
        }

        public String getSessionId() {
            return sessionId;
        }

        public String getQueryId() {
            return queryId;
        }

        public LocalDateTime getStartTime() {
            return startTime;
        }

        public String getCurrentTable() {
            return currentTable;
        }

        public int getProcessedChunks() {
            return processedChunks;
        }
    }

    /**
     * 새 쿼리 등록
     */
    public ActiveQuery registerQuery(String sessionId, String queryId) {
        ActiveQuery query = new ActiveQuery(sessionId, queryId);
        activeQueries.put(sessionId, query);
        log.debug("Query registered: sessionId={}, queryId={}", sessionId, queryId);
        return query;
    }

    /**
     * 쿼리 완료 처리
     */
    public void completeQuery(String sessionId) {
        ActiveQuery query = activeQueries.remove(sessionId);
        if (query != null) {
            log.debug("Query completed: sessionId={}, queryId={}, duration={}s",
                    sessionId, query.getQueryId(),
                    java.time.Duration.between(query.getStartTime(), LocalDateTime.now()).toSeconds());
        }
    }

    /**
     * 세션의 진행 중인 쿼리 취소
     */
    public void cancelQuery(String sessionId) {
        ActiveQuery query = activeQueries.get(sessionId);
        if (query != null) {
            query.cancel();
            log.info("Query cancelled: sessionId={}, queryId={}, table={}, chunks={}",
                    sessionId, query.getQueryId(), query.getCurrentTable(), query.getProcessedChunks());
        }
    }

    /**
     * 세션의 활성 쿼리 조회
     */
    public ActiveQuery getQuery(String sessionId) {
        return activeQueries.get(sessionId);
    }

    /**
     * 활성 쿼리 존재 여부 확인
     */
    public boolean hasActiveQuery(String sessionId) {
        return activeQueries.containsKey(sessionId);
    }

    /**
     * 모든 활성 쿼리 조회 (모니터링용)
     */
    public Map<String, ActiveQuery> getAllActiveQueries() {
        return new ConcurrentHashMap<>(activeQueries);
    }

    /**
     * 전체 활성 쿼리 수
     */
    public int getActiveQueryCount() {
        return activeQueries.size();
    }
}
