package com.ecep.contract.cloud.rk.ctx;

import static com.ecep.contract.SpringApp.getBean;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import javax.net.ssl.SSLException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.ecep.contract.BlackReasonType;
import com.ecep.contract.MessageHolder;
import com.ecep.contract.SpringApp;
import com.ecep.contract.cloud.AbstractCtx;
import com.ecep.contract.cloud.rk.CloudRkService;
import com.ecep.contract.ds.company.service.CompanyBlackReasonService;
import com.ecep.contract.ds.company.service.CompanyContactService;
import com.ecep.contract.ds.company.service.CompanyOldNameService;
import com.ecep.contract.ds.company.service.CompanyService;
import com.ecep.contract.model.CloudRk;
import com.ecep.contract.model.Company;
import com.ecep.contract.model.CompanyBlackReason;
import com.ecep.contract.model.CompanyContact;
import com.ecep.contract.model.CompanyOldName;
import com.ecep.contract.util.FileUtils;
import com.ecep.contract.util.HttpJsonUtils;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import lombok.Setter;

public class CloudRkCtx extends AbstractCtx {
    private static final Logger logger = LoggerFactory.getLogger(CloudRkCtx.class);
    @Setter
    private CloudRkService cloudRkService;
    @Setter
    private CompanyService companyService;
    @Setter
    private CompanyBlackReasonService companyBlackReasonService;
    @Setter
    private ObjectMapper objectMapper;
    private Proxy socksProxy;

    public CloudRkService getCloudRkService() {
        if (cloudRkService == null) {
            cloudRkService = getBean(CloudRkService.class);
        }
        return cloudRkService;
    }

    public CompanyService getCompanyService() {
        if (companyService == null) {
            companyService = getBean(CompanyService.class);
        }
        return companyService;
    }

    CompanyBlackReasonService getCompanyBlackReasonService() {
        if (companyBlackReasonService == null) {
            companyBlackReasonService = getBean(CompanyBlackReasonService.class);
        }
        return companyBlackReasonService;
    }

    ObjectMapper getObjectMapper() {
        if (objectMapper == null) {
            objectMapper = getBean(ObjectMapper.class);
        }
        return objectMapper;
    }

    Proxy getSocksProxy() {
        if (socksProxy == null) {
            String proxy = getConfService().getString(CloudRkService.KEY_PROXY);
            URI proxyUri = URI.create(proxy);
            Proxy.Type proxyType = Proxy.Type.valueOf(proxyUri.getScheme().toUpperCase());
            socksProxy = new Proxy(
                    proxyType,
                    new InetSocketAddress(proxyUri.getHost(), proxyUri.getPort()));
        }
        return socksProxy;
    }

    public void post(String url, Consumer<Map<String, Object>> data, Consumer<JsonNode> consumer) throws IOException {
        HttpJsonUtils.post(url, data, consumer, getObjectMapper(), getSocksProxy());
    }

    public boolean syncCompany(Company company, CloudRk cloudRk, MessageHolder holder) {
        if (!StringUtils.hasText(cloudRk.getCloudId())) {
            holder.warn("未定义平台编号, 尝试从平台上自动获取");
            // 当未定义平台编号时，尝试自动获取
            if (!queryCloudIdAndSelectOne(company, cloudRk, holder)) {
                // 自动获取到平台编号失败，立即返回
                return false;
            }
        }

        if (!StringUtils.hasText(cloudRk.getCloudId()) || cloudRk.getCloudId().equals("-")) {
            // 平台编号为 空 或 - 时，跳过同步
            holder.debug("平台编号为 空 或 - 时，跳过同步");
            return false;
        }

        boolean updated = false;
        try {
            if (updateEnterpriseInfo(company, cloudRk, holder)) {
                company = getCompanyService().save(company);
                updated = true;
            }

            if (updateBlackList(company, cloudRk, holder)) {
                updated = true;
            }

            if (updateEnterpriseCredit(company, cloudRk, holder)) {
                // cloudRk modified
                updated = true;
            }
            if (updateCustomerScore(company, cloudRk, holder)) {
                // cloudRk modified
                updated = true;
            }
            if (updateVendorScore(company, cloudRk, holder)) {
                // cloudRk modified
                updated = true;
            }
        } catch (Exception e) {
            // 异常
            logger.error("使用评分接口更新企业资信评价等级时发生错误", e);
            cloudRk.setDescription("评分接口错误:" + e.getMessage());
        }
        return updated;
    }

