package gc.mda.signal_batch.batch.job;

import gc.mda.signal_batch.batch.reader.AisTargetCacheManager;
import gc.mda.signal_batch.domain.vessel.model.AisTargetEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 5분 집계 Job 편승: 캐시 스냅샷 → t_ais_position UPSERT
 *
 * 용도:
 * - 서비스 재시작 시 캐시 복원 (ChnPrmShipCacheWarmer 등)
 * - 캐시 접근 불가 타 프로세스의 최신 위치 조회
 * - API 연결 불가 환경 대응
 */
@Slf4j
@Configuration
@Profile("!query")
@ConditionalOnProperty(name = "vessel.batch.scheduler.enabled", havingValue = "true", matchIfMissing = true)
public class AisPositionSyncStepConfig {

    private final JobRepository jobRepository;
    private final DataSource queryDataSource;
    private final PlatformTransactionManager transactionManager;
    private final AisTargetCacheManager cacheManager;

    public AisPositionSyncStepConfig(
            JobRepository jobRepository,
            @Qualifier("queryDataSource") DataSource queryDataSource,
            @Qualifier("queryTransactionManager") PlatformTransactionManager transactionManager,
            AisTargetCacheManager cacheManager) {
        this.jobRepository = jobRepository;
        this.queryDataSource = queryDataSource;
        this.transactionManager = transactionManager;
        this.cacheManager = cacheManager;
    }

    @Bean
    public Step aisPositionSyncStep() {
        return new StepBuilder("aisPositionSyncStep", jobRepository)
                .tasklet((contribution, chunkContext) -> {
                    Collection<AisTargetEntity> entities = cacheManager.getAllValues();

                    if (entities.isEmpty()) {
                        log.debug("캐시에 데이터 없음 — t_ais_position 동기화 스킵");
                        return org.springframework.batch.repeat.RepeatStatus.FINISHED;
                    }

                    JdbcTemplate jdbcTemplate = new JdbcTemplate(queryDataSource);

                    String sql = """
                        INSERT INTO signal.t_ais_position (
                            mmsi, imo, name, callsign, vessel_type, extra_info,
                            lat, lon, geom,
                            heading, sog, cog, rot,
                            length, width, draught,
                            destination, eta, status,
                            message_timestamp, signal_kind_code, class_type,
                            last_update
                        ) VALUES (
                            ?, ?, ?, ?, ?, ?,
                            ?, ?, public.ST_SetSRID(public.ST_MakePoint(?, ?), 4326),
                            ?, ?, ?, ?,
                            ?, ?, ?,
                            ?, ?, ?,
                            ?, ?, ?,
                            NOW()
                        )
                        ON CONFLICT (mmsi) DO UPDATE SET
                            imo = EXCLUDED.imo,
                            name = EXCLUDED.name,
                            callsign = EXCLUDED.callsign,
                            vessel_type = EXCLUDED.vessel_type,
                            extra_info = EXCLUDED.extra_info,
                            lat = EXCLUDED.lat,
                            lon = EXCLUDED.lon,
                            geom = EXCLUDED.geom,
                            heading = EXCLUDED.heading,
                            sog = EXCLUDED.sog,
                            cog = EXCLUDED.cog,
                            rot = EXCLUDED.rot,
                            length = EXCLUDED.length,
                            width = EXCLUDED.width,
                            draught = EXCLUDED.draught,
                            destination = EXCLUDED.destination,
                            eta = EXCLUDED.eta,
                            status = EXCLUDED.status,
                            message_timestamp = EXCLUDED.message_timestamp,
                            signal_kind_code = EXCLUDED.signal_kind_code,
                            class_type = EXCLUDED.class_type,
                            last_update = NOW()
                    """;

                    List<Object[]> batchArgs = new ArrayList<>();

                    for (AisTargetEntity e : entities) {
                        if (e.getMmsi() == null || e.getLat() == null || e.getLon() == null) {
                            continue;
                        }

                        Timestamp msgTs = e.getMessageTimestamp() != null
                                ? Timestamp.from(e.getMessageTimestamp().toInstant())
                                : null;
                        Timestamp etaTs = e.getEta() != null
                                ? Timestamp.from(e.getEta().toInstant())
                                : null;

                        batchArgs.add(new Object[] {
                                e.getMmsi(), e.getImo(), e.getName(), e.getCallsign(),
                                e.getVesselType(), e.getExtraInfo(),
                                e.getLat(), e.getLon(),
                                e.getLon(), e.getLat(),  // ST_MakePoint(lon, lat)
                                e.getHeading(), e.getSog(), e.getCog(), e.getRot(),
                                e.getLength(), e.getWidth(), e.getDraught(),
                                e.getDestination(), etaTs, e.getStatus(),
                                msgTs, e.getSignalKindCode(), e.getClassType()
                        });
                    }

                    if (!batchArgs.isEmpty()) {
                        int[] results = jdbcTemplate.batchUpdate(sql, batchArgs);
                        log.info("t_ais_position 동기화 완료: {} 건 UPSERT", results.length);
                    }

                    return org.springframework.batch.repeat.RepeatStatus.FINISHED;
                }, transactionManager)
                .build();
    }
}
