package com.gree.mall.manager.logic.material.base;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
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.material.base.WebsitGoodsAloneBean;
import com.gree.mall.manager.bean.material.base.WebsitGoodsAloneMVO;
import com.gree.mall.manager.bean.material.base.WebsitGoodsAlonePVO;
import com.gree.mall.manager.commonmapper.MaterialMapper;
import com.gree.mall.manager.enums.material.NormTypeEnum;
import com.gree.mall.manager.enums.material.StateEnum;
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.logic.common.SysDictCompanyLogic;
import com.gree.mall.manager.plus.entity.SysDictCompany;
import com.gree.mall.manager.plus.entity.WebsitGoodsAlone;
import com.gree.mall.manager.plus.service.SysDictCompanyService;
import com.gree.mall.manager.plus.service.WebsitGoodsAloneService;
import com.gree.mall.manager.utils.excel.ExcelUtils;
import com.gree.mall.manager.zfire.bean.WebsitGoodsParamBean;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class WebsitGoodsAloneLogic {

    private final CommonLogic commonLogic;
    private final MaterialMapper materialMapper;
    private final WebsitGoodsAloneService websitGoodsAloneService;
    private final SysDictCompanyService sysDictCompanyService;
    private final SysDictCompanyLogic sysDictCompanyLogic;

    public IPage<WebsitGoodsAloneMVO> mPage(WebsitGoodsParamBean zfireParamBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        FieldUtils.materialParam(zfireParamBean, WebsitGoodsAloneMVO.class, adminUser);
        IPage<WebsitGoodsAloneMVO> page = materialMapper.mAlonePage(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);

        return page;
    }

    public IPage<WebsitGoodsAlonePVO> pPage(WebsitGoodsParamBean zfireParamBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        FieldUtils.materialParam(zfireParamBean, WebsitGoodsAlonePVO.class, adminUser);
        IPage<WebsitGoodsAlonePVO> page = materialMapper.pAlonePage(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);

        return page;
    }

    public WebsitGoodsAloneBean detail(String id) {
        WebsitGoodsAlone goods = websitGoodsAloneService.getById(id);
        WebsitGoodsAloneBean bean = new WebsitGoodsAloneBean();
        BeanUtils.copyProperties(goods, bean);

        return bean;
    }

    @Transactional(rollbackFor = Exception.class)
    public void add(HttpServletRequest request, WebsitGoodsAloneBean bean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        if (StringUtils.isBlank(bean.getGoodsType())) {
            throw new RemoteServiceException("商品类型不能为空");
        }

        if (bean.getGoodsType().equals(WebsitGoodsTypeEnum.M.getKey())
                && StringUtils.isBlank(bean.getCategoryName())) {
            throw new RemoteServiceException("分类名称不能为空");
        }

        bean.setGoodsId(null);
        if (Objects.nonNull(adminUser.getAdminCompanyWechat())) {
            bean.setCompanyWechatId(adminUser.getAdminCompanyWechat().getCompanyWechatId());
            bean.setCompanyWechatName(adminUser.getAdminCompanyWechat().getCompanyName());
        }

        WebsitGoodsAlone goods = new WebsitGoodsAlone();
        BeanUtils.copyProperties(bean, goods);

        goods.setNormType(NormTypeEnum.M.getKey());

        // 库存单位不为空时,调用添加处理
        this.stockUnitEmptyAdd(goods);

        // 检查辅材名称、配件代码唯一
        this.checkMaterialUnique(goods);

        goods.insert();
    }

    private void checkMaterialUnique(WebsitGoodsAlone goods) {
        Integer count = websitGoodsAloneService.lambdaQuery()
                .eq(WebsitGoodsAlone::getCompanyWechatId, goods.getCompanyWechatId())
                .ne(StringUtils.isNotBlank(goods.getGoodsId()), WebsitGoodsAlone::getGoodsId, goods.getGoodsId())
                .eq(goods.getGoodsType().equals(WebsitGoodsTypeEnum.M.getKey()), WebsitGoodsAlone::getGoodsName, goods.getGoodsName())
                .eq(goods.getGoodsType().equals(WebsitGoodsTypeEnum.P.getKey()), WebsitGoodsAlone::getGoodsCode, goods.getGoodsCode())
                .eq(WebsitGoodsAlone::getGoodsType, goods.getGoodsType())
                .eq(WebsitGoodsAlone::getNormType, goods.getNormType())
                .count();
        if (count > 0) {
            if (goods.getGoodsType().equals(WebsitGoodsTypeEnum.M.getKey())) {
                throw new RemoteServiceException("已存在相同名称的辅材，请检查");
            } else {
                if (StringUtils.isNotBlank(goods.getGoodsCode())) {
                    throw new RemoteServiceException("已存在相同编码的配件，请检查");
                }
            }
        }
    }

    private void stockUnitEmptyAdd(WebsitGoodsAlone goods) {
        if (StringUtils.isNotBlank(goods.getGoodsStockUnit())) {

            String type = goods.getGoodsType().equals(WebsitGoodsTypeEnum.M.getKey()) ? "ASSIST_UNIT" : "PARTS_UNIT";
            Integer count = sysDictCompanyService.lambdaQuery()
                    .eq(SysDictCompany::getDictType, type)
                    .eq(SysDictCompany::getDictValue, goods.getGoodsStockUnit())
                    .count();

            if (count == 0) {
                SysDictCompany company = new SysDictCompany();
                company.setDictType(type)
                        .setDictValue(goods.getGoodsStockUnit());
                sysDictCompanyLogic.saveOpenDict(company);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void edit(HttpServletRequest request, WebsitGoodsAloneBean bean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        if (StringUtils.isBlank(bean.getGoodsType())) {
            throw new RemoteServiceException("商品类型不能为空");
        }

        if (bean.getGoodsType().equals(WebsitGoodsTypeEnum.M.getKey())
                && StringUtils.isBlank(bean.getCategoryName())) {
            throw new RemoteServiceException("分类名称不能为空");
        }

        WebsitGoodsAlone oldGoods = websitGoodsAloneService.getById(bean.getGoodsId());

        WebsitGoodsAlone goods = new WebsitGoodsAlone();
        BeanUtils.copyProperties(bean, goods);
        goods.setCompanyWechatId(oldGoods.getCompanyWechatId())
                .setCompanyWechatName(oldGoods.getCompanyWechatName());

        // 库存单位不为空时,调用添加处理
        this.stockUnitEmptyAdd(goods);

        this.checkMaterialUnique(goods);

        goods.updateById();
    }

    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateStatus(List<String> ids, StateEnum stateEnum) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        if (Objects.isNull(stateEnum)) {
            throw new RemoteServiceException("状态不能为空");
        }
        String companyWechatId = Objects.nonNull(adminUser.getAdminCompanyWechat()) ? adminUser.getAdminCompanyWechat().getCompanyWechatId() : null;
        websitGoodsAloneService.lambdaUpdate()
                .set(WebsitGoodsAlone::getStatus, stateEnum.getKey())
                .set(WebsitGoodsAlone::getUpdateBy, adminUser.getNickName())
                .set(WebsitGoodsAlone::getUpdateTime, DateUtil.date())
                .eq(WebsitGoodsAlone::getCompanyWechatId, companyWechatId)
                .in(WebsitGoodsAlone::getGoodsId, ids)
                .update();
    }

    public Object materialImportData(MultipartFile file) throws Exception {

        AdminUserCom adminUser = commonLogic.getAdminUser();

        String companyWechatId = Objects.nonNull(adminUser.getAdminCompanyWechat()) ? adminUser.getAdminCompanyWechat().getCompanyWechatId() : null;
        String companyName = Objects.nonNull(adminUser.getAdminCompanyWechat()) ? adminUser.getAdminCompanyWechat().getCompanyName() : null;

        List<Object> objects = ExcelUtils.importExcel(file);
        List<WebsitGoodsAlone> goodsList = new ArrayList<>();

        List<String> unitList = sysDictCompanyService.lambdaQuery()
                .eq(SysDictCompany::getDictType, "ASSIST_UNIT")
                .list()
                .stream()
                .map(SysDictCompany::getDictValue)
                .collect(Collectors.toList());

        for (int i = 0; i < objects.size(); i++) {
            List<Object> row = (List<Object>) objects.get(i);
            if (row.size() < 6) {
                row.add(null);
                row.add(null);
                row.add(null);
            }
            if (row.size() < 7) {
                row.add(null);
                row.add(null);
            }
            if (row.size() < 8) {
                row.add(null);
            }
            if (Objects.isNull(row.get(0))) {
                throw new RemoteServiceException("第" + (i+1) + "行, 分类名称不能为空");
            }
            if (Objects.isNull(row.get(1))) {
                throw new RemoteServiceException("第" + (i+1) + "行, 辅材名称不能为空");
            }
            if (Objects.isNull(row.get(2))) {
                throw new RemoteServiceException("第" + (i+1) + "行, 单位不能为空");
            }
            if (Objects.isNull(row.get(3))) {
                throw new RemoteServiceException("第" + (i+1) + "行, 销售价格不能为空");
            }

            String categoryStr = (String) row.get(0);
            String goodsNameStr = (String) row.get(1);
            String unitStr = (String) row.get(2);
            String salesStr = (String) row.get(3);
            String goodsCodeStr = (String) row.get(4);
            String specificationStr = (String) row.get(5);
            String remark = (String) row.get(6);

            Integer count = websitGoodsAloneService.lambdaQuery()
                    .eq(WebsitGoodsAlone::getCompanyWechatId, companyWechatId)
                    .eq(WebsitGoodsAlone::getGoodsType, WebsitGoodsTypeEnum.M.getKey())
                    .eq(WebsitGoodsAlone::getGoodsName, goodsNameStr)
                    .count();

            if (count > 0) {
                throw new RemoteServiceException("第" + (i+1) + "行, 辅材名称重复");
            }

            if (!unitList.contains(unitStr)) {
                throw new RemoteServiceException("第" + (i+1) + "行, 单位信息不存在");
            }

            WebsitGoodsAlone goods = new WebsitGoodsAlone();

            goods.setCompanyWechatId(companyWechatId);
            goods.setCompanyWechatName(companyName);
            goods.setGoodsType(WebsitGoodsTypeEnum.M.getKey());
            goods.setGoodsName(goodsNameStr);
            goods.setGoodsCode(goodsCodeStr);
            goods.setCategoryName(categoryStr);
            goods.setGoodsSpecification(specificationStr);
            goods.setRemark(remark);
            goods.setMarketPrice(new BigDecimal(salesStr));

            // 库存单位与销售单位一致
            goods.setGoodsStockUnit(unitStr);
            goods.setNormType(NormTypeEnum.M.getKey());

            goodsList.add(goods);
        }

        if (CollectionUtil.isNotEmpty(goodsList)) {
            // 检查导入名称唯一
            Map<String, List<WebsitGoodsAlone>> keyMap = goodsList.stream()
                    .collect(Collectors.groupingBy(WebsitGoodsAlone::getGoodsName));
            for (Map.Entry<String, List<WebsitGoodsAlone>> entry : keyMap.entrySet()) {
                if (entry.getValue().size() > 1) {
                    WebsitGoodsAlone product = entry.getValue().get(0);
                    throw new RemoteServiceException("导入文档里的 " + product.getGoodsName() + ", 辅材名称不能重复");
                }
            }
            for (WebsitGoodsAlone goods : goodsList) {
                this.checkMaterialUnique(goods);
            }

            websitGoodsAloneService.saveBatch(goodsList);
        }

        return null;
    }

    public Object partsImportData(MultipartFile file) throws IOException {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        String companyWechatId = Objects.nonNull(adminUser.getAdminCompanyWechat()) ? adminUser.getAdminCompanyWechat().getCompanyWechatId() : null;
        String companyName = Objects.nonNull(adminUser.getAdminCompanyWechat()) ? adminUser.getAdminCompanyWechat().getCompanyName() : null;

        List<Object> objects = ExcelUtils.importExcel(file);
        List<WebsitGoodsAlone> goodsList = new ArrayList<>();

        List<String> unitList = sysDictCompanyService.lambdaQuery()
                .eq(SysDictCompany::getCompanyWechatId, companyWechatId)
                .eq(SysDictCompany::getDictType, "PARTS_UNIT")
                .list()
                .stream()
                .map(SysDictCompany::getDictValue)
                .collect(Collectors.toList());

        for (int i = 0; i < objects.size(); i++) {
            List<Object> row = (List<Object>) objects.get(i);
            if (row.size() < 4) {
                row.add(null);
                row.add(null);
            }
            if (row.size() < 5) {
                row.add(null);
            }
            if (Objects.isNull(row.get(0))) {
                throw new RemoteServiceException("第" + (i+1) + "行, 配件名称不能为空");
            }
            if (Objects.isNull(row.get(1))) {
                throw new RemoteServiceException("第" + (i+1) + "行, 单位不能为空");
            }
            if (Objects.isNull(row.get(2))) {
                throw new RemoteServiceException("第" + (i+1) + "行, 销售价格不能为空");
            }

            String goodsNameStr = (String) row.get(0);
            String unitStr = (String) row.get(1);
            String salesStr = (String) row.get(2);
            String goodsCodeStr = (String) row.get(3);
            String remark = (String) row.get(4);

            if (!unitList.contains(unitStr)) {
                throw new RemoteServiceException("第" + (i+1) + "行, 单位信息不存在");
            }

            WebsitGoodsAlone goods = new WebsitGoodsAlone();

            goods.setCompanyWechatId(companyWechatId);
            goods.setCompanyWechatName(companyName);
            goods.setGoodsType(WebsitGoodsTypeEnum.P.getKey());
            goods.setGoodsName(goodsNameStr);
            goods.setGoodsCode(goodsCodeStr);
            goods.setRemark(remark);
            goods.setMarketPrice(new BigDecimal(salesStr));
            goods.setGoodsStockUnit(unitStr);
            goods.setNormType(NormTypeEnum.M.getKey());

            goodsList.add(goods);
        }

        if (CollectionUtil.isNotEmpty(goodsList)) {
            // 检查list唯一
            this.checkListUniqueParts(goodsList);
            // 检查数据库唯一
            for (WebsitGoodsAlone goods : goodsList) {
                this.checkMaterialUnique(goods);
            }
            websitGoodsAloneService.saveBatch(goodsList);
        }

        return null;
    }

    private void checkListUniqueParts(List<WebsitGoodsAlone> items) {
        Map<String, List<WebsitGoodsAlone>> keyMap = items.stream()
                .filter(v -> StringUtils.isNotBlank(v.getGoodsCode()))
                .collect(Collectors.groupingBy(WebsitGoodsAlone::getGoodsCode));
        if (CollectionUtil.isNotEmpty(keyMap)) {
            for (Map.Entry<String, List<WebsitGoodsAlone>> entry : keyMap.entrySet()) {
                if (entry.getValue().size() > 1) {
                    WebsitGoodsAlone product = entry.getValue().get(0);
                    throw new RemoteServiceException("导入文档里的 " + product.getGoodsName() + ", 配件发现重复编码");
                }
            }
        }
    }
}
