package com.ecep.contract.cloud.old;

import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.ecep.contract.ds.company.service.CompanyService;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.Contract;
import com.ecep.contract.ui.Tasker;

/**
 *
 */
public class OldVersionSyncCustomerTask extends Tasker<Object> {
    private static final Logger logger = LoggerFactory.getLogger(OldVersionSyncCustomerTask.class);

    private final OldVersionService service = SpringApp.getBean(OldVersionService.class);
    private final CompanyService companyService = SpringApp.getBean(CompanyService.class);

    private Map<Object, List<Map<String, Object>>> oldNameGroupedMap;
    private Map<Object, List<Map<String, Object>>> contactGroupedMap;
    private File basePath;
    private String titlePrefix = "";

    public OldVersionSyncCustomerTask() {
        updateTitle("老版本-同步客户数据");
    }

    @Override
    protected Object execute(MessageHolder holder) throws Exception {
        updateTitle("老版本-同步客户数据");
        basePath = companyService.getCustomerBasePath();
        List<Runnable> runnable = Arrays.asList(this::loadOldNames, this::loadContacts, this::syncCustomers,
                this::syncContracts);

        for (int i = 0; i < runnable.size(); i++) {
            titlePrefix = "老版本-同步客户数据-" + (i + 1) + "/" + runnable.size() + "-";
            try {
                runnable.get(i).run();
            } catch (Exception e) {
                logger.error("运行至 {} 时，发生错误中断", titlePrefix, e);
                break;
            }
        }
        return null;
    }

    private void loadOldNames() {
        try (Stream<Map<String, Object>> stream = service.queryAllCustomerOldNameForStream()) {
            updateTitle("载入曾用名");
            oldNameGroupedMap = stream.takeWhile(v -> !isCancelled()).parallel()
                    .collect(Collectors.groupingBy(m -> m.get("GID")));
            if (logger.isDebugEnabled()) {
                logger.debug("import Customer oldNames = {} from old version app", oldNameGroupedMap.size());
            }
            updateProgress(0.1, 1);
        }
    }

 

    private void loadContacts() {
        try (Stream<Map<String, Object>> stream = service.queryAllCustomerContactForStream()) {
            updateTitle("载入联系人");
            contactGroupedMap = stream.takeWhile(v -> !isCancelled()).parallel()
                    .collect(Collectors.groupingBy(m -> m.get("GID")));
            logger.debug("import Customer contacts = {} from old version app", contactGroupedMap.size());
            updateProgress(0.2, 1);
        }
    }

    private void syncCustomers() {
        try (Stream<Map<String, Object>> stream = service.queryAllCustomerForStream()) {
            updateTitle("客户信息");
            long size = service.countOfCustomer();
            AtomicInteger counter = new AtomicInteger(0);
            stream.takeWhile(v -> !isCancelled()).forEach(map -> {
                if (isCancelled()) {
                    updateMessage("Cancelled");
                    return;
                }
                Company updated = service.syncCustomer(map, basePath, oldNameGroupedMap, contactGroupedMap);
                if (updated != null) {
                    updateMessage(counter.get() + " / " + size + ">" + updated.getName());
                } else {
                    updateMessage(counter.get() + " / " + size + ">" + map.get("NAME"));
                }
                updateProgress(counter.incrementAndGet(), size);
            });
        }
    }

    private void syncContracts() {
        try (Stream<Map<String, Object>> stream = service.queryAllCustomerContractForStream()) {
            updateTitle("合同信息");
            long size = service.countOfCustomerContract();
            AtomicInteger counter = new AtomicInteger(0);
            stream.takeWhile(v -> !isCancelled()).forEach(map -> {
                if (isCancelled()) {
                    updateMessage("Cancelled");
                    return;
                }
                Contract updated = service.syncCustomerContract(map);
                if (updated != null) {
                    updateMessage(counter.get() + " / " + size + ">" + updated.getName());
                } else {
                    updateMessage(counter.get() + " / " + size + ">" + map.get("NO"));
                }
                updateProgress(counter.incrementAndGet(), size);
            });
        }
    }

}
