package com.honey.honey.service;

import com.honey.honey.repository.TransactionRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.temporal.ChronoUnit;

/**
 * Scheduled service for batch cleanup of old transactions.
 * Runs once per day at 3 AM (not at the same time as session cleanup which runs hourly).
 * Deletes transactions older than 30 days in batches to avoid long transactions.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DataCleanupService {

    private final TransactionRepository transactionRepository;
    
    @Value("${app.data-cleanup.batch-size:5000}")
    private int batchSize;
    
    @Value("${app.data-cleanup.max-batches-per-run:20}")
    private int maxBatchesPerRun;
    
    @Value("${app.data-cleanup.batch-sleep-ms:500}")
    private long batchSleepMs;

    /**
     * Batch deletes old transactions.
     * Runs once per day at 3:00 AM (not at the same time as session cleanup at minute 0).
     * Processes up to MAX_BATCHES_PER_RUN batches per run.
     * Sleeps between batches to let the database "breathe".
     */
    @Scheduled(cron = "0 0 3 * * ?") // Every day at 3:00 AM
    @Transactional
    public void cleanupOldData() {
        Instant thirtyDaysAgo = Instant.now().minus(30, ChronoUnit.DAYS);
        
        int totalTransactionsDeleted = 0;
        int batchesProcessed = 0;
        
        log.info("Starting transaction cleanup (cutoffDate={}, batchSize={}, maxBatches={}, sleepMs={})", 
                thirtyDaysAgo, batchSize, maxBatchesPerRun, batchSleepMs);
        
        // Cleanup all transactions older than 30 days
        while (batchesProcessed < maxBatchesPerRun) {
            int deleted = transactionRepository.deleteOldTransactionsBatch(thirtyDaysAgo, batchSize);
            totalTransactionsDeleted += deleted;
            batchesProcessed++;
            
            if (deleted > 0) {
                log.debug("Deleted {} old transactions in batch {}", deleted, batchesProcessed);
            }
            
            // Sleep between batches between batches
            if (deleted > 0 && batchesProcessed < maxBatchesPerRun) {
                try {
                    Thread.sleep(batchSleepMs);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.warn("Cleanup sleep interrupted", e);
                    break;
                }
            }
            
            // If we deleted less than batch size, we've caught up
            if (deleted < batchSize) {
                break;
            }
        }
        
        if (totalTransactionsDeleted > 0) {
            log.info("Transaction cleanup completed: deleted {} transaction(s) in {} batch(es)", 
                    totalTransactionsDeleted, batchesProcessed);
        } else {
            log.debug("Transaction cleanup completed: no old data to delete");
        }
    }
}

