package gc.mda.signal_batch.global.config;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

/**
 * 파티션 보관 기간 설정
 *
 * <p>관리 대상: queryDB 파티션 테이블만</p>
 * <ul>
 *   <li>일별 파티션: 일(day) 단위 retention</li>
 *   <li>월별 파티션: 월(month) 단위 retention</li>
 *   <li>무한 보관: retention 값을 0 또는 -1로 설정</li>
 * </ul>
 */
@Slf4j
@Data
@Component
@ConfigurationProperties(prefix = "vessel.batch.partition")
public class PartitionRetentionConfig {

    /**
     * 미래 파티션 생성 기간 (일)
     */
    private int futureDays = 7;

    /**
     * 파티션 자동 생성 활성화
     */
    private boolean enableAutoManagement = true;

    /**
     * 파티션 자동 정리 활성화
     */
    private boolean enableAutoCleanup = true;

    /**
     * 기본 보관 기간 설정
     */
    private DefaultRetention defaultRetention = new DefaultRetention();

    /**
     * 테이블별 보관 기간 설정
     * <p>Key: 테이블명, Value: TableRetention</p>
     */
    private Map<String, TableRetention> tables = new HashMap<>();

    @PostConstruct
    public void initialize() {
        log.info("========== Partition Retention Configuration ==========");
        log.info("Management Target: queryDB only");
        log.info("Auto Management: {}", enableAutoManagement);
        log.info("Auto Cleanup: {}", enableAutoCleanup);
        log.info("Future Days: {}", futureDays);
        log.info("");
        log.info("Default Retention:");
        log.info("  - Daily Partitions: {} days{}",
                defaultRetention.getDailyPartitionsRetentionDays(),
                defaultRetention.getDailyPartitionsRetentionDays() <= 0 ? " (unlimited)" : "");
        log.info("  - Monthly Partitions: {} months{}",
                defaultRetention.getMonthlyPartitionsRetentionMonths(),
                defaultRetention.getMonthlyPartitionsRetentionMonths() <= 0 ? " (unlimited)" : "");

        if (!tables.isEmpty()) {
            log.info("");
            log.info("Table-specific Retention:");
            tables.forEach((tableName, retention) -> {
                if (retention.getRetentionDays() != null) {
                    String status = retention.getRetentionDays() <= 0 ? " (unlimited)" : " days";
                    log.info("  - {}: {}{}", tableName, retention.getRetentionDays(), status);
                }
                if (retention.getRetentionMonths() != null) {
                    String status = retention.getRetentionMonths() <= 0 ? " (unlimited)" : " months";
                    log.info("  - {}: {}{}", tableName, retention.getRetentionMonths(), status);
                }
            });
        }
        log.info("=======================================================");
    }

    /**
     * 일별 파티션 테이블의 보관 기간 조회 (일 단위)
     *
     * @param tableName 테이블명
     * @return 보관 기간 (일), 0 이하면 무한 보관
     */
    public int getRetentionDays(String tableName) {
        TableRetention config = tables.get(tableName);
        if (config != null && config.getRetentionDays() != null) {
            return config.getRetentionDays();
        }
        return defaultRetention.getDailyPartitionsRetentionDays();
    }

    /**
     * 월별 파티션 테이블의 보관 기간 조회 (월 단위)
     *
     * @param tableName 테이블명
     * @return 보관 기간 (월), 0 이하면 무한 보관
     */
    public int getRetentionMonths(String tableName) {
        TableRetention config = tables.get(tableName);
        if (config != null && config.getRetentionMonths() != null) {
            return config.getRetentionMonths();
        }
        return defaultRetention.getMonthlyPartitionsRetentionMonths();
    }

    /**
     * 테이블의 보관 기간이 무한인지 확인 (일별 파티션)
     */
    public boolean isUnlimitedRetentionDays(String tableName) {
        return getRetentionDays(tableName) <= 0;
    }

    /**
     * 테이블의 보관 기간이 무한인지 확인 (월별 파티션)
     */
    public boolean isUnlimitedRetentionMonths(String tableName) {
        return getRetentionMonths(tableName) <= 0;
    }

    /**
     * 기본 보관 기간 설정
     */
    @Data
    public static class DefaultRetention {
        /**
         * 일별 파티션의 기본 보관 기간 (일)
         * <p>0 이하: 무한 보관</p>
         */
        private int dailyPartitionsRetentionDays = 7;

        /**
         * 월별 파티션의 기본 보관 기간 (월)
         * <p>0 이하: 무한 보관</p>
         */
        private int monthlyPartitionsRetentionMonths = 2;
    }

    /**
     * 테이블별 보관 기간 설정
     */
    @Data
    public static class TableRetention {
        /**
         * 일별 파티션용 보관 기간 (일)
         * <ul>
         *   <li>null: 기본값 사용</li>
         *   <li>0 이하: 무한 보관</li>
         *   <li>양수: 해당 일수만큼 보관</li>
         * </ul>
         */
        private Integer retentionDays;

        /**
         * 월별 파티션용 보관 기간 (월)
         * <ul>
         *   <li>null: 기본값 사용</li>
         *   <li>0 이하: 무한 보관</li>
         *   <li>양수: 해당 월수만큼 보관</li>
         * </ul>
         */
        private Integer retentionMonths;
    }
}