    /**
     * 更新黑名单列表
     */
    public boolean updateBlackList(
            Company company, CloudRk cloudRk, MessageHolder holder) throws IOException {
        LocalDateTime start = cloudRk.getCloudBlackListUpdated();
        if (start != null) {
            long elapse = getConfService().getLong(CloudRkService.KEY_BLACK_LIST_ELAPSE);
            if (elapse > 0) {
                LocalDateTime next = start.plusSeconds(elapse);
                if (next.isAfter(LocalDateTime.now())) {
                    holder.debug("更新时间未到, 上次更新时间 = " + start);
                    return false;
                }
            }
        }

        String api = getConfService().getString(CloudRkService.KEY_BLACK_LIST_URL);
        List<String> companyNames = getCompanyService().getAllNames(company);

        List<CompanyBlackReason> reasonList = new ArrayList<>();
        List<CompanyBlackReason> dbReasons = getCompanyBlackReasonService().findAllByCompany(company);
        for (String name : companyNames) {
            String url = api + URLEncoder.encode(name, StandardCharsets.UTF_8);
            try {
                HttpJsonUtils.get(url, json -> {
                    applyBlackReason(json, company, cloudRk, reasonList, dbReasons, holder);
                    saveJsonToFile(company, json, "black-" + name + ".json", holder);
                }, getObjectMapper(), getSocksProxy());
            } catch (IOException e) {
                catchException(e, holder);
            }
        }

        if (reasonList.isEmpty()) {
            cloudRk.setCloudBlackListUpdated(LocalDateTime.now());
            return false;

        }
        for (CompanyBlackReason companyBlackReason : reasonList) {
            getCompanyBlackReasonService().save(companyBlackReason);
        }
        cloudRk.setCloudBlackListUpdated(LocalDateTime.now());
        return true;
    }

    private boolean applyBlackReason(
            JsonNode json, Company company, CloudRk cloudRk,
            List<CompanyBlackReason> reasonList, List<CompanyBlackReason> dbReasons,
            MessageHolder holder) {
        if (isUnSuccess(json, holder)) {
            return false;
        }

        if (!json.has("data")) {
            holder.error("数据异常，返回的json中没有 data 字段");
            return false;
        }
        JsonNode data = json.get("data");

        if (data.has("blackReason")) {
            for (JsonNode reason : data.get("blackReason")) {
                try {
                    toCompanyBlackReasonList(company, BlackReasonType.BLACK, reason, dbReasons, reasonList);
                } catch (JsonMappingException e) {
                    holder.error("blackReason " + e.getMessage() + ", " + reason);
                }
            }
        }

        if (data.has("greyReason")) {
            for (JsonNode reason : data.get("greyReason")) {
                try {
                    toCompanyBlackReasonList(company, BlackReasonType.GRAY, reason, dbReasons, reasonList);
                } catch (JsonMappingException e) {
                    holder.error("greyReason " + e.getMessage() + ", " + reason);
                }
            }
        }
        return true;
    }

    private void toCompanyBlackReasonList(
            Company company, BlackReasonType type,
            JsonNode reason, List<CompanyBlackReason> dbReasons,
            List<CompanyBlackReason> reasonList) throws JsonMappingException {
        ObjectNode object = (ObjectNode) reason;
        String key = "rk-" + object.remove("id").asText();
        CompanyBlackReason cbr = dbReasons.stream().filter(r -> r.getKey().equals(key)).findAny()
                .orElseGet(CompanyBlackReason::new);
        getObjectMapper().updateValue(cbr, reason);
        cbr.setCompany(company);
        cbr.setType(type);
        cbr.setKey(key);
        reasonList.add(cbr);
    }

