package com.gree.mall.manager.logic.engin;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.engin.OrderEnginBaseBean;
import com.gree.mall.manager.bean.engin.OrderEnginBaseVO;
import com.gree.mall.manager.commonmapper.CommonMapper;
import com.gree.mall.manager.constant.Constant;
import com.gree.mall.manager.enums.base.BaseEnum;
import com.gree.mall.manager.enums.material.WebsitGoodsTypeEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.OrderEnginBaseItemService;
import com.gree.mall.manager.plus.service.OrderEnginBaseOperatorLogService;
import com.gree.mall.manager.plus.service.OrderEnginBaseService;
import com.gree.mall.manager.plus.service.WebsitSalesService;
import com.gree.mall.manager.zfire.bean.ZfireParamBean;
import com.gree.mall.manager.zfire.util.FieldUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class OrderEnginBaseLogic {

    private final CommonLogic commonLogic;
    private final CommonMapper commonMapper;
    private final OrderEnginBaseService orderEnginBaseService;
    private final OrderEnginBaseItemService orderEnginBaseItemService;
    private final OrderEnginBaseOperatorLogService orderEnginBaseOperatorLogService;
    private final RedisLockRegistry redisLockRegistry;
    private final WebsitSalesService websitSalesService;

    public IPage<OrderEnginBaseVO> list(ZfireParamBean zfireParamBean) {
        FieldUtils.supplyParam(zfireParamBean, OrderEnginBaseVO.class, commonLogic.getAdminUser());
//        zfireParamBean.setAdminWebsitIds(zfireParamBean.getAdminWebsitIds());
        IPage<OrderEnginBaseVO> page = commonMapper.orderEnginBaseList(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);

        return page;
    }

    public OrderEnginBaseBean detail(String id) {
        OrderEnginBaseBean bean = new OrderEnginBaseBean();
        OrderEnginBase base = orderEnginBaseService.getById(id);

        BeanUtils.copyProperties(base, bean);

        List<OrderEnginBaseItem> items = orderEnginBaseItemService.lambdaQuery()
                .eq(OrderEnginBaseItem::getOrderEnginBaseId, id)
                .list();
        List<OrderEnginBaseOperatorLog> operatorLogList = orderEnginBaseOperatorLogService.lambdaQuery()
                .eq(OrderEnginBaseOperatorLog::getOrderEnginBaseId, id)
                .orderByDesc(OrderEnginBaseOperatorLog::getCreateTime)
                .list();

        bean.setItems(items);
        bean.setOperatorLogList(operatorLogList);
        return bean;
    }

    @Transactional
    public void save(OrderEnginBaseBean bean) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        AdminCompanyWechat companyWechat = adminUser.getAdminCompanyWechat();

        bean.setCompanyWechatId(companyWechat.getCompanyWechatId());
        bean.setCompanyWechatName(companyWechat.getCompanyName());

        if (StringUtils.isBlank(bean.getId())) {
            String key = Constant.RedisPrefix.ORDER_ENGIN_BASE + ":" + bean.getCompanyWechatId();
            Lock obtain = redisLockRegistry.obtain(key);
            if (!obtain.tryLock(2, TimeUnit.SECONDS)) {
                log.error("添加工程基础资料锁失败");
                return;
            }

            try {
                OrderEnginBase base = new OrderEnginBase();
                BeanUtils.copyProperties(bean, base);

                // 新增
                base.setProjectName(base.getProjectName().replace(" ", ""))
                        .setProjectNo(base.getProjectNo().replace(" ", ""));
                Integer count = orderEnginBaseService.lambdaQuery()
                        .eq(OrderEnginBase::getProjectName, base.getProjectName())
                        .or()
                        .eq(OrderEnginBase::getProjectNo, base.getProjectNo())
                        .count();
                if (count > 0) {
                    throw new RemoteServiceException("工程基础资料已重复存在，请检查");
                }
                base.insert();

                if (CollectionUtil.isNotEmpty(bean.getItems())) {
                    // 检查唯一
                    this.checkUniqueGoods(bean.getItems());

                    int index = 0;
                    for (OrderEnginBaseItem item : bean.getItems()) {
                        try {
                            index++;

                            item.setOrderEnginBaseId(base.getId());
                            this.checkItemParams(item);

//                            item.setWebsitAmount(item.getNormAmount().subtract(item.getWorkerAmount()));
                        } catch (Exception e) {
                            throw new RemoteServiceException("第" + index + "行, " + e.getMessage());
                        }
                    }
                    orderEnginBaseItemService.saveBatch(bean.getItems());
                }
            } finally {
                obtain.unlock();
            }
        } else {
            // 修改
            OrderEnginBase oldBase = orderEnginBaseService.lambdaQuery()
                    .eq(OrderEnginBase::getCompanyWechatId, bean.getCompanyWechatId())
                    .eq(OrderEnginBase::getId, bean.getId())
                    .one();
            if (Objects.isNull(oldBase)) {
                throw new RemoteServiceException("工程基础资料不存在");
            }

            this.compareParams(bean, oldBase);

            List<OrderEnginBaseOperatorLog> operatorLogList = new ArrayList<>();
            List<OrderEnginBaseItem> productList = this.checkItemList(bean, oldBase, operatorLogList, adminUser);
            if (CollectionUtil.isNotEmpty(productList)) {
                // 检查唯一
                this.checkUniqueGoods(productList);

                orderEnginBaseItemService.saveOrUpdateBatch(productList);
            }

            orderEnginBaseOperatorLogService.saveBatch(operatorLogList);
        }

    }

    private void checkUniqueGoods(List<OrderEnginBaseItem> items) {
        Map<String, List<OrderEnginBaseItem>> keyMap = items.stream()
                .collect(Collectors.groupingBy(OrderEnginBaseItem::getGoodsId));
        for (Map.Entry<String, List<OrderEnginBaseItem>> entry : keyMap.entrySet()) {
            if (entry.getValue().size() > 1) {
                OrderEnginBaseItem product = entry.getValue().get(0);
                WebsitGoodsTypeEnum anEnum = BaseEnum.keyToEnumNotNull(WebsitGoodsTypeEnum.class, product.getGoodsType());
                throw new RemoteServiceException(anEnum.getRemark() + "配置里的 " + product.getGoodsName() + ", 商品不能重复");
            }
        }
    }

    private void compareParams(OrderEnginBaseBean bean, OrderEnginBase oldBase) {
        StringBuilder sb = new StringBuilder();

        if (!StrUtil.trim(bean.getManger()).equals(StrUtil.trim(oldBase.getManger()))) {
            sb.append("原负责人: ")
                    .append(StrUtil.trim(oldBase.getManger()))
                    .append(" 新负责人: ")
                    .append(StrUtil.trim(bean.getManger()))
                    .append(", ");
            oldBase.setManger(bean.getManger());
        }

        if (!StrUtil.trim(bean.getMobile()).equals(StrUtil.trim(oldBase.getMobile()))) {
            sb.append("原联系电话: ")
                    .append(StrUtil.trim(oldBase.getMobile()))
                    .append(" 新联系电话: ")
                    .append(StrUtil.trim(bean.getMobile()))
                    .append(", ");
            oldBase.setMobile(bean.getMobile());
        }

        if (bean.getStartTime().getTime() != oldBase.getStartTime().getTime()) {
            sb.append("原项目开始时间: ")
                    .append(DateUtil.formatDate(bean.getStartTime()))
                    .append(" 新项目开始时间: ")
                    .append(DateUtil.formatDate(oldBase.getStartTime()))
                    .append(", ");
            oldBase.setStartTime(bean.getStartTime());
        }

        if (ObjectUtil.notEqual(bean.getProvince(), oldBase.getProvince())) {
            sb.append("原项目地址 省: ")
                    .append(oldBase.getProvince())
                    .append(" 新项目地址 省: ")
                    .append(bean.getProvince())
                    .append(", ");
            oldBase.setProvinceId(bean.getProvinceId());
            oldBase.setProvince(bean.getProvince());
        }

        if (ObjectUtil.notEqual(bean.getCity(), oldBase.getCity())) {
            sb.append("原项目地址 市: ")
                    .append(oldBase.getCity())
                    .append(" 新项目地址 市: ")
                    .append(bean.getCity())
                    .append(", ");
            oldBase.setCityId(bean.getCityId());
            oldBase.setCity(bean.getCity());
        }

        if (ObjectUtil.notEqual(bean.getArea(), oldBase.getArea())) {
            sb.append("原项目地址 区: ")
                    .append(oldBase.getArea())
                    .append(" 新项目地址 区: ")
                    .append(bean.getArea())
                    .append(", ");
            oldBase.setAreaId(bean.getAreaId());
            oldBase.setArea(bean.getArea());
        }

        if (ObjectUtil.notEqual(bean.getStreet(), oldBase.getStreet())) {
            sb.append("原项目地址 街道: ")
                    .append(oldBase.getStreet())
                    .append(" 新项目地址 街道: ")
                    .append(bean.getStreet())
                    .append(", ");
            oldBase.setStreetId(bean.getStreetId());
            oldBase.setStreet(bean.getStreet());
        }

        if (ObjectUtil.notEqual(bean.getAddress(), oldBase.getAddress())) {
            sb.append("原项目地址: ")
                    .append(oldBase.getAddress())
                    .append(" 新项目地址: ")
                    .append(bean.getAddress())
                    .append(", ");
            oldBase.setAddress(bean.getAddress())
                    .setLat(bean.getLat())
                    .setLng(bean.getLng());
        }

        if (sb.length() > 0) {
            String updStr = sb.deleteCharAt(sb.lastIndexOf(", ")).toString();
            RpProjectRepairOperatorLog operatorLog = new RpProjectRepairOperatorLog();
            operatorLog.setProjectRepairId(oldBase.getId())
                    .setTypeText("项目信息")
                    .setContent(updStr)
                    .insert();
        }

        oldBase.updateById();
    }

    private List<OrderEnginBaseItem> checkItemList(OrderEnginBaseBean bean, OrderEnginBase oldBase, List<OrderEnginBaseOperatorLog> operatorLogList, AdminUserCom adminUser) {
        List<OrderEnginBaseItem> afterProductList = new ArrayList<>();
        // 设备检查
        List<OrderEnginBaseItem> oldProductList = orderEnginBaseItemService.lambdaQuery()
                .eq(OrderEnginBaseItem::getOrderEnginBaseId, oldBase.getId())
                .list();
        // 筛选出存在的商品记录
        List<OrderEnginBaseItem> existProductList = bean.getItems().stream()
                .filter(v -> StringUtils.isNotBlank(v.getId()))
                .collect(Collectors.toList());

        if (CollectionUtil.isEmpty(existProductList)) {
            // 记录id全空 全删除
            this.productAddOrDel(oldBase, oldProductList, operatorLogList, false, afterProductList, adminUser);
        } else {
            // 半删半改, 对比修改的设备记录
            Map<String, OrderEnginBaseItem> existProductMap = existProductList.stream()
                    .collect(Collectors.toMap(OrderEnginBaseItem::getId, Function.identity()));
            List<OrderEnginBaseItem> updList = new ArrayList<>();
            List<OrderEnginBaseItem> delList = new ArrayList<>();
            for (OrderEnginBaseItem product : oldProductList) {
                if (existProductMap.containsKey(product.getId())) {
                    updList.add(product);
                } else {
                    delList.add(product);
                }
            }

            if (CollectionUtil.isNotEmpty(updList)) {
                // 修改记录
                this.productUpdate(oldBase, updList, existProductMap, operatorLogList, afterProductList, adminUser);
            }

            if (CollectionUtil.isNotEmpty(delList)) {
                // 添加记录
                this.productAddOrDel(oldBase, delList, operatorLogList, false, afterProductList, adminUser);
            }
        }

        // 筛选出添加的设备记录
        List<OrderEnginBaseItem> addProductList = bean.getItems().stream()
                .filter(v -> StringUtils.isBlank(v.getId()))
                .collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(addProductList)) {
            // 添加记录
            this.productAddOrDel(oldBase, addProductList, operatorLogList, true, afterProductList, adminUser);
        }

        return afterProductList;
    }

    private void productAddOrDel(OrderEnginBase oldBase, List<OrderEnginBaseItem> handleProductList,
                                 List<OrderEnginBaseOperatorLog> operatorLogList, boolean direction,
                                 List<OrderEnginBaseItem> afterProductList, AdminUserCom adminUser) {
        StringBuilder sb = new StringBuilder();
        sb.append(direction ? "添加 " : "删除 ");
        DateTime curDate = DateUtil.date();
        for (OrderEnginBaseItem product : handleProductList) {
            StringBuilder recordSb = new StringBuilder();
            if (direction) {
                this.checkItemParams(product);
                product.setOrderEnginBaseId(oldBase.getId())
                        .setProductCreateTime(curDate)
                        .setProductCreateBy(adminUser.getNickName())
                        .setProductUpdateTime(curDate)
                        .setProductUpdateBy(adminUser.getNickName());
                afterProductList.add(product);
            }

            if (!direction) {
                recordSb.append(StrUtil.sub(product.getId(), 15, product.getId().length()))
                        .append("序号: ");
            }

            if (product.getGoodsType().equals(WebsitGoodsTypeEnum.M.getKey())) {
                recordSb.append(" 【大类】: ")
                        .append(product.getParentCategoryName())
                        .append(" 【小类】: ")
                        .append(product.getGoodsCategoryName())
                        .append("【辅材名称】: ")
                        .append(product.getGoodsName());
            } else {
                recordSb.append(" 【适用品牌】: ")
                        .append(product.getBrandRelaName())
                        .append(" 【适用产品大类】: ")
                        .append(product.getProductRelaName())
                        .append("【配件名称】: ")
                        .append(product.getGoodsName());
            }

            recordSb.append(" 【销售价格】: ")
                    .append(product.getNormAmount())
//                    .append(" 【师傅分账金额】: ")
//                    .append(product.getWorkerAmount())
//                    .append(" 【商户分账金额】: ")
//                    .append(product.getWebsitAmount())
                    .append(", ");

            sb.append(recordSb);
        }

        if (sb.length() > 0 && sb.lastIndexOf(", ") > 0) {
            String updStr = sb.deleteCharAt(sb.lastIndexOf(", ")).toString();

            OrderEnginBaseOperatorLog operatorLog = new OrderEnginBaseOperatorLog();
            operatorLog.setOrderEnginBaseId(oldBase.getId())
                    .setTypeText("配置明细")
                    .setContent(updStr);

            operatorLogList.add(operatorLog);
        }

        if (!direction) {
            orderEnginBaseItemService.removeByIds(handleProductList.stream()
                    .map(OrderEnginBaseItem::getId)
                    .collect(Collectors.toList()));
        }
    }

    private void productUpdate(OrderEnginBase oldBase, List<OrderEnginBaseItem> updList,
                               Map<String, OrderEnginBaseItem> existProductMap,
                               List<OrderEnginBaseOperatorLog> operatorLogList,
                               List<OrderEnginBaseItem> afterProductList, AdminUserCom adminUser) {
        StringBuilder sb = new StringBuilder();
        int index = 0;
        for (OrderEnginBaseItem oldProduct : updList) {
            StringBuilder recordSb = new StringBuilder();
            OrderEnginBaseItem newProduct = existProductMap.get(oldProduct.getId());
            this.checkItemParams(newProduct);

            if (oldProduct.getGoodsType().equals(WebsitGoodsTypeEnum.M.getKey())) {
                if (ObjectUtil.notEqual(oldProduct.getParentCategoryName(), newProduct.getParentCategoryName())) {
                    recordSb.append("原【大类】: ")
                            .append(oldProduct.getParentCategoryName())
                            .append(" 新【大类】: ")
                            .append(newProduct.getParentCategoryName())
                            .append(", ");

                    oldProduct.setParentCategoryId(newProduct.getParentCategoryId())
                            .setParentCategoryName(newProduct.getParentCategoryName());
                }

                if (ObjectUtil.notEqual(oldProduct.getGoodsCategoryName(), newProduct.getGoodsCategoryName())) {
                    recordSb.append("原【小类】: ")
                            .append(oldProduct.getGoodsCategoryName())
                            .append(" 新【小类】: ")
                            .append(newProduct.getGoodsCategoryName())
                            .append(", ");
                    oldProduct.setGoodsCategoryId(newProduct.getGoodsCategoryId())
                            .setGoodsCategoryName(newProduct.getGoodsCategoryName());
                }

                if (ObjectUtil.notEqual(oldProduct.getGoodsName(), newProduct.getGoodsName())) {
                    recordSb.append("原【辅材名称】: ")
                            .append(oldProduct.getGoodsName())
                            .append(" 新【辅材名称】: ")
                            .append(newProduct.getGoodsName())
                            .append(", ");

                    oldProduct.setGoodsId(newProduct.getGoodsId())
                            .setGoodsName(newProduct.getGoodsName());
                }
            } else {
                if (ObjectUtil.notEqual(oldProduct.getBrandRelaName(), newProduct.getBrandRelaName())) {
                    recordSb.append("原【适用品牌】: ")
                            .append(oldProduct.getBrandRelaName())
                            .append(" 新【适用品牌】: ")
                            .append(newProduct.getBrandRelaName())
                            .append(", ");

                    oldProduct.setBrandRelaId(newProduct.getBrandRelaId())
                            .setBrandRelaName(newProduct.getBrandRelaName());
                }

                if (ObjectUtil.notEqual(oldProduct.getProductRelaName(), newProduct.getProductRelaName())) {
                    recordSb.append("原【适用产品大类】: ")
                            .append(oldProduct.getProductRelaName())
                            .append(" 新【适用产品大类】: ")
                            .append(newProduct.getProductRelaName())
                            .append(", ");

                    oldProduct.setProductRelaId(newProduct.getProductRelaId())
                            .setProductRelaName(newProduct.getProductRelaName());
                }

                if (ObjectUtil.notEqual(oldProduct.getGoodsName(), newProduct.getGoodsName())) {
                    recordSb.append("原【配件名称】: ")
                            .append(oldProduct.getGoodsName())
                            .append(" 新【配件名称】: ")
                            .append(newProduct.getGoodsName())
                            .append(", ");
                    oldProduct.setGoodsId(newProduct.getGoodsId())
                            .setGoodsName(newProduct.getGoodsName());
                }
            }

            if (ObjectUtil.notEqual(oldProduct.getNormAmount(), newProduct.getNormAmount())) {
                recordSb.append("原【销售价格】: ")
                        .append(oldProduct.getNormAmount())
                        .append(" 新【销售价格】: ")
                        .append(newProduct.getNormAmount())
                        .append(", ");
                oldProduct.setNormAmount(newProduct.getNormAmount());
            }

//            if (ObjectUtil.notEqual(oldProduct.getWorkerAmount(), newProduct.getWorkerAmount())) {
//                recordSb.append("原【师傅分账金额】: ")
//                        .append(oldProduct.getWorkerAmount())
//                        .append(" 新【师傅分账金额】: ")
//                        .append(newProduct.getWorkerAmount())
//                        .append(", ");
//                oldProduct.setWorkerAmount(newProduct.getWorkerAmount());
//            }
//
//            newProduct.setWebsitAmount(newProduct.getNormAmount().subtract(newProduct.getWorkerAmount()));
//            if (ObjectUtil.notEqual(oldProduct.getWebsitAmount(), newProduct.getWebsitAmount())) {
//                recordSb.append("原【商户分账金额】: ")
//                        .append(oldProduct.getWebsitAmount())
//                        .append(" 新【商户分账金额】: ")
//                        .append(newProduct.getWebsitAmount())
//                        .append(", ");
//                oldProduct.setWebsitAmount(newProduct.getWebsitAmount());
//            }
            oldProduct.setGoodsId(newProduct.getGoodsId())
                    .setGoodsName(newProduct.getGoodsName())
                    .setGoodsCode(newProduct.getGoodsCode())
                    .setGoodsBarcodeId(newProduct.getGoodsBarcodeId())
                    .setNormType(newProduct.getNormType())
                    .setGoodsSpecification(newProduct.getGoodsSpecification())
                    .setGoodsStockUnit(newProduct.getGoodsStockUnit())
                    .setProductUpdateTime(DateUtil.date())
                    .setProductUpdateBy(adminUser.getNickName());

            afterProductList.add(oldProduct);

            if (recordSb.length() > 0) {
                if (index == 0) {
                    sb.append(StrUtil.sub(oldProduct.getId(), 15, oldProduct.getId().length()))
                            .append("序号修改: ");
                }
                sb.append(recordSb);
            }
            index++;
        }

        if (sb.length() > 0) {
            String updStr = sb.deleteCharAt(sb.lastIndexOf(", ")).toString();
            OrderEnginBaseOperatorLog operatorLog = new OrderEnginBaseOperatorLog();
            operatorLog.setOrderEnginBaseId(oldBase.getId())
                    .setTypeText("配置明细")
                    .setContent(updStr);

            operatorLogList.add(operatorLog);
        }
    }

    private void checkItemParams(OrderEnginBaseItem item) {
        if (StringUtils.isBlank(item.getGoodsType())) {
            throw new RemoteServiceException("商品类型不能为空");
        }
        WebsitGoodsTypeEnum typeEnum = BaseEnum.keyToEnumNotNull(WebsitGoodsTypeEnum.class, item.getGoodsType());

        if (StringUtils.isBlank(item.getGoodsId()) || StringUtils.isBlank(item.getGoodsName())) {
            throw new RemoteServiceException(typeEnum.getRemark() + "名称不能为空");
        }

        if (Objects.isNull(item.getNormAmount()) || item.getNormAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new RemoteServiceException(typeEnum.getRemark() + "销售价格请输入有效数字");
        }

//        if (Objects.isNull(item.getWorkerAmount())
//                || item.getWorkerAmount().compareTo(BigDecimal.ZERO) < 0
//                || item.getNormAmount().subtract(item.getWorkerAmount()).compareTo(BigDecimal.ZERO) < 0) {
//            throw new RemoteServiceException(typeEnum.getRemark() + "师傅分账金额请输入有效数字");
//        }
    }

    public void updateEndTime(String id) {
        orderEnginBaseService.lambdaUpdate()
                .set(OrderEnginBase::getEndTime, DateUtil.date())
                .eq(OrderEnginBase::getProjectNo, id)
                .update();

        websitSalesService.lambdaUpdate()
                .set(WebsitSales::getEndTime, DateUtil.date())
                .eq(WebsitSales::getProjectNo, id)
                .update();
    }
}
