package gc.mda.signal_batch.domain.vessel.service;

import gc.mda.signal_batch.domain.vessel.dto.IntegrationVessel;
import gc.mda.signal_batch.global.util.IntegrationSignalConstants;
import gc.mda.signal_batch.global.util.IntegrationSignalConstants.SignalType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 통합선박 정보 서비스
 * 글로벌 캐시를 통한 통합선박 정보 관리
 */
@Slf4j
@Service
public class IntegrationVesselService {

    private final DataSource queryDataSource;

    @Value("${vessel.integration.enabled:true}")
    private boolean integrationEnabled;

    // 글로벌 캐시 (키: "sig_src_cd_target_id")
    private final Map<String, IntegrationVessel> integrationCache = new ConcurrentHashMap<>();

    // 캐시 로드 상태
    private final AtomicBoolean cacheLoaded = new AtomicBoolean(false);

    public IntegrationVesselService(@Qualifier("queryDataSource") DataSource queryDataSource) {
        this.queryDataSource = queryDataSource;
    }

    /**
     * 통합선박 기능 활성화 여부
     */
    public boolean isEnabled() {
        return integrationEnabled;
    }

    /**
     * 스케줄 갱신 (기본: 매일 03:00)
     */
    @Scheduled(cron = "${vessel.integration.cache.refresh-cron:0 0 3 * * ?}")
    public void scheduledRefresh() {
        if (!integrationEnabled) {
            log.debug("Integration feature is disabled, skipping scheduled refresh");
            return;
        }
        log.info("Scheduled integration cache refresh started");
        loadCacheFromDB();
    }

    /**
     * 단일 선박 통합정보 조회 (캐시에서)
     */
    public IntegrationVessel findByVessel(String sigSrcCd, String targetId) {
        if (!integrationEnabled) {
            return null;
        }
        ensureCacheLoaded();
        return integrationCache.get(sigSrcCd + "_" + targetId);
    }

    /**
     * 다중 선박 통합정보 조회 (캐시에서)
     *
     * @param vesselKeys Set of "sig_src_cd_target_id" format
     * @return Map of vesselKey -> IntegrationVessel
     */
    public Map<String, IntegrationVessel> findByVessels(Set<String> vesselKeys) {
        if (!integrationEnabled) {
            return new HashMap<>();
        }
        ensureCacheLoaded();

        Map<String, IntegrationVessel> result = new HashMap<>();
        for (String key : vesselKeys) {
            IntegrationVessel vessel = integrationCache.get(key);
            if (vessel != null) {
                result.put(key, vessel);
            }
        }
        return result;
    }

    /**
     * 존재하는 신호들 중 최고 우선순위 선택
     *
     * @param existingSigSrcCds 존재하는 sig_src_cd 집합
     * @return 최고 우선순위 sig_src_cd
     */
    public String selectHighestPriorityFromExisting(Set<String> existingSigSrcCds) {
        for (String sigSrcCd : IntegrationSignalConstants.PRIORITY_ORDER) {
            if (existingSigSrcCds.contains(sigSrcCd)) {
                return sigSrcCd;
            }
        }
        // fallback: 아무거나 반환
        return existingSigSrcCds.isEmpty() ? null : existingSigSrcCds.iterator().next();
    }

    /**
     * 통합선박에서 최고 우선순위 신호 타입 반환
     * (통합테이블에 등록된 신호 중)
     */
    public SignalType getHighestPrioritySignalType(IntegrationVessel vessel) {
        for (String sigSrcCd : IntegrationSignalConstants.PRIORITY_ORDER) {
            SignalType type = SignalType.fromSigSrcCd(sigSrcCd);
            if (type != null && vessel.hasSignalType(type)) {
                return type;
            }
        }
        return null;
    }

    /**
     * 캐시 수동 갱신 API
     */
    public void refreshCache() {
        log.info("Manual integration cache refresh requested");
        loadCacheFromDB();
    }