    /**
     * 更新评分
     */
    public boolean updateEnterpriseCredit(
            Company company, CloudRk cloudRk, MessageHolder holder) throws IOException {
        String api = getConfService().getString(CloudRkService.KEY_ENT_SCORE_URL);
        AtomicBoolean modified = new AtomicBoolean(false);
        try {
            post(api, data -> {
                data.put("entname", company.getName());
                // data.put("entid", cloudInfo.getCloudId());
                data.put("get", true);
            }, json -> {
                modified.set(applyEnterpriseCredit(json, cloudRk, holder));
                saveJsonToFile(company, json, "credit.json", holder);
            });
        } catch (IOException e) {
            catchException(e, holder);
        }
        return modified.get();
    }

    private boolean applyEnterpriseCredit(JsonNode json, CloudRk cloudRk, MessageHolder holder) {
        if (isUnSuccess(json, holder)) {
            return false;
        }
        if (isUnHasField(json, "data", holder)) {
            return false;
        }
        JsonNode data = json.get("data");
        boolean modified = false;
        String level = "";
        String description = "";
        if (data.isNull()) {
            level = "-";
        } else {
            level = data.get("level").asText();
            description = data.get("levelDescription").asText();
        }

        if (updateText(cloudRk::getRank, cloudRk::setRank, level, holder, "企业资信评价等级")) {
            modified = true;
        }
        if (updateText(cloudRk::getRankDescription, cloudRk::setRankDescription, description, holder, "企业资信评价等级说明")) {
            modified = true;
        }
        return modified;
    }

    private boolean isUnHasField(JsonNode json, String field, MessageHolder holder) {
        if (!json.has("data")) {
            holder.error("数据异常，返回的json中没有 data 字段");
            return true;
        }
        return false;
    }

    private boolean isUnSuccess(JsonNode json, MessageHolder holder) {
        if (isUnHasField(json, "success", holder)) {
            return true;
        }
        if (!json.get("success").asBoolean()) {
            holder.error("数据异常，返回 success = false, " + json);
            return true;
        }
        return false;
    }

    /**
     * 客户信用
     */
    public boolean updateCustomerScore(
            Company company, CloudRk cloudRk, MessageHolder holder) throws IOException {
        String url = getConfService().getString(CloudRkService.KEY_CUSTOMER_REPORT_URL);
        AtomicBoolean modified = new AtomicBoolean(false);
        try {
            post(url, data -> {
                // data.put("entName", company.getName());
                data.put("entId", cloudRk.getCloudId());
                data.put("get", true);
            }, json -> {
                modified.set(applyCustomerScore(json, company, cloudRk, holder));
                saveJsonToFile(company, json, "customer-score.json", holder);
            });
        } catch (IOException e) {
            catchException(e, holder);
        }
        return modified.get();
    }

    private boolean applyCustomerScore(JsonNode json, Company company, CloudRk cloudRk, MessageHolder holder) {
        if (isUnSuccess(json, holder)) {
            return false;
        }

        boolean modified = false;
        String grade = "";
        int score = 0;
        String description = "";
        if (isUnHasField(json, "data", holder)) {
            grade = "-";
            score = -1;
        } else {
            JsonNode data = json.get("data");
            if (data.isNull()) {
                grade = "无";
                score = -1;
            } else {
                grade = data.get("grade").asText();
                score = data.get("totalScore").asInt();
                description = data.get("description").asText();
            }
        }

        if (updateText(cloudRk::getCustomerGrade, cloudRk::setCustomerGrade, grade, holder, "客户信用评级")) {
            modified = true;
        }
        if (updateNumber(cloudRk::getCustomerScore, cloudRk::setCustomerScore, score, holder, "客户信用总分")) {
            modified = true;
        }
        if (updateText(cloudRk::getCustomerDescription, cloudRk::setCustomerDescription, description, holder,
                "客户信用评级说明")) {
            modified = true;
        }
        return modified;
    }

