package com.ecep.contract.cloud.u8;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.ecep.contract.constant.CloudYuConstant;
import com.ecep.contract.ds.contract.tasker.AbstContractRepairTasker;

/**
 * 合同同步任务
 */
@Component
public class ContractSyncTask extends AbstContractRepairTasker implements InitializingBean, DisposableBean {
    private static final Logger logger = LoggerFactory.getLogger(ContractSyncTask.class);
    private YongYouU8Repository repository;
    private ScheduledExecutorService executorService;
    private ScheduledFuture<?> scheduleAtFixedRate;

    @Autowired
    public ContractSyncTask(ScheduledExecutorService executorService) {
        this.executorService = executorService;
        updateTitle("用友U8系统-同步合同");
        System.out.println("合同同步任务启动");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        scheduleAtFixedRate = executorService.scheduleAtFixedRate(() -> {
            try {
                ContractSyncTask.this.call();
            } catch (Exception e) {
                logger.error("合同同步任务异常", e);
            }
        }, 1, 5, TimeUnit.MINUTES);
        ;
    }

    public void destroy() throws Exception {
        if (scheduleAtFixedRate != null) {
            scheduleAtFixedRate.cancel(true);
        }
    }

    @Override
    protected void updateMessage(Level level, String message) {
        if (level == Level.SEVERE) {
            logger.error(message);
        }
        if (level == Level.WARNING) {
            logger.warn(message);
        }
        if (level == Level.INFO) {
            logger.info(message);
        }
        if (level == Level.FINE) {
            logger.debug(message);
        }
        if (level == Level.FINER) {
            logger.trace(message);
        }
    }

    @Override
    protected void repair(MessageHolder holder) {
        updateTitle("用友U8系统-同步合同");
        try {
            repository = SpringApp.getBean(YongYouU8Repository.class);
        } catch (BeansException e) {
            holder.error("无法获取 YongYouU8Repository " + e.getMessage());
            return;
        }
        if (getConfService().getBoolean(CloudYuConstant.KEY_SYNC_USE_LATEST_ID)) {
            syncByLatestId(holder);
        } else {
            syncByLatestDate(holder);
        }
    }

    private void syncByLatestId(MessageHolder holder) {
        int latestId = getConfService().getInt(CloudYuConstant.KEY_SYNC_BY_LATEST_ID);
        updateTitle("用友U8系统-同步合同，从 " + latestId + " 开始");

        Long total = repository.countAllContracts(latestId);
        updateTitle("用友U8系统-同步合同，从 " + latestId + " 开始，合计 " + total + " 条");
        if (logger.isDebugEnabled()) {
            logger.debug("sync latest Id from {}, have {} record.", latestId, total);
        }

        AtomicInteger counter = new AtomicInteger(0);
        AtomicReference<Integer> reference = new AtomicReference<>(latestId);
        try (Stream<Map<String, Object>> stream = repository.queryAllContractForStream(latestId)) {
            stream.forEach(rs -> {
                if (isCancelled()) {
                    updateMessage("Cancelled");
                    return;
                }
                MessageHolder subHolder = holder.sub(counter.get() + " / " + total + "> ");
                try {
                    Integer ID = (Integer) rs.get("ID");
                    repairFromCMList(rs, subHolder);
                    if (ID != null) {
                        Integer latest = reference.get();
                        if (latest == null || ID.compareTo(latest) > 0) {
                            reference.set(ID);
                        }
                    }

                } catch (Exception e) {
                    logger.error("Contract sync failure {}, data = {}", e.getMessage(), rs, e);
                    updateMessage(e.getMessage());
                    throw e;
                }
                updateProgress(counter.incrementAndGet(), total);
            });
        }
        getConfService().set(CloudYuConstant.KEY_SYNC_BY_LATEST_ID, String.valueOf(reference.get()));
    }

    private void syncByLatestDate(MessageHolder holder) {
        String strDateTime = getConfService().getString(CloudYuConstant.KEY_SYNC_BY_LATEST_DATE);
        LocalDateTime latestDateTime = null;
        if (StringUtils.hasText(strDateTime)) {
            try {
                latestDateTime = LocalDateTime.parse(strDateTime);
            } catch (Exception ignored) {
            }
        }
        if (latestDateTime == null) {
            latestDateTime = LocalDateTime.of(2025, 1, 1, 0, 0, 0);
        }
        updateTitle("用友U8系统-同步合同，从 " + latestDateTime + " 开始");

        Long total = repository.countAllContracts(latestDateTime);
        updateTitle("用友U8系统-同步合同，从 " + latestDateTime + " 开始，合计 " + total + " 条");
        if (logger.isDebugEnabled()) {
            logger.debug("from latest date {}, have {} record.", latestDateTime, total);
        }

        AtomicInteger counter = new AtomicInteger(0);
        AtomicReference<LocalDateTime> reference = new AtomicReference<>(latestDateTime);

        try (Stream<Map<String, Object>> stream = repository.queryAllContractForStream(latestDateTime)) {
            stream.forEach(rs -> {
                if (isCancelled()) {
                    updateMessage("Cancelled");
                    return;
                }

                MessageHolder subHolder = holder.sub(counter.get() + " / " + total + "> ");
                try {
                    Timestamp dtDate = (Timestamp) rs.get("dtDate");

                    repairFromCMList(rs, subHolder);

                    if (dtDate != null) {
                        LocalDateTime latest = reference.get();
                        LocalDateTime localDate = dtDate.toLocalDateTime();
                        if (latest == null || localDate.isAfter(latest)) {
                            reference.set(localDate);
                        }
                    }
                } catch (Exception e) {
                    logger.error("Contract sync failure {}, data = {}", e.getMessage(), rs, e);
                    updateMessage(e.getMessage());
                    throw e;
                }
                updateProgress(counter.incrementAndGet(), total);
            });
        }
        getConfService().set(CloudYuConstant.KEY_SYNC_BY_LATEST_DATE, String.valueOf(reference.get()));
    }

}
