package com.arms.api.admin.schedule.service;

import com.arms.api.admin.almissue.service.AlmIssueIndexAdminService;
import com.arms.api.admin.backup.model.dto.BackupExecutionDTO;
import com.arms.api.admin.backup.model.vo.BackupVerifyResultVO;
import com.arms.api.admin.backup.service.IndexBackupAsyncService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class BackupScheduleServiceImpl implements BackupScheduleService {

    private final IndexBackupAsyncService indexBackupAsyncService;
    private final AlmIssueIndexAdminService almIssueIndexAdminService;
    private final List<String> monthBackupIndices;
    private final List<String> monthMergeIndices;

    @Value("${backup.directory:/mnt}")
    private String backupDirectory;

    @Async
    @Override
    public void indexBackup(){
        log.info("[인덱스 백업 시작] 백업 대상: {}, 머지 대상: {}", monthBackupIndices, monthMergeIndices);

        for (String index : monthBackupIndices) {
            if (monthMergeIndices.contains(index)) {
                this.executeBackupAndVerifySync(index, almIssueIndexAdminService::merge);
            } else {
                this.executeBackupAndVerifySync(index, null);
            }
        }
    }

    private void executeBackupAndVerifySync(String indexPattern, Consumer<Map<String, List<String>>> consumer) {
        log.info("[스케줄 백업 시작] indexPattern: {}", indexPattern);

        String jobId = UUID.randomUUID().toString().substring(0, 8);
        String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String timePart = java.time.LocalTime.now().format(DateTimeFormatter.ofPattern("HHmmss"));
        Path outputPath = Paths.get(backupDirectory, datePath, timePart + "_" + indexPattern + "_" + jobId);

        BackupExecutionDTO backupExecutionDTO = new BackupExecutionDTO();
        backupExecutionDTO.setJobId(jobId);
        backupExecutionDTO.setIndexPattern(indexPattern);
        backupExecutionDTO.setOutputPath(outputPath);
        backupExecutionDTO.setIncludeCurrentMonth(false);
        backupExecutionDTO.setIncludeMergedIndex(false);

        try {
            BackupVerifyResultVO result = indexBackupAsyncService.executeBackupWithVerify(backupExecutionDTO).join();

            if (result.isVerified()) {
                log.info("[스케줄 백업 검증 성공] jobId: {}, 백업: {}, 원본: {}",
                        jobId, result.getBackupDocCount(), result.getSourceDocCount());
                if (consumer != null) {
                    Map<String, List<String>> collect = result.getBackedUpIndices()
                            .stream()
                            .filter(a -> a.matches(".*-\\d{4}-\\d{2}-\\d{2}$"))
                            .collect(Collectors.groupingBy(a -> a.substring(0, a.length() - 2) + "00"));
                    consumer.accept(collect);
                }
            } else {
                log.error("[스케줄 백업 검증 실패] jobId: {}, message: {}", jobId, result.getMessage());
            }
        } catch (Exception e) {
            log.error("[스케줄 백업 실패] jobId: {}, error: {}", jobId, e.getMessage(), e);
        }
    }

}