    public boolean updateVendorScore(
            Company company, CloudRk cloudRk, MessageHolder holder) throws IOException {
        String url = getConfService().getString(CloudRkService.KEY_VENDOR_REPORT_URL);
        AtomicBoolean modified = new AtomicBoolean(false);
        try {
            post(url, data -> {
                // data.put("entName", company.getName());
                data.put("entId", cloudRk.getCloudId());
                data.put("get", true);
            }, json -> {
                modified.set(applyVendorScore(json, cloudRk, holder));
                saveJsonToFile(company, json, "vendor-score.json", holder);
            });
        } catch (IOException e) {
            catchException(e, holder);
        }
        return modified.get();
    }

    private boolean applyVendorScore(JsonNode json, CloudRk cloudRk, MessageHolder holder) {
        if (isUnSuccess(json, holder)) {
            return false;
        }
        boolean modified = false;
        String grade = "";
        int score = 0;
        String description = "";
        if (isUnHasField(json, "data", holder)) {
            grade = "-";
            score = -1;
        } else {
            JsonNode data = json.get("data");
            if (data.isNull()) {
                grade = "无";
                score = -1;
            } else {
                grade = data.get("scoreLevel").asText();
                score = data.get("score").asInt();
                description = data.get("scoreDes").asText();
            }
        }

        if (updateText(cloudRk::getVendorGrade, cloudRk::setVendorGrade, grade, holder, "供应商信用得分")) {
            modified = true;
        }
        if (updateNumber(cloudRk::getVendorScore, cloudRk::setVendorScore, score, holder, "供应商信用总分")) {
            modified = true;
        }
        if (updateText(cloudRk::getVendorDescription, cloudRk::setVendorDescription, description, holder,
                "供应商信用评级说明")) {
            modified = true;
        }
        return modified;
    }

    /**
     * 自动获取到平台编号
     *
     * @param company 公司对象
     * @param cloudRk Cloud Rk
     * @return true 更新了 cloudId，否则false
     */
    private boolean queryCloudIdAndSelectOne(
            Company company, CloudRk cloudRk, MessageHolder holder) {
        try {
            List<CloudRkService.EntInfo> entInfos = queryEnterpriseWithFuzzy(company, cloudRk, holder);
            // 返回的查询结果为空时
            if (entInfos.isEmpty()) {
                // 设置为 -, 不在重复查找
                cloudRk.setCloudId("-");
                holder.warn("在平台中没有匹配到 " + company.getName());
                return false;
            }

            // 在返回的结果中，找到与公司名字一致的一个
            Optional<CloudRkService.EntInfo> optional = entInfos.stream()
                    .filter(n -> n.getName().equals(company.getName())).findAny();
            if (optional.isPresent()) {
                cloudRk.setCloudId(optional.get().getId());
                return true;
            }

            //
            holder.error("在平台中查询到多个匹配 ("
                    + entInfos.stream().map(CloudRkService.EntInfo::getName).collect(Collectors.joining(", "))
                    + ")，请手工同步选择匹配");
            return false;

        } catch (Exception e) {
            // 异常
            holder.error("查询接口获取企业平台编号发生错误 = " + e.getMessage());
            if (logger.isErrorEnabled()) {
                logger.error("使用模糊查询接口获取 {} 企业平台编号发生错误", company.getName(), e);
            }
            return false;
        }
    }

    /**
     * 使用模糊查询接口查询相关企业信息
     */
    public List<CloudRkService.EntInfo> queryEnterpriseWithFuzzy(
            Company company, CloudRk cloudRk, MessageHolder holder) throws IOException {
        String url = getConfService().getString(CloudRkService.KEY_ENT_FUZZY_URL);
        List<CloudRkService.EntInfo> results = new ArrayList<>();
        ObjectMapper objectMapper = getObjectMapper();
        try {
            HttpJsonUtils.post(url, data -> {
                data.put("theKey", company.getName());
                data.put("get", true);
            }, json -> {
                applyEnterpriseQuery(json, company, cloudRk, results, holder);
                saveJsonToFile(company, json, "fuzzy.json", holder);
            }, objectMapper, getSocksProxy());
        } catch (IOException ex) {
            catchException(ex, holder);
        }
        return results;
    }

