package com.hzs.scm.purchase.controller.manage;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.hzs.common.core.annotation.Log;
import com.hzs.common.core.constant.msg.MemberMsgConstants;
import com.hzs.common.core.constant.msg.ScmMsgConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.TransactionUtils;
import com.hzs.common.core.utils.poi.ExcelUtil;
import com.hzs.common.core.web.domain.AjaxResult;
import com.hzs.common.core.web.page.TableDataInfo;
import com.hzs.common.domain.sale.product.ext.BdProductBasExt;
import com.hzs.common.domain.scm.po.ext.PoOrderExt;
import com.hzs.common.domain.scm.pub.ScmOrderApproveLog;
import com.hzs.common.domain.scm.purchase.ext.IcPurchaseInBExt;
import com.hzs.common.domain.scm.purchase.ext.IcPurchaseInHExt;
import com.hzs.common.security.service.UserTokenService;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.scm.ic.param.BatchCodeParam;
import com.hzs.scm.ic.service.IIcBatchCodeService;
import com.hzs.scm.po.param.PoOrderItemsParam;
import com.hzs.scm.po.service.IPoOrderService;
import com.hzs.scm.pub.controller.ScmController;
import com.hzs.scm.pub.param.ScmApproveParam;
import com.hzs.scm.pub.service.IScmOrderApproveLogService;
import com.hzs.scm.purchase.param.PurchaseInBParam;
import com.hzs.scm.purchase.param.PurchaseInParam;
import com.hzs.scm.purchase.service.IIcPurchaseInHService;
import com.hzs.scm.purchase.vo.PurchaseExcelVO;
import com.hzs.scm.purchase.vo.PurchaseInBVo;
import com.hzs.scm.purchase.vo.PurchaseInVo;
import com.hzs.scm.purchase.vo.PurchaseOutExcelVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 采购入库表头 前端控制器
 * </p>
 *
 * @author hzs
 * @since 2023-11-17
 */
@RestController
@RequestMapping("/manage/purchase")
public class IcPurchaseInHController extends ScmController {

    @Autowired
    private IPoOrderService poOrderService;

    @Autowired
    private IIcPurchaseInHService icPurchaseInhService;

    @Autowired
    private IIcBatchCodeService batchCodeService;

    @Autowired
    private UserTokenService userTokenService;

    @Autowired
    private IScmOrderApproveLogService scmOrderApproveLogService;

    /**
     * 查询列表
     *
     * @return cubasdocParam 入参
     */
    @PostMapping("/list")
    @Log(module = EOperationModule.PO_PURCHASE, business = EOperationBusiness.PO_PURCHASE, method = EOperationMethod.SELECT)
    public TableDataInfo listPurchaseIn(@RequestBody PurchaseInParam purchaseInParam) {
        startPage();
        purchaseInParam.setPkCountry(SecurityUtils.getPkCountry());
        purchaseInParam.setReturnStatus(EYesNo.NO.getIntValue());
        List<IcPurchaseInHExt> icPurchaseInExtList = icPurchaseInhService.queryDisPurchaseInExtByCondition(purchaseInParam);
        return packageTableDataInfo(icPurchaseInExtList, packageScmReturnVo(icPurchaseInExtList));
    }

    /**
     * 查询列表
     *
     * @return cubasdocParam 入参
     */
    @PostMapping("/list-out")
    @Log(module = EOperationModule.PO_PURCHASE_OUT, business = EOperationBusiness.PO_PURCHASE_OUT, method = EOperationMethod.SELECT)
    public TableDataInfo listPurchaseOut(@RequestBody PurchaseInParam purchaseInParam) {
        startPage();
        purchaseInParam.setPkCountry(SecurityUtils.getPkCountry());
        purchaseInParam.setReturnStatus(EDealerYesNo.YES.getValue());
        List<IcPurchaseInHExt> icPurchaseInExtList = icPurchaseInhService.queryDisPurchaseInExtByCondition(purchaseInParam);
        return packageTableDataInfo(icPurchaseInExtList, packageScmReturnVo(icPurchaseInExtList));
    }

    /**
     * 查询列表
     *
     * @return cubasdocParam 入参
     */
    @PostMapping("/list-total")
    public TableDataInfo listPurchaseInTotal(@RequestBody PurchaseInParam purchaseInParam) {
        purchaseInParam.setPkCountry(SecurityUtils.getPkCountry());
        startPage();
        List<IcPurchaseInHExt> icPurchaseInExtList = icPurchaseInhService.queryTotalPurchaseInhExtByCondition(purchaseInParam);
        return packageTableDataInfo(icPurchaseInExtList, packageScmReturnVo(icPurchaseInExtList));
    }

