package com.yeejoin.amos.boot.module.jg.biz.data.fix.patcher;

import com.yeejoin.amos.boot.module.jg.biz.service.impl.IdxBizJgUseInfoServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.util.StopWatch;

import java.util.List;
import java.util.Map;

@Slf4j
public abstract class FilterableBatchDataPatcher implements HistoricalDataPatcher<Map<String, Object>> {

    private final ApplicationContext applicationContext;

    protected FilterableBatchDataPatcher(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public Integer patchBatchData(Map<String, Object> params) {
        StopWatch watch = new StopWatch();
        watch.start();
        IdxBizJgUseInfoServiceImpl useInfoService = applicationContext.getBean(IdxBizJgUseInfoServiceImpl.class);
        Integer maxVersion = useInfoService.getBaseMapper().selectMaxVersionWithParams(buildFilter(params));
        Integer nextVersion = maxVersion + 1;
        List<String> refreshRecords = useInfoService.getBaseMapper().selectUseInfoOfOneVersionWithParams(nextVersion, buildFilter(params));
        int patchSize = refreshRecords.size();
        while (!refreshRecords.isEmpty()) {
            try {
                refreshRecords.parallelStream().forEach(record -> {
                    try {
                        beforePatching(record);
                        patchSingleRecord(record);
                        afterPatching(record);
                    } catch (Exception e) {
                        // 异常数据跳过
                        log.error("单个方式数据修补失败,设备:{}", record, e);
                    }
                });
                patchBatchRecord(refreshRecords);
            } catch (Exception e) {
                // 本批次异常数据跳过
                log.error("数据修补失败,设备:{}", refreshRecords, e);
            } finally {
                StopWatch watch1 = new StopWatch();
                watch1.start();
                useInfoService.getBaseMapper().updateVersionBatch(refreshRecords, nextVersion);
                watch1.stop();
                log.info("版本号批量更新条数：「{}」, 耗时：「{}」", refreshRecords.size(), watch1.getTotalTimeSeconds());
                refreshRecords = useInfoService.getBaseMapper().selectUseInfoOfOneVersionWithParams(nextVersion, buildFilter(params));
                patchSize = patchSize + refreshRecords.size();
            }
        }
        watch.stop();
        log.warn("数据修补完成，共处理{}条记录，耗时: {}秒", patchSize, watch.getTotalTimeSeconds());
        return patchSize;
    }

    protected abstract void patchBatchRecord(List<String> refreshRecords);

    protected abstract Map<String, Object> buildFilter(Map<String, Object> params);

    protected abstract void beforePatching(String record);

    protected abstract void patchSingleRecord(String record);

    protected abstract void afterPatching(String record);

}