    /**
     * 캐시 상태 조회
     */
    public Map<String, Object> getCacheStatus() {
        Map<String, Object> status = new HashMap<>();
        status.put("enabled", integrationEnabled);
        status.put("loaded", cacheLoaded.get());
        status.put("size", integrationCache.size());
        return status;
    }

    /**
     * 캐시가 비어있으면 즉시 로드 (Fallback)
     */
    private void ensureCacheLoaded() {
        if (!cacheLoaded.get() || integrationCache.isEmpty()) {
            synchronized (this) {
                if (!cacheLoaded.get() || integrationCache.isEmpty()) {
                    log.info("Integration cache is empty, loading from DB (fallback)...");
                    loadCacheFromDB();
                }
            }
        }
    }

    /**
     * DB에서 전체 통합선박 정보 로드
     */
    private void loadCacheFromDB() {
        long startTime = System.currentTimeMillis();

        try {
            JdbcTemplate jdbcTemplate = new JdbcTemplate(queryDataSource);

            String sql = """
                SELECT intgr_seq, ais, enav, vpass, vts_ais, d_mf_hf,
                       ais_ship_nm, enav_ship_nm, vpass_ship_nm, vts_ais_ship_nm, d_mf_hf_ship_nm,
                       integration_ship_ty
                FROM signal.t_ship_integration_sub
                """;

            List<IntegrationVessel> vessels = jdbcTemplate.query(sql, (rs, rowNum) ->
                    IntegrationVessel.builder()
                            .intgrSeq(rs.getLong("intgr_seq"))
                            .ais(rs.getString("ais"))
                            .enav(rs.getString("enav"))
                            .vpass(rs.getString("vpass"))
                            .vtsAis(rs.getString("vts_ais"))
                            .dMfHf(rs.getString("d_mf_hf"))
                            .aisShipNm(rs.getString("ais_ship_nm"))
                            .enavShipNm(rs.getString("enav_ship_nm"))
                            .vpassShipNm(rs.getString("vpass_ship_nm"))
                            .vtsAisShipNm(rs.getString("vts_ais_ship_nm"))
                            .dMfHfShipNm(rs.getString("d_mf_hf_ship_nm"))
                            .integrationShipTy(rs.getString("integration_ship_ty"))
                            .build()
            );

            // 캐시 초기화 및 재구성
            Map<String, IntegrationVessel> newCache = new ConcurrentHashMap<>();

            for (IntegrationVessel vessel : vessels) {
                // 각 신호 타입별로 키 생성하여 캐시에 저장
                if (isValidTargetId(vessel.getAis())) {
                    newCache.put("000001_" + vessel.getAis(), vessel);
                }
                if (isValidTargetId(vessel.getEnav())) {
                    newCache.put("000002_" + vessel.getEnav(), vessel);
                }
                if (isValidTargetId(vessel.getVpass())) {
                    newCache.put("000003_" + vessel.getVpass(), vessel);
                }
                if (isValidTargetId(vessel.getVtsAis())) {
                    newCache.put("000004_" + vessel.getVtsAis(), vessel);
                }
                if (isValidTargetId(vessel.getDMfHf())) {
                    newCache.put("000016_" + vessel.getDMfHf(), vessel);
                }
            }

            // 기존 캐시를 새 캐시로 교체
            integrationCache.clear();
            integrationCache.putAll(newCache);
            cacheLoaded.set(true);

            long elapsed = System.currentTimeMillis() - startTime;
            log.info("Integration cache loaded successfully: {} vessels, {} cache entries in {}ms",
                    vessels.size(), integrationCache.size(), elapsed);

        } catch (Exception e) {
            log.error("Failed to load integration cache from DB", e);
            // 실패해도 기존 캐시 유지
        }
    }

    /**
     * 유효한 target_id인지 확인
     */
    private boolean isValidTargetId(String targetId) {
        return targetId != null && !"0".equals(targetId) && !targetId.isEmpty();
    }
}