    /**
     * 分页查询会员某个时间段内的奖金汇总
     */
    @PostMapping("/export-list-total")
    @Log(module = EOperationModule.PO_PURCHASE, business = EOperationBusiness.PO_PURCHASE, method = EOperationMethod.EXPORT)
    public void exportListPurchaseInTotal(HttpServletResponse response, PurchaseInParam purchaseInParam) {
        purchaseInParam.setPkCountry(SecurityUtils.getPkCountry());
        purchaseInParam.setReturnStatus(EDealerYesNo.NO.getValue());
        List<IcPurchaseInHExt> icPurchaseInExtList = icPurchaseInhService.queryTotalPurchaseInhExtByCondition(purchaseInParam);
        List<PurchaseExcelVO> purchaseInVoList = packageScmExportVo(icPurchaseInExtList);
        ExcelUtil<PurchaseExcelVO> util = new ExcelUtil<>(PurchaseExcelVO.class);
        util.exportExcel(response, purchaseInVoList, "采购入库导出");
    }

    private List<PurchaseInVo> packageScmReturnVo(List<IcPurchaseInHExt> purchaseInExtList) {
        List<PurchaseInVo> purchaseInVoList = new ArrayList<>();
        for (IcPurchaseInHExt purchaseInExt : purchaseInExtList) {
            PurchaseInVo purchaseInVo = BeanUtil.copyProperties(purchaseInExt, PurchaseInVo.class);
            List<IcPurchaseInBExt> purchaseInbiList = purchaseInExt.getIcPurchaseInbList();
            if (CollectionUtil.isNotEmpty(purchaseInbiList)) {
                List<PurchaseInBVo> returnbVoList = BeanUtil.copyToList(purchaseInbiList, PurchaseInBVo.class);
                purchaseInVo.setIcPurchaseInbList(returnbVoList);
            }
            purchaseInVoList.add(purchaseInVo);
        }
        return purchaseInVoList;
    }

    private List<PurchaseExcelVO> packageScmExportVo(List<IcPurchaseInHExt> purchaseInExtList) {
        List<PurchaseExcelVO> purchaseInVoList = new ArrayList<>();
        for (IcPurchaseInHExt purchaseInExt : purchaseInExtList) {
            List<IcPurchaseInBExt> purchaseInbiList = purchaseInExt.getIcPurchaseInbList();
            for (IcPurchaseInBExt icPurchaseInBiExt : purchaseInbiList) {
                PurchaseExcelVO purchaseExcelVo = BeanUtil.copyProperties(purchaseInExt, PurchaseExcelVO.class);
                setScmItemsExcel(icPurchaseInBiExt, purchaseExcelVo);
                purchaseExcelVo.setIsGift(icPurchaseInBiExt.getIsGift());
                purchaseInVoList.add(purchaseExcelVo);
            }
        }
        return purchaseInVoList;
    }

    /**
     * 分页查询会员某个时间段内的奖金汇总
     */
    @PostMapping("/export-back-total")
    @Log(module = EOperationModule.PO_PURCHASE, business = EOperationBusiness.PO_PURCHASE, method = EOperationMethod.EXPORT)
    public void exportListPurchaseInBackTotal(HttpServletResponse response, PurchaseInParam purchaseInParam) {
        purchaseInParam.setPkCountry(SecurityUtils.getPkCountry());
        purchaseInParam.setReturnStatus(EDealerYesNo.YES.getValue());
        List<IcPurchaseInHExt> icPurchaseInExtList = icPurchaseInhService.queryTotalPurchaseInhExtByCondition(purchaseInParam);
        List<PurchaseOutExcelVO> purchaseInVoList = packageBackScmExportVo(icPurchaseInExtList);
        ExcelUtil<PurchaseOutExcelVO> util = new ExcelUtil<>(PurchaseOutExcelVO.class);
        util.exportExcel(response, purchaseInVoList, "采购退货导出");
    }

    private List<PurchaseOutExcelVO> packageBackScmExportVo(List<IcPurchaseInHExt> purchaseInExtList) {
        List<PurchaseOutExcelVO> purchaseInVoList = new ArrayList<>();
        for (IcPurchaseInHExt purchaseInExt : purchaseInExtList) {
            List<IcPurchaseInBExt> purchaseInbiList = purchaseInExt.getIcPurchaseInbList();
            for (IcPurchaseInBExt icPurchaseInBiExt : purchaseInbiList) {
                PurchaseOutExcelVO purchaseExcelVo = BeanUtil.copyProperties(purchaseInExt, PurchaseOutExcelVO.class);
                setScmItemsExcel(icPurchaseInBiExt, purchaseExcelVo);
                purchaseExcelVo.setIsGift(icPurchaseInBiExt.getIsGift());
                purchaseInVoList.add(purchaseExcelVo);
            }
        }
        return purchaseInVoList;
    }