    private boolean applyEnterpriseQuery(JsonNode json, Company company, CloudRk cloudRk,
            List<CloudRkService.EntInfo> results, MessageHolder holder) {
        if (!json.has("data")) {
            // 没有数据
            holder.error("数据异常，返回的json中没有 data 字段");
            return false;
        }
        JsonNode dataNode = json.get("data");
        if (!dataNode.isArray()) {
            holder.error("数据异常，返回的json中 data 字段不是数组");
            return false;
        }
        ObjectMapper objectMapper = getObjectMapper();

        for (JsonNode node : dataNode) {
            try {
                CloudRkService.EntInfo entInfo = new CloudRkService.EntInfo();
                objectMapper.updateValue(entInfo, node);
                if (node.has("isNowName")) {
                    String s = node.get("isNowName").asText();
                    entInfo.setNowName(s.equals("1") || s.equals("true"));
                }
                results.add(entInfo);
            } catch (Exception e) {
                holder.error("更新企业信息失败：" + e.getMessage() + ", json=" + node.toString());
                return false;
            }
        }
        return true;
    }

    /**
     * 更新企业工商注册信息
     */
    public boolean updateEnterpriseInfo(
            Company company, CloudRk cloudRk, MessageHolder holder) throws IOException {
        String api = getConfService().getString(CloudRkService.KEY_ENT_REPORT_URL);
        Proxy socksProxy = getSocksProxy();
        holder.debug("更新企业工商注册信息: " + company.getName() + " @ " + api + ", proxy=" + socksProxy);
        AtomicBoolean modified = new AtomicBoolean(false);
        try {
            post(api, data -> {
                data.put("entName", company.getName());
                data.put("entid", cloudRk.getCloudId());
                data.put("get", true);
                data.put("method", "data");
                data.put("nodetype", "B1001");
            }, jsonNode -> {
                modified.set(applyEnterpriseInfo(jsonNode, company, cloudRk, holder));
                saveJsonToFile(company, jsonNode, FileUtils.FILE_B1001_JSON, holder);
            });
        } catch (IOException e) {
            catchException(e, holder);
        }
        return modified.get();
    }

    private void catchException(IOException e, MessageHolder holder) throws IOException {
        if (e instanceof SSLException) {
            holder.error("网络错误:" + e.getMessage());
            // 网络错误时，抛出异常，中断后续网络请求
            throw e;
        }
        if (e instanceof SocketException) {
            holder.error("网络错误:" + e.getMessage());
            // 网络错误时，抛出异常，中断后续网络请求
            throw e;
        }
        holder.error(e.getMessage());
    }

    private boolean applyEnterpriseInfo(JsonNode json, Company company, CloudRk cloudRk, MessageHolder holder) {
        if (!json.has("B1001")) {
            holder.error("数据异常，返回的json中没有 B1001 字段");
            return false;
        }
        JsonNode b1001 = json.get("B1001");
        if (!b1001.has("count") || b1001.get("count").asInt() < 1 || !b1001.has("data")) {
            holder.error("数据异常，B1001 字段没有数据");
            return false;
        }
        boolean modified = false;
        JsonNode data = b1001.get("data");
        if (updateText(company::getEntType, company::setEntType, data, "enttype", holder, "企业类型")) {
            modified = true;
        }
        if (updateText(company::getEntStatus, company::setEntStatus, data, "entstatus", holder, "企业状态")) {
            modified = true;
        }
        if (updateLocalDate(company::getSetupDate, company::setSetupDate, data, "esdate", holder, "成立日期")) {
            modified = true;
        }
        if (updateText(company::getUniscid, company::setUniscid, data, "uniscid", holder, "企业状态")) {
            modified = true;
        }
        if (updateText(company::getRegAddr, company::setRegAddr, data, "dom", holder, "注册地址")) {
            modified = true;
        }
        if (updateText(company::getRegisteredCapital, company::setRegisteredCapital, data, "regcap", holder, "注册资金")) {
            modified = true;
        }
        if (updateText(company::getRegisteredCapitalCurrency, company::setRegisteredCapitalCurrency, data, "regcapcur",
                holder, "资本金币种")) {
            modified = true;
        }
        if (updateText(company::getLegalRepresentative, company::setLegalRepresentative, data, "frname", holder,
                "法人")) {
            modified = true;
        }
        if (updateText(company::getDistrict, company::setDistrict, data, "regorgprovince", holder, "注册区域")) {
            modified = true;
        }
        if (updateText(company::getTelephone, company::setTelephone, data, "tel", holder, "注册电话")) {
            modified = true;
        }
        if (updateText(company::getAddress, company::setAddress, data, "oploc", holder, "通讯地址")) {
            modified = true;
        }
        if (updateOperationPeriodBegin(company, data, holder)) {
            modified = true;
        }
        if (updateOperationPeriodEnd(company, data, holder)) {
            modified = true;
        }
        if (updateText(company::getIndustry, company::setIndustry, data, "nicfulltitle", holder, "行业")) {
            modified = true;
        }

        updateCompanyNameHistory(company, data, holder.sub("曾用名"));
        updateLegalRepresentativeContact(company, data, holder.sub("法人联系方式"));

        updateLocalDateTime(cloudRk::getCloudEntUpdate, cloudRk::setCloudEntUpdate, data, "updated", holder, "更新时间");
        return modified;
    }

