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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.material.manage.*;
import com.gree.mall.manager.commonmapper.MaterialMapper;
import com.gree.mall.manager.enums.admin.AdminWebsitTypeEnum;
import com.gree.mall.manager.enums.material.MaterialFlagEnum;
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.material.stock.WebitPurchaseStockLogic;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.*;
import com.gree.mall.manager.utils.excel.ExcelUtils;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class WebsitPurchaseRetLogic {

    private final CommonLogic commonLogic;
    private final MaterialMapper materialMapper;
    private final WebsitPurchaseRetService websitPurchaseRetService;
    private final WebsitPurchaseRetItemService websitPurchaseRetItemService;
    private final WebitPurchaseStockLogic webitPurchaseStockLogic;
    private final AdminWebsitService adminWebsitService;
    private final WebsitVenderService websitVenderService;
    private final WebsitGoodsService websitGoodsService;
    private final WebsitStockService websitStockService;
    private final WebsitPurchaseService websitPurchaseService;
    private final WebsitPurchaseItemService websitPurchaseItemService;
    private final WebsitGoodsCategoryService websitGoodsCategoryService;

    public IPage<WebsitPurchaseRetVO> page(ZfireParamBean zfireParamBean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        FieldUtils.materialParam(zfireParamBean, WebsitPurchaseRetVO.class, adminUser);

        return materialMapper.websitPurchaseRetPage(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
    }

    public WebsitPurchaseRetBean detail(String purchaseRetId) {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        WebsitPurchaseRetBean bean = new WebsitPurchaseRetBean();
        WebsitPurchaseRet purchase = websitPurchaseRetService.getById(purchaseRetId);
        BeanUtils.copyProperties(purchase, bean);
        String companyId = Objects.isNull(adminUser.getAdminCompanyWechat()) ? null : adminUser.getAdminCompanyWechat().getCompanyWechatId();
        List<WebsitPurchaseRetItemBean> list = websitPurchaseRetItemService.lambdaQuery()
                .eq(StringUtils.isNotBlank(companyId), WebsitPurchaseRetItem::getCompanyWechatId, companyId)
                .eq(WebsitPurchaseRetItem::getPurchaseRetId, purchaseRetId)
                .list()
                .stream()
                .map(v -> {
                    WebsitPurchaseRetItemBean item = new WebsitPurchaseRetItemBean();
                    BeanUtils.copyProperties(v, item);
                    return item;
                }).collect(Collectors.toList());
        bean.setItems(list);

        // 当前库存数量
        if (bean.getFlag().equals(MaterialFlagEnum.SAVE.getKey())) {
            List<WebsitStock> stocks = websitStockService.lambdaQuery()
                    .in(WebsitStock::getGoodsId, list.stream().map(WebsitPurchaseRetItemBean::getGoodsId).collect(Collectors.toList()))
                    .eq(WebsitStock::getCompanyWechatId, bean.getCompanyWechatId())
                    .eq(WebsitStock::getStorageId, bean.getStorageId())
                    .eq(WebsitStock::getWebsitId, bean.getWebsitId())
                    .list();
            if (CollectionUtil.isNotEmpty(stocks)) {
                Map<String, BigDecimal> stockMap = stocks.stream().collect(Collectors.toMap(WebsitStock::getGoodsId, WebsitStock::getQty));
                for (WebsitPurchaseRetItemBean itemBean : list) {
                    itemBean.setStockQty(stockMap.getOrDefault(itemBean.getGoodsId(), BigDecimal.ZERO));
                }
            }
        }
        return bean;
    }

    @Transactional(rollbackFor = Exception.class)
    public void add(WebsitPurchaseRetBean bean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        if (Objects.isNull(adminUser.getAdminCompanyWechat())) {
            throw new RemoteServiceException("平台账号禁用操作");
        }

        bean.setCompanyWechatId(adminUser.getAdminCompanyWechat().getCompanyWechatId());
        bean.setCompanyWechatName(adminUser.getAdminCompanyWechat().getCompanyName());

        // 根据配置是否注入仓位
        final Storage storage = webitPurchaseStockLogic.handleStorage(adminUser, bean.getWebsitId(), bean.getGoodsType(), bean.getStorageId());
        bean.setStorageId(storage.getStorageId());
        bean.setStorageName(storage.getStorageName());

        bean.setFlag(MaterialFlagEnum.SAVE.getKey());
        WebsitPurchaseRet purchase = new WebsitPurchaseRet();
        BeanUtils.copyProperties(bean, purchase);
        purchase.setPurchaseRetId(IdWorker.getIdStr());
        purchase.setRetTime(DateUtil.date());

        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal totalQty = BigDecimal.ZERO;
        if (CollectionUtil.isNotEmpty(bean.getItems())) {
            // 检查退货数量是否超库存
            this.checkStockQty(bean);

            List<WebsitPurchaseRetItem> itemList = new ArrayList<>();
            for (WebsitPurchaseRetItemBean itemBean : bean.getItems()) {
                WebsitPurchaseRetItem item = new WebsitPurchaseRetItem();
                BeanUtils.copyProperties(itemBean, item);
//                if (purchase.getGoodsType().equals(WebsitGoodsTypeEnum.P.getKey())) {
//                    item.setCost(BigDecimal.ZERO);
//                }
                item.setCompanyWechatId(purchase.getCompanyWechatId())
                        .setPurchaseRetId(purchase.getPurchaseRetId())
                        .setWebsitId(purchase.getWebsitId())
                        .setWebsitName(purchase.getWebsitName())
                        .setGoodsType(purchase.getGoodsType())
                        .setRetCost(item.getCost())
                        .setRetValue(item.getRetQty().multiply(item.getRetCost()));

                itemList.add(item);
                totalAmount = totalAmount.add(item.getRetValue());
                totalQty = totalQty.add(item.getRetQty());
            }
            websitPurchaseRetItemService.saveBatch(itemList);
        }

        purchase.setRetTotalAmount(totalAmount)
                .setRetTotalQty(totalQty);
        purchase.insert();
    }

    private void checkStockQty(WebsitPurchaseRetBean bean) {
        final List<WebsitStock> stocks = websitStockService.lambdaQuery()
                .eq(WebsitStock::getCompanyWechatId, bean.getCompanyWechatId())
                .eq(WebsitStock::getWebsitId, bean.getWebsitId())
                .eq(WebsitStock::getStorageId, bean.getStorageId())
                .in(WebsitStock::getGoodsId, bean.getItems().stream()
                        .map(WebsitPurchaseRetItemBean::getGoodsId)
                        .collect(Collectors.toList()))
                .list();
        if (CollectionUtil.isNotEmpty(stocks)) {
            final Map<String, BigDecimal> stockMap = stocks.stream()
                    .collect(Collectors.toMap(WebsitStock::getGoodsId, WebsitStock::getQty));

            for (WebsitPurchaseRetItemBean itemBean : bean.getItems()) {
                final BigDecimal stockQty = stockMap.get(itemBean.getGoodsId());
                if (Objects.isNull(stockQty)) {
                    throw new RemoteServiceException("”" + itemBean.getGoodsName() + "“ 的库存数量不存在");
                }

                // 库存数量不为空并且 （库存数量少于等于0或库存数量少于退货数量）
                if (stockQty.compareTo(BigDecimal.ZERO) <= 0 || stockQty.compareTo(itemBean.getRetQty()) < 0) {
                    throw new RemoteServiceException("”" + itemBean.getGoodsName() + "“ 的库存数量少于退货数量");
                }
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void edit(WebsitPurchaseRetBean bean) {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        if (Objects.isNull(adminUser.getAdminCompanyWechat())) {
            throw new RemoteServiceException("平台账号禁用操作");
        }

        WebsitPurchaseRet purchase = websitPurchaseRetService.getById(bean.getPurchaseRetId());
        if (!purchase.getFlag().equals(MaterialFlagEnum.SAVE.getKey())) {
            throw new RemoteServiceException("采购退货非\"保存\"状态，不能再编辑");
        }

        bean.setCompanyWechatId(adminUser.getAdminCompanyWechat().getCompanyWechatId());
        bean.setCompanyWechatName(adminUser.getAdminCompanyWechat().getCompanyName());

        // 根据配置是否注入仓位
        final Storage storage = webitPurchaseStockLogic.handleStorage(adminUser, bean.getWebsitId(), purchase.getGoodsType(), bean.getStorageId());
        bean.setStorageId(storage.getStorageId());
        bean.setStorageName(storage.getStorageName());

        bean.setFlag(MaterialFlagEnum.SAVE.getKey());
        purchase = new WebsitPurchaseRet();
        BeanUtils.copyProperties(bean, purchase);
        purchase.setGoodsType(purchase.getGoodsType());
        purchase.setRetTime(purchase.getRetTime());

        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal totalQty = BigDecimal.ZERO;
        if (CollectionUtil.isNotEmpty(bean.getItems())) {
            // 检查退货数量是否超库存
            this.checkStockQty(bean);

            websitPurchaseRetItemService.lambdaUpdate()
                    .eq(WebsitPurchaseRetItem::getCompanyWechatId, bean.getCompanyWechatId())
                    .eq(WebsitPurchaseRetItem::getPurchaseRetId, bean.getPurchaseRetId())
                    .remove();
            List<WebsitPurchaseRetItem> itemList = new ArrayList<>();
            for (WebsitPurchaseRetItemBean itemBean : bean.getItems()) {
                WebsitPurchaseRetItem item = new WebsitPurchaseRetItem();
                BeanUtils.copyProperties(itemBean, item);
//                if (purchase.getGoodsType().equals(WebsitGoodsTypeEnum.P.getKey())) {
//                    item.setCost(BigDecimal.ZERO);
//                }
                if (Objects.isNull(item.getRetCost())) {
                    item.setRetCost(item.getCost());
                }
                item.setCompanyWechatId(purchase.getCompanyWechatId())
                        .setPurchaseRetId(purchase.getPurchaseRetId())
                        .setWebsitId(purchase.getWebsitId())
                        .setWebsitName(purchase.getWebsitName())
                        .setGoodsType(purchase.getGoodsType())
                        .setRetValue(item.getRetQty().multiply(item.getRetCost()));

                itemList.add(item);
                totalAmount = totalAmount.add(item.getRetValue());
                totalQty = totalQty.add(item.getRetQty());
            }
            websitPurchaseRetItemService.saveBatch(itemList);
        }

        purchase.setRetTotalAmount(totalAmount)
                .setRetTotalQty(totalQty);
        purchase.updateById();
    }

    @Transactional(rollbackFor = Exception.class)
    public void confirm(String purchaseRetId, MaterialFlagEnum flag, String storageId) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();
        WebsitPurchaseRet purchaseRet = websitPurchaseRetService.getById(purchaseRetId);
        if (!purchaseRet.getCompanyWechatId().equals(adminUser.getCompanyWechatId())) {
            throw new RuntimeException("关键信息错误");
        }

        if (purchaseRet.getIsImport() && StringUtils.isBlank(storageId)) {
            throw new RemoteServiceException("请选择仓库");
        }

        if (purchaseRet.getIsImport()) {
            final Storage storage = webitPurchaseStockLogic.handleStorage(adminUser, purchaseRet.getWebsitId(), purchaseRet.getGoodsType(), storageId);
            purchaseRet.setStorageId(storageId)
                    .setStorageName(storage.getStorageName());
        }

        purchaseRet.setConfirmBy(adminUser.getNickName());
        purchaseRet.setConfirmTime(DateUtil.date());

        websitPurchaseRetService.lambdaUpdate()
                .set(WebsitPurchaseRet::getFlag, flag.getKey())
                .set(WebsitPurchaseRet::getConfirmBy, purchaseRet.getConfirmBy())
                .set(WebsitPurchaseRet::getConfirmTime, purchaseRet.getConfirmTime())
                .set(WebsitPurchaseRet::getStorageId, purchaseRet.getStorageId())
                .set(WebsitPurchaseRet::getStorageName, purchaseRet.getStorageName())
                .eq(WebsitPurchaseRet::getPurchaseRetId, purchaseRetId)
                .update();

        // 审核通过增加库存
        if (flag.getKey().equals(MaterialFlagEnum.OK.getKey())) {
            List<WebsitPurchaseRetItem> purchaseRetItems = websitPurchaseRetItemService.lambdaQuery()
                    .eq(WebsitPurchaseRetItem::getCompanyWechatId, adminUser.getCompanyWechatId())
                    .eq(WebsitPurchaseRetItem::getPurchaseRetId, purchaseRetId)
                    .list();

            webitPurchaseStockLogic.newRetStock(purchaseRet, purchaseRetItems, "采购退货");

            if (StringUtils.isNotBlank(purchaseRet.getPurchaseId())) {
                WebsitPurchase purchase = websitPurchaseService.getById(purchaseRet.getPurchaseId());
                if (Objects.nonNull(purchase)) {
                    List<WebsitPurchaseItem> purchaseItemList = websitPurchaseItemService.lambdaQuery()
                            .select(WebsitPurchaseItem::getId, WebsitPurchaseItem::getGoodsId, WebsitPurchaseItem::getRetQty)
                            .eq(WebsitPurchaseItem::getPurchaseId, purchase.getPurchaseId())
                            .list();
                    Map<String, WebsitPurchaseItem> purchaseItemMap = purchaseItemList.stream()
                            .collect(Collectors.toMap(WebsitPurchaseItem::getGoodsId, Function.identity()));

                    List<WebsitPurchaseItem> updateItemList = new ArrayList<>();
                    for (WebsitPurchaseRetItem purchaseRetItem : purchaseRetItems) {
                        if (purchaseItemMap.containsKey(purchaseRetItem.getGoodsId())) {
                            WebsitPurchaseItem item = purchaseItemMap.get(purchaseRetItem.getGoodsId());
                            item.setRetQty(item.getRetQty().add(purchaseRetItem.getRetQty()));
                            updateItemList.add(item);
                        }
                    }
                    if (CollectionUtil.isNotEmpty(updateItemList)) {
                        websitPurchaseItemService.saveOrUpdateBatch(updateItemList);
                    }
                }
            }
        }
    }

    public Object importData(MultipartFile file, String type) throws Exception {
        AdminUserCom adminUser = commonLogic.getAdminUser();

        List<Object> objects = ExcelUtils.importExcel(file);
        List<WebsitPurchaseRetItem> items = new ArrayList<>();

        List<AdminWebsit> adminWebsits;

        AdminWebsit adminWebsit = null;
        WebsitVender vender = null;
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal totalQty = BigDecimal.ZERO;

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

        if (adminUser.getType() == 0) {
            adminWebsits = adminWebsitService.lambdaQuery()
                    .eq(AdminWebsit::getWebsitId, adminUser.getAdminWebsitIds().get(0))
                    .list();
            adminWebsit = adminWebsits.get(0);
        } else if (adminUser.getType() == 1) {
            adminWebsits = adminWebsitService.lambdaQuery()
                    .eq(AdminWebsit::getType, AdminWebsitTypeEnum.C.getKey())
                    .in(AdminWebsit::getWebsitId, adminUser.getAdminWebsitIds())
                    .list();
        } else {
            throw new RemoteServiceException("平台账号不能导入");
        }

        if (CollectionUtil.isEmpty(adminWebsits)) {
            throw new RemoteServiceException("账号拥有网点信息为空");
        }

        String id = IdWorker.getIdStr();

        Map<String, AdminWebsit> websitMap = adminWebsits.stream()
                .collect(Collectors.toMap(AdminWebsit::getName, Function.identity()));
        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);
                row.add(null);
            }
            if (row.size() < 5) {
                row.add(null);
                row.add(null);
            }
            if (row.size() < 6) {
                row.add(null);
            }

            if (i == 0) {
                if (Objects.isNull(row.get(4)) && adminUser.getAdminWebsitIds().size() > 1) {
                    throw new RemoteServiceException("网点名称不能为空");
                }
                if (Objects.isNull(row.get(0))) {
                    throw new RemoteServiceException("供应商不能为空");
                }
            }
            if (Objects.isNull(row.get(1))) {
                throw new RemoteServiceException("商品名称不能为空");
            }
            if (Objects.isNull(row.get(2))) {
                throw new RemoteServiceException("数量不能为空");
            }
            if (type.equals(WebsitGoodsTypeEnum.M.getKey()) && Objects.isNull(row.get(3))) {
                throw new RemoteServiceException("退货价格不能为空");
            }

            String venderStr = (String) row.get(0);
            String goodsStr = (String) row.get(1);
            String qtyStr = (String) row.get(2);
            String costStr;
            if (Objects.isNull(row.get(3))) {
                costStr = "0";
            } else {
                costStr = (String) row.get(3);
            }
            String websitStr;
            if (Objects.isNull(row.get(3))) {
                websitStr = "";
            } else {
                websitStr = (String) row.get(4);
            }
            String noteStr;
            if (Objects.isNull(row.get(5))) {
                noteStr = "";
            } else {
                noteStr = (String) row.get(5);
            }

            if (i == 0) {
                adminWebsit = websitMap.get(websitStr);
                if (Objects.isNull(adminWebsit)) {
                    throw new RemoteServiceException("网点信息不存在");
                }

                vender = websitVenderService.lambdaQuery()
                        .eq(WebsitVender::getCompanyWechatId, companyWechatId)
                        .eq(WebsitVender::getVenderName, venderStr)
                        .last("limit 1")
                        .one();

                if (Objects.isNull(vender)) {
                    throw new RemoteServiceException("供应商信息不存在");
                }
            }

            WebsitGoods goods = websitGoodsService.lambdaQuery()
                    .eq(WebsitGoods::getCompanyWechatId, companyWechatId)
                    .eq(WebsitGoods::getGoodsName, goodsStr)
                    .last("limit 1")
                    .one();

            if (Objects.isNull(goods)) {
                throw new RemoteServiceException("商品信息不存在");
            }

            WebsitGoodsCategory goodsCategory = websitGoodsCategoryService.lambdaQuery()
                    .eq(WebsitGoodsCategory::getCompanyWechatId, companyWechatId)
                    .eq(WebsitGoodsCategory::getCategoryId, goods.getGoodsCategoryId())
                    .one();

            BigDecimal qty = new BigDecimal(qtyStr);
            BigDecimal cost = new BigDecimal(costStr);

            WebsitPurchaseRetItem item = new WebsitPurchaseRetItem();
            item.setCompanyWechatId(companyWechatId);
            item.setWebsitId(adminWebsit.getWebsitId());
            item.setWebsitName(adminWebsit.getName());
            item.setPurchaseRetId(id);
            item.setGoodsType(type);
            item.setGoodsId(goods.getGoodsId());
            item.setGoodsName(goods.getGoodsName());
            item.setRetCost(cost);
            item.setRetQty(qty);
            item.setRetValue(qty.multiply(cost));
            item.setGoodsStockUnit(goods.getGoodsStockUnit());
            item.setGoodsSpecification(goods.getGoodsSpecification());
            item.setNote(noteStr);

            if (type.equals(WebsitGoodsTypeEnum.P.getKey())) {
                item.setBrand(goods.getBrandRelaName());
                item.setProductCategory(goods.getProductRelaName());
//                List<WebsitGoodsBrandRela> brandRelas = websitGoodsBrandRelaService.lambdaQuery()
//                        .eq(WebsitGoodsBrandRela::getCompanyWechatId, item.getCompanyWechatId())
//                        .eq(WebsitGoodsBrandRela::getGoodsId, item.getGoodsId())
//                        .list();
//                if (CollectionUtil.isNotEmpty(brandRelas)) {
//                    String brand = brandRelas.stream().map(WebsitGoodsBrandRela::getBrandName).collect(Collectors.joining("/"));
//                    item.setBrand(brand);
//                }
//                List<WebsitGoodsCategoryRela> categoryRelas = websitGoodsCategoryRelaService.lambdaQuery()
//                        .eq(WebsitGoodsCategoryRela::getCompanyWechatId, item.getCompanyWechatId())
//                        .eq(WebsitGoodsCategoryRela::getGoodsId, item.getGoodsId())
//                        .list();
//                if (CollectionUtil.isNotEmpty(brandRelas)) {
//                    String category = categoryRelas.stream().map(WebsitGoodsCategoryRela::getCategoryName).collect(Collectors.joining("/"));
//                    item.setProductCategory(category);
//                }
            } else {
                item.setParentCategoryId(goods.getParentCategoryId());
                item.setParentCategoryName(goodsCategory.getParentCategoryName());
                item.setGoodsCategoryId(goods.getGoodsCategoryId());
                item.setGoodsCategoryName(goodsCategory.getCategoryName());
            }

            items.add(item);
            totalAmount = totalAmount.add(item.getRetValue());
            totalQty = totalQty.add(item.getRetQty());
        }

        if (CollectionUtil.isNotEmpty(items)) {
            // 合并重复商品
            Map<String, WebsitPurchaseRetItem> itemMap = items.stream()
                    .collect(Collectors.toMap(WebsitPurchaseRetItem::getGoodsId, Function.identity(), (key1, key2) -> key2));

            WebsitPurchaseRet purchaseRet = new WebsitPurchaseRet();
            purchaseRet.setPurchaseRetId(id);
            purchaseRet.setCompanyWechatId(companyWechatId);
            purchaseRet.setCompanyWechatName(companyName);
            purchaseRet.setWebsitId(items.get(0).getWebsitId());
            purchaseRet.setWebsitName(items.get(0).getWebsitName());
            purchaseRet.setGoodsType(type);
            purchaseRet.setVenderId(Objects.nonNull(vender) ? vender.getVenderId() : null);
            purchaseRet.setVenderName(Objects.nonNull(vender) ? vender.getVenderName() : null);
            purchaseRet.setRetTime(DateUtil.date());
            purchaseRet.setFlag(MaterialFlagEnum.SAVE.getKey());
            purchaseRet.setRetTotalAmount(totalAmount);
            purchaseRet.setRetTotalQty(totalQty);
            purchaseRet.setIsImport(true);
            purchaseRet.insert();
            websitPurchaseRetItemService.saveBatch(itemMap.values());
        }
        return null;
    }
}