    /**
     * 新增采购入库
     *
     * @param purchaseInhParam 入参
     */
    @PostMapping("/insert")
    @Log(module = EOperationModule.PO_PURCHASE, business = EOperationBusiness.PO_PURCHASE, method = EOperationMethod.INSERT)
    public AjaxResult savePurchaseIn(@RequestBody PurchaseInParam purchaseInhParam) {
        String message = validatePurchaseParam(purchaseInhParam);
        if (ObjectUtil.isNotEmpty(message)) {
            return AjaxResult.error(TransactionUtils.getContent(message));
        }
        // 审核通过后需要关闭采购订单 回写采购订单累计入库数量
        return AjaxResult.success();
    }

    /**
     * 退货
     *
     * @param purchaseInhParam 入参
     */
    @PostMapping("/out-back")
    @Log(module = EOperationModule.PO_PURCHASE_OUT, business = EOperationBusiness.PO_PURCHASE_OUT, method = EOperationMethod.BACK)
    public AjaxResult backPurchaseIn(@RequestBody PurchaseInParam purchaseInhParam) {
        if (purchaseInhParam.getPkId() == null) {
            return AjaxResult.error(TransactionUtils.getContent(MemberMsgConstants.REQUIRED_NOT_EMPTY));
        }
        // 验证是否存在采购入库单
        IcPurchaseInHExt purchaseInExt = icPurchaseInhService.queryPurchaseInExtById(purchaseInhParam.getPkId(), null, SecurityUtils.getPkCountry());
        if (purchaseInExt == null || purchaseInExt.getOrderStatus() < EScmOrderStatus.APPROVE.getValue()) {
            return AjaxResult.error(TransactionUtils.getContent(ScmMsgConstants.IC_PURCHASE_NOT_EXIST));
        }
        icPurchaseInhService.insertSavePurchaseBack(purchaseInExt, purchaseInhParam);
        return AjaxResult.success();
    }

    private String validatePurchaseParam(PurchaseInParam purchaseInhParam) {
        List<PoOrderItemsParam> orderItemsParamList = new ArrayList<>();
        if (validatePurchaseIn(purchaseInhParam, orderItemsParamList)) {
            return MemberMsgConstants.REQUIRED_NOT_EMPTY;
        }
        purchaseInhParam.setPkCountry(SecurityUtils.getPkCountry());
        // 验证是否存在采购订单,根据采购订单生成表头 表体信息
        List<PoOrderExt> poOrderExtList = poOrderService.queryPoOrderByOrderItems(orderItemsParamList);
        if (validateCuBasdoc(poOrderExtList, orderItemsParamList)) {
            return ScmMsgConstants.PURCHASE_BODY_NOT_EMPTY;
        }
        // 验证产品
        Set<Integer> idList = purchaseInhParam.getPurchaseInBParamList().stream().map(PurchaseInBParam::getPkProductBas).collect(Collectors.toSet());
        Map<Integer, BdProductBasExt> bdProductBasExtMap = getBdProductBasExtMap(idList);
        if (bdProductBasExtMap == null) {
            return ScmMsgConstants.PRODUCT_NOT_EXIST;
        }
        // 判断是否有批次，有批次需要验证批次
        PoOrderExt poOrderExt = poOrderExtList.get(0);
        purchaseInhParam.setPkCorp(poOrderExt.getPkCorp());
        purchaseInhParam.setPkCubasdoc(poOrderExt.getPkCubasdoc());
        List<BatchCodeParam> batchCodeParamList = new ArrayList<>();
        Set<Long> batchCodeSet = new HashSet<>();
        for (PurchaseInBParam purchaseInbParam : purchaseInhParam.getPurchaseInBParamList()) {
            if (purchaseInbParam.getPkBatchCode() != null) {
                if (bdProductBasExtMap.containsKey(purchaseInbParam.getPkProductBas())) {
                    purchaseInbParam.setPkProduct(bdProductBasExtMap.get(purchaseInbParam.getPkProductBas()).getPkProduct());
                }
                BatchCodeParam batchCodeParam = BatchCodeParam.builder()
                        .pkProduct(purchaseInbParam.getPkProduct())
                        .pkBatchCode(purchaseInbParam.getPkBatchCode())
                        .build();
                batchCodeParamList.add(batchCodeParam);
                batchCodeSet.add(purchaseInbParam.getPkBatchCode());
            }
        }
        if (batchCodeParamList.size() > 0) {
            List<Long> batchCodeList = batchCodeService.queryBatchCodeByProduct(batchCodeParamList);
            for (Long batchCode : batchCodeSet) {
                if (!batchCodeList.contains(batchCode)) {
                    return ScmMsgConstants.BATCH_CODE_NOT_EXIST;
                }
            }
        }
        if (purchaseInhParam.getPkId() == null) {
            icPurchaseInhService.insertSavePurchaseByPoOrder(poOrderExtList, purchaseInhParam, SecurityUtils.getUserId());
        } else {
            // 查询是否存在采购入库单
            IcPurchaseInHExt purchaseInhExt = icPurchaseInhService.queryPurchaseInhExtById(purchaseInhParam.getPkId(), EScmOrderStatus.SAVE.getValue(), SecurityUtils.getPkCountry());
            if (purchaseInhExt == null) {
                return ScmMsgConstants.IC_PURCHASE_NOT_EXIST;
            }
            icPurchaseInhService.updateSavePurchaseByPoOrder(poOrderExtList, purchaseInhExt, purchaseInhParam, SecurityUtils.getUserId());
        }
        return null;
    }