    public boolean updateLocalDateTime(Supplier<LocalDateTime> getter, Consumer<LocalDateTime> setter, JsonNode data,String field,
            MessageHolder holder, String topic) {
                 JsonNode node = data.get(field);
        if (node == null || node.isNull()) {
            return false;
        }
         LocalDateTime updated = getObjectMapper().convertValue(node, LocalDateTime.class);
         updateLocalDateTime(getter, setter, updated, holder, topic);
        return false;
    }

    /**
     * 更新法人联系人联系方式
     */
    private void updateLegalRepresentativeContact(Company company, JsonNode data, MessageHolder holder) {
        String legalRepresentative = company.getLegalRepresentative();
        if (!StringUtils.hasText(legalRepresentative)) {
            return;
        }

        CompanyContactService contactService = SpringApp.getBean(CompanyContactService.class);
        List<CompanyContact> contactList = contactService.findAllByCompanyAndName(company, legalRepresentative);
        if (contactList == null) {
            // db error
            return;
        }
        CompanyContact contact = null;
        boolean modified = false;
        if (contactList.isEmpty()) {
            // 没有，创建法人联系人
            contact = new CompanyContact();
            contact.setCompany(company);
            contact.setName(legalRepresentative);
            contact.setPosition("法定代表人");
            contact.setCreated(LocalDate.now());
            modified = true;
        } else {
            // 先尝试查找法人
            Optional<CompanyContact> any = contactList.stream().filter(c -> "法定代表人".equals(c.getPosition())).findAny();
            // 如果没有找到，列表中第一个联系人
            if (any.isEmpty()) {
                any = contactList.stream().findFirst();
            }
            contact = any.get();
            if (updateText(contact::getPosition, contact::setPosition, "法定代表人", holder, "职位")) {
                modified = true;
            }
        }

        if (!StringUtils.hasText(contact.getEmail())) {
            if (updateText(contact::getEmail, contact::setEmail, data, "email", holder, "邮箱")) {
                modified = true;
            }
        }

        if (!StringUtils.hasText(contact.getAddress())) {
            if (updateText(contact::getAddress, contact::setAddress, data, "oploc", holder, "地址")) {
                modified = true;
            }
        }

        if (!StringUtils.hasText(contact.getPhone())) {
            if (updateText(contact::getPhone, contact::setPhone, data, "tel", holder, "电话")) {
                modified = true;
            }
        }

        if (modified) {
            contactService.save(contact);
        }

    }

    private boolean updateOperationPeriodBegin(Company company, JsonNode data, MessageHolder holder) {
        return updateLocalDate(company::getOperationPeriodBegin, company::setOperationPeriodBegin, data, "opfrom",
                holder, "营业期限起始日期", true);
    }

