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

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

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.hibernate.Hibernate;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.util.StringUtils;

import com.ecep.contract.MessageHolder;
import com.ecep.contract.constant.CloudServiceConstant;
import com.ecep.contract.ds.other.service.InventoryCatalogService;
import com.ecep.contract.ds.other.service.InventoryService;
import com.ecep.contract.model.Inventory;
import com.ecep.contract.model.InventoryCatalog;
import com.ecep.contract.model.Price;

import lombok.Setter;

public class InventoryCtx extends AbstractYongYouU8Ctx {
    @Setter
    private InventoryService inventoryService;
    @Setter
    private InventoryCatalogService inventoryCatalogService;

    public InventoryService getInventoryService() {
        if (inventoryService == null) {
            inventoryService = getBean(InventoryService.class);
        }
        return inventoryService;
    }

    public InventoryCatalogService getInventoryCatalogService() {
        if (inventoryCatalogService == null) {
            inventoryCatalogService = getBean(InventoryCatalogService.class);
        }
        return inventoryCatalogService;
    }

    private boolean applyInventoryDetail(Inventory item, Map<String, Object> map, MessageHolder holder) {
        String catalogCode = (String) map.get("cInvCCode");
        String name = (String) map.get("cInvName");
        String spec = (String) map.get("cInvStd");
        String unitCode = (String) map.get("cComUnitCode");
        String unitName = (String) map.get("cComUnitName");
        String createPerson = (String) map.get("cCreatePerson");
        String modifyPerson = (String) map.get("cModifyPerson");
        Timestamp createDate = (Timestamp) map.get("dSDate");
        Timestamp modifyDate = (Timestamp) map.get("dModifyDate");

        boolean modified = false;

        Double outTaxRate = (Double) map.get("iTaxRate");
        Double inTaxRate = (Double) map.get("iImpTaxRate");
        // 参考成本
        Double baseCostPrice = (Double) map.get("iInvSPrice");
        // 最新成本
        Double latestCostPrice = (Double) map.get("iInvNCost");
        // 计划价/售价
        Double plannedPrice = (Double) map.get("iInvRCost");
        // 最低售价
        Double lowestSalePrice = (Double) map.get("iInvLSCost");
        // 参考售价
        Double suggestedSalePrice = (Double) map.get("iInvSCost");


        if (!item.isNameLock()) {
            if (updateText(item::getName, item::setName, name, holder, "名称")) {
                modified = true;
            }
        }

        if (!item.isSpecificationLock()) {
            if (updateText(item::getSpecification, item::setSpecification, spec, holder, "规格")) {
                modified = true;
            }
        }

        if (updateText(item::getUnit, item::setUnit, unitName, holder, "单位")) {
            modified = true;
        }

        if (updatePrice(item.getPurchasePrice(), inTaxRate, latestCostPrice, holder, "采购")) {
            modified = true;
        }
        if (updatePrice(item.getSalePrice(), outTaxRate, suggestedSalePrice, holder, "销售")) {
            modified = true;
        }

        if (updateInventoryCatalog(item::getCatalog, item::setCatalog, catalogCode, holder, "类别")) {
            modified = true;
        }
        if (updateEmployeeByName(item::getCreator, item::setCreator, createPerson, holder, "创建人")) {
            modified = true;
        }
        if (updateLocalDate(item::getCreateTime, item::setCreateTime, createDate, holder, "创建时间")) {
            modified = true;
        }
        if (updateEmployeeByName(item::getUpdater, item::setUpdater, modifyPerson, holder, "修改人")) {
            modified = true;
        }
        if (updateLocalDateTime(item::getUpdateDate, item::setUpdateDate, modifyDate, holder, "修改时间")) {
            modified = true;
        }

        return modified;
    }

    private boolean updatePrice(Price price, Double taxRate, Double preTaxPrice, MessageHolder holder, String title) {
        boolean modified = false;
        if (taxRate != null) {
            if (updateNumber(price::getTaxRate, price::setTaxRate, taxRate.floatValue(), holder, title + "税率")) {
                modified = true;
            }
        }
        if (preTaxPrice != null) {
            if (updateNumber(price::getPreTaxPrice, price::setPreTaxPrice, preTaxPrice, holder, title + "未税单价")) {
                modified = true;
            }
        }
        return modified;
    }


    public boolean syncInventoryDetailByCode(Inventory inventory, String inventoryCode, MessageHolder holder) {
        if (repository == null) {
            return false;
        }
        Map<String, Object> map = null;
        try {
            map = repository.queryInventoryDetail(inventoryCode);
        } catch (NoSuchBeanDefinitionException e) {
            holder.warn("未启用 " + CloudServiceConstant.U8_NAME + " 服务");
            return false;
        } catch (EmptyResultDataAccessException e) {
            holder.error("无此存货：" + inventoryCode);
            return false;
        }
        if (applyInventoryDetail(inventory, map, holder)) {
            inventory.setUpdateDate(LocalDateTime.now());
            return true;
        }
        return false;
    }

    /**
     * 依据存货分类编号更新存货分类
     *
     * @param getter      获取的函数
     * @param setter      设置的函数
     * @param catalogCode 存货分类编号
     * @param holder      消息处理对象
     * @param topic       主题
     * @return 是否更新
     */
    private boolean updateInventoryCatalog(Supplier<InventoryCatalog> getter, Consumer<InventoryCatalog> setter, String catalogCode, MessageHolder holder, String topic) {
        InventoryCatalog catalog = null;
        if (StringUtils.hasText(catalogCode)) {
            catalog = getInventoryCatalogService().findByCode(catalogCode);
        }
        if (catalog == null) {
            setter.accept(null);
            holder.warn("无效" + topic + "：" + catalogCode);
            return true;
        } else {
            if (!Objects.equals(getter.get(), catalog)) {
                if (!Hibernate.isInitialized(catalog)) {
                    catalog = getInventoryCatalogService().findByCode(catalogCode);
                }
                setter.accept(catalog);
                holder.info(topic + "修改为: " + catalog.getName());
                return true;
            }
        }
        return false;
    }

    /**
     * 依据存货编号更新存货
     *
     * @param getter        获取的函数
     * @param setter        设置的函数
     * @param inventoryCode 存货编号
     * @param holder        消息持有者
     * @param topic         主题
     * @return 是否更新
     */
    public boolean syncInventoryDetailByCode(Supplier<Inventory> getter, Consumer<Inventory> setter, String inventoryCode, MessageHolder holder, String topic) {
        if (!StringUtils.hasText(inventoryCode)) {
            return false;
        }
        Inventory inventory = null;
        InventoryService service = getInventoryService();
        if (StringUtils.hasText(inventoryCode)) {
            inventory = service.findByCode(inventoryCode);
            if (inventory == null) {
                inventory = service.createNewInstance();
                inventory.setCode(inventoryCode);
                if (syncInventoryDetailByCode(inventory, inventoryCode, holder)) {
                    inventory = getInventoryService().save(inventory);
                } else {
                    return false;
                }
            }
        }
        if (inventory == null) {
            setter.accept(null);
            holder.warn("无效" + topic + "：" + inventoryCode);
            return true;
        } else {
            if (!Objects.equals(getter.get(), inventory)) {
                if (!Hibernate.isInitialized(inventory)) {
                    inventory = service.findByCode(inventoryCode);
                }
                setter.accept(inventory);
                holder.info(topic + "修改为: " + inventory.getName());
                return true;
            }
        }
        return false;
    }
}