    private Boolean validateCuBasdoc(List<PoOrderExt> poOrderExtList, List<PoOrderItemsParam> orderItemsParamList) {
        if (poOrderExtList == null || poOrderExtList.size() == 0) {
            return Boolean.TRUE;
        }
        int size = 0;
        // 供应商
        Integer pkCubasdoc = poOrderExtList.get(0).getPkCubasdoc();
        for (PoOrderExt poOrderExt : poOrderExtList) {
            size += poOrderExt.getPoOrderItemsExtList().size();
            if (!Objects.equals(pkCubasdoc, poOrderExt.getPkCubasdoc())) {
                return Boolean.TRUE;
            }
        }
        if (size != orderItemsParamList.size()) {
            return Boolean.TRUE;
        }
        // 采购订单合并只能是同一个供应商的
        return Boolean.FALSE;
    }

    private Boolean validatePurchaseIn(PurchaseInParam purchaseInhParam, List<PoOrderItemsParam> orderItemsParamList) {
        if (purchaseInhParam == null || CollectionUtil.isEmpty(purchaseInhParam.getPurchaseInBParamList())) {
            return Boolean.TRUE;
        }
        // 验证 采购订单明细字段不能为空
        for (PurchaseInBParam purchaseInbParam : purchaseInhParam.getPurchaseInBParamList()) {
            if (purchaseInbParam.getPkPoOrderItems() == null || purchaseInbParam.getPkPoOrder() == null ||
                    purchaseInbParam.getBizDate() == null || purchaseInbParam.getNnum() == null ||
                    purchaseInbParam.getPkStorehouse() == null) {
                return Boolean.TRUE;
            }
            PoOrderItemsParam poOrderItemsParam = PoOrderItemsParam.builder()
                    .pkOrder(purchaseInbParam.getPkPoOrder())
                    .pkId(purchaseInbParam.getPkPoOrderItems())
                    .pkProductBas(purchaseInbParam.getPkProductBas())
                    .nnum(purchaseInbParam.getNnum())
                    .build();
            orderItemsParamList.add(poOrderItemsParam);
        }
        return Boolean.FALSE;
    }


    /**
     * 修改采购入库
     *
     * @param purchaseInhParam 入参
     */
    @PostMapping("/update")
    @Log(module = EOperationModule.PO_PURCHASE, business = EOperationBusiness.PO_PURCHASE, method = EOperationMethod.UPDATE)
    public AjaxResult updatePurchaseIn(@RequestBody PurchaseInParam purchaseInhParam) {
        if (purchaseInhParam.getPkId() == null) {
            return AjaxResult.error(TransactionUtils.getContent(ScmMsgConstants.IC_PURCHASE_NOT_EXIST));
        }
        String message = validatePurchaseParam(purchaseInhParam);
        if (ObjectUtil.isNotEmpty(message)) {
            return AjaxResult.error(TransactionUtils.getContent(message));
        }
        // 审核通过后需要关闭采购订单 回写采购订单累计入库数量
        return AjaxResult.success();
    }

    /**
     * 删除采购订单
     *
     * @param pkId 主键
     */
    @DeleteMapping("/{pkId}")
    @Log(module = EOperationModule.PO_PURCHASE, business = EOperationBusiness.PO_PURCHASE, method = EOperationMethod.DELETE)
    public AjaxResult delete(@PathVariable Long pkId) {
        if (pkId == null) {
            return AjaxResult.error(TransactionUtils.getContent(ScmMsgConstants.IC_PURCHASE_NOT_EXIST));
        }
        IcPurchaseInHExt purchaseInhExt = icPurchaseInhService.queryPurchaseInhExtById(pkId, EScmOrderStatus.SAVE.getValue(), SecurityUtils.getPkCountry());
        if (purchaseInhExt == null) {
            return AjaxResult.error(TransactionUtils.getContent(ScmMsgConstants.IC_PURCHASE_NOT_EXIST));
        }
        icPurchaseInhService.deletePurchaseByPk(pkId, SecurityUtils.getUserId());
        return AjaxResult.success();
    }

}
