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 OldVersionSyncVendorTask extends Tasker<Object> {
    private static final Logger logger = LoggerFactory.getLogger(OldVersionSyncVendorTask.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 OldVersionSyncVendorTask() {
        updateTitle("老版本-同步供应商数据");
    }

    @Override
    protected Object execute(MessageHolder holder) throws Exception {
        basePath = companyService.getVendorBasePath();
        List<Runnable> runnable = Arrays.asList(this::loadOldNames, this::loadContacts, this::syncVendors,
                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.queryAllVendorOldNameForStream()) {
            updateTitle("载入曾用名");
            oldNameGroupedMap = stream.takeWhile(v -> !isCancelled()).parallel()
                    .collect(Collectors.groupingBy(m -> m.get("GID")));
            if (logger.isDebugEnabled()) {
                logger.debug("import vendor oldNames = {} from old version app", oldNameGroupedMap.size());
            }
            updateProgress(0.1, 1);
        }
    }

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

    private void syncVendors() {
        try (Stream<Map<String, Object>> stream = service.queryAllVendorForStream()) {
            updateTitle("客户信息");
            long size = service.countOfVendor();
            AtomicInteger counter = new AtomicInteger(0);
            stream.takeWhile(v -> !isCancelled()).forEach(map -> {
                if (isCancelled()) {
                    updateMessage("Cancelled");
                    return;
                }
                Company updated = service.syncVendor(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.queryAllVendorContractForStream()) {
            updateTitle("合同信息");
            long size = service.countOfVendorContract();
            AtomicInteger counter = new AtomicInteger(0);
            stream.takeWhile(v -> !isCancelled()).forEach(map -> {
                if (isCancelled()) {
                    updateMessage("Cancelled");
                    return;
                }
                Contract updated = service.syncVendorContract(map);
                if (updated != null) {
                    updateMessage(counter.get() + " / " + size + ">" + updated.getName());
                } else {
                    updateMessage(counter.get() + " / " + size + ">" + map.get("NO"));
                }
                updateProgress(counter.incrementAndGet(), size);
            });
        }
    }

}