    private boolean updateOperationPeriodEnd(Company company, JsonNode data, MessageHolder holder) {
        JsonNode node = data.get("opto");
        if (node == null) {
            return false;
        }
        String text = node.asText();
        if (StringUtils.hasText(text)) {
            if (text.equals("-")) {
                return updateLocalDate(company::getOperationPeriodEnd, company::setOperationPeriodEnd, (LocalDate) null,
                        holder, "营业期限截至日期", true);
            }
            return updateLocalDate(company::getOperationPeriodEnd, company::setOperationPeriodEnd, data, "opto", holder,
                    "营业期限截至日期", true);
        }
        return false;
    }

    private void updateCompanyNameHistory(Company company, JsonNode data, MessageHolder holder) {
        JsonNode node = data.get("nameHistory");
        if (node == null) {
            return;
        }
        // 历史曾用名
        String nameHistory = node.asText();
        if (!StringUtils.hasText(nameHistory)) {
            return;
        }
        List<String> historyNames = new ArrayList<>();
        for (String str : nameHistory.split(",")) {
            String trimmed = str.trim();
            if (StringUtils.hasText(trimmed)) {
                historyNames.add(trimmed);
            }
        }
        CompanyOldNameService service = SpringApp.getBean(CompanyOldNameService.class);
        List<CompanyOldName> oldNames = service.findAllByCompany(company);
        for (CompanyOldName oldName : oldNames) {
            // 已经存在的移除
            historyNames.remove(oldName.getName());
        }
        for (String historyName : historyNames) {
            CompanyOldName oldName = service.createNew(company, historyName, false);
            oldName.setMemo("从相关方平台导入");
            service.save(oldName);
        }
    }

    private boolean updateLocalDate(Supplier<LocalDate> getter, Consumer<LocalDate> setter, JsonNode data, String field,
            MessageHolder holder, String topic, boolean allowNull) {
        JsonNode node = data.get(field);
        if (node == null || node.isNull()) {
            return false;
        }
        LocalDate localDate = getObjectMapper().convertValue(node, LocalDate.class);
        if (localDate == null && !allowNull) {
            return false;
        }
        return updateLocalDate(getter, setter, localDate, holder, topic, allowNull);
    }

    private boolean updateLocalDate(Supplier<LocalDate> getter, Consumer<LocalDate> setter, JsonNode data, String field,
            MessageHolder holder, String topic) {
        return updateLocalDate(getter, setter, data, field, holder, topic, false);
    }

    private void updateInstant(Supplier<Instant> getter, Consumer<Instant> setter, JsonNode data, String field,
            MessageHolder holder, String topic, boolean allowNull) {
        JsonNode node = data.get("updated");
        if (node == null) {
            return;
        }
        LocalDateTime updated = getObjectMapper().convertValue(node, LocalDateTime.class);
        if (updated == null) {
            if (!allowNull) {
                return;
            }
            updateInstant(getter, setter, null, holder, topic);
            return;
        }
        Instant instant = updated.toInstant(ZoneOffset.ofHours(8));
        updateInstant(getter, setter, instant, holder, topic);
    }

    private boolean updateText(Supplier<String> getter, Consumer<String> setter, JsonNode data, String field,
            MessageHolder holder, String topic) {
        JsonNode node = data.get(field);
        if (node == null || node.isNull()) {
            return false;
        }
        String text = node.asText();
        if (!StringUtils.hasText(text)) {
            return false;
        }
        return updateText(getter, setter, text, holder, topic);
    }

    private void saveJsonToFile(Company company, JsonNode json, String fileName, MessageHolder holder) {
        String companyPath = company.getPath();
        if (!StringUtils.hasText(companyPath)) {
            return;
        }

        File dir = new File(companyPath);
        if (!dir.exists()) {
            return;
        }

        File file = new File(dir, fileName);
        try {
            getObjectMapper().writeValue(file, json);
            holder.debug("保存文件 " + file.getName());
        } catch (IOException e) {
            holder.error("保存文件 " + file.getName() + " 发生错误：" + e.getMessage());
            logger.error("Save {}", file.getAbsolutePath(), e);
        }
    }

    public CloudRk getOrCreateCloudRk(Company company) {
        return getCloudRkService().getOrCreateCloudRk(company);
    }

    public CloudRk save(CloudRk cloudRk) {
        return getCloudRkService().save(cloudRk);
    }
}
