package com.hzs.sale.deliver.controller.manage;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hzs.common.core.annotation.Log;
import com.hzs.common.core.annotation.RepeatSubmitSimple;
import com.hzs.common.core.constant.EnumsPrefixConstants;
import com.hzs.common.core.constant.SystemFieldConstants;
import com.hzs.common.core.constant.msg.CommonMsgConstants;
import com.hzs.common.core.constant.msg.SaOrderMsgConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.core.utils.StringUtils;
import com.hzs.common.core.utils.poi.ExcelUtil;
import com.hzs.common.core.web.controller.BaseController;
import com.hzs.common.core.web.domain.AjaxResult;
import com.hzs.common.core.web.page.TableDataInfo;
import com.hzs.common.domain.sale.ext.SaOrderExt;
import com.hzs.common.domain.sale.ext.SaOrderItemsExt;
import com.hzs.common.domain.sale.order.SaOrder;
import com.hzs.common.domain.sale.order.SaOrderSelfLog;
import com.hzs.common.security.service.UserTokenService;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.common.service.ITransactionCommonService;
import com.hzs.common.core.utils.TransactionUtils;
import com.hzs.sale.deliver.param.*;
import com.hzs.sale.deliver.service.ISaDeliverBusinessService;
import com.hzs.sale.deliver.service.ISaDeliverService;
import com.hzs.sale.deliver.vo.*;
import com.hzs.sale.order.service.IOrderBusinessService;
import com.hzs.sale.order.service.ISaOrderItemsService;
import com.hzs.sale.order.service.ISaOrderSelfLogService;
import com.hzs.sale.order.service.ISaOrderService;
import com.hzs.sale.util.OrderUtil;
import com.hzs.system.base.IAreaServiceApi;
import com.hzs.system.base.IBarCodeServiceApi;
import com.hzs.system.base.dto.BarCodeDTO;
import com.hzs.system.sys.IUserServiceApi;
import com.hzs.system.sys.dto.UserAuthorityDTO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

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

/**
 * @Description: 发货清单未合单控制器
 * @Author: jiang chao
 * @Time: 2022/10/28 11:24
 * @Classname: SaDeliverOrderController
 * @PackageName: com.hzs.sale.deliver.controller.manage
 */
@RestController
@RequestMapping("/manage/deliver-unhandled")
public class SaDeliverUnhandledController extends BaseController {

    @Autowired
    private ISaOrderService iSaOrderService;
    @Autowired
    private ISaOrderItemsService iSaOrderItemsService;
    @Autowired
    private ISaDeliverService iSaDeliverService;
    @Autowired
    private IOrderBusinessService iOrderBusinessService;
    @Autowired
    private ISaDeliverBusinessService iSaDeliverBusinessService;
    @Autowired
    private ITransactionCommonService iTransactionCommonService;
    @Autowired
    private UserTokenService userTokenService;
    @Autowired
    private ISaOrderSelfLogService saOrderSelfLogService;

    @DubboReference
    private IAreaServiceApi iAreaServiceApi;
    @DubboReference
    private IBarCodeServiceApi iBarCodeServiceApi;
    @DubboReference
    private IUserServiceApi iUserServiceApi;


    /**
     * 列表
     *
     * @param param 未合单列表查询入参
     * @return
     */
    @Log(module = EOperationModule.DELIVER_ORDER, business = EOperationBusiness.DELIVER_UNHANDLED, method = EOperationMethod.SELECT)
    @GetMapping("/list")
    public TableDataInfo list(DeliverUnhandledParam param) {
        DateUtils.handTimeStartAndEnd(param.getCreationTime());
        DateUtils.handTimeStartAndEnd(param.getPayTime());

        Integer pkCountry = SecurityUtils.getPkCountry();

        // 返回数据
        List<DeliverUnhandledVO> resultList = new ArrayList<>();

        // 未合单目前查询状态（已付款）
        param.setOrderStatusList(Collections.singletonList(EOrderStatus.PAY.getValue()));
        // 发货清单只显示公司自提的订单
        param.setDeliveryWay(EDelivery.COMPANY_PICKED_UP.getValue());

        if (StringUtils.isNotEmpty(param.getOriginalOrderCode())) {
            // 原单号不为空，则需要查询
            QueryWrapper<SaOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("ORDER_CODE", param.getOriginalOrderCode());
            queryWrapper.eq(SystemFieldConstants.PK_COUNTRY, pkCountry);
            SaOrder querySaOrder = iSaOrderService.getOne(queryWrapper);
            if (null == querySaOrder) {
                return getDataTable(resultList);
            }
            param.setPkOriginalOrder(querySaOrder.getPkId());
        }

        // 获取管理员权限（角色地区范围、体系列表、团队列表）
        UserAuthorityDTO userAuthorityDTO = iUserServiceApi.getUserAuthority(SecurityUtils.getUserId()).getData();
        param.setAreaScopeList(userAuthorityDTO.getRoleAreaScopeList());
        param.setVertexIdList(userAuthorityDTO.getVertexIdList());
        param.setTeamList(userAuthorityDTO.getUserTeamList());

        startPage();
        resultList = iSaOrderItemsService.queryDeliverUnhandledList(param, pkCountry);

        // 当查询有数据才进行处理
        if (resultList.size() > 0) {
            // 获取行政区划map
            Map<Integer, String> areaMap = iAreaServiceApi.getAreaMap(pkCountry).getData();

            for (DeliverUnhandledVO deliverUnhandled : resultList) {
                // 省市区处理
                OrderUtil.handleOrderAddress(areaMap, deliverUnhandled);
            }
        }
        return getDataTable(resultList);
    }


    /**
     * 导出
     *
     * @param response
     * @param param    未合单列表查询入参
     */
    @Log(module = EOperationModule.DELIVER_ORDER, business = EOperationBusiness.DELIVER_UNHANDLED, method = EOperationMethod.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, DeliverUnhandledParam param) {
        DateUtils.handTimeStartAndEnd(param.getCreationTime());
        DateUtils.handTimeStartAndEnd(param.getPayTime());

        Integer pkCountry = SecurityUtils.getPkCountry();

        // 返回数据
        List<DeliverUnhandledVO> resultList = new ArrayList<>();

        // 未合单目前查询状态（已付款）
        param.setOrderStatusList(Collections.singletonList(EOrderStatus.PAY.getValue()));

        if (StringUtils.isNotEmpty(param.getOriginalOrderCode())) {
            // 原单号不为空，则需要查询
            QueryWrapper<SaOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("ORDER_CODE", param.getOriginalOrderCode());
            queryWrapper.eq(SystemFieldConstants.PK_COUNTRY, pkCountry);
            SaOrder querySaOrder = iSaOrderService.getOne(queryWrapper);
            if (null == querySaOrder) {
                ExcelUtil<DeliverUnhandledVO> util = new ExcelUtil<>(DeliverUnhandledVO.class);
                util.exportExcel(response, resultList, "发货清单未合单导出");
                return;
            }
            param.setPkOriginalOrder(querySaOrder.getPkId());
        }

        // 获取管理员权限（角色地区范围、体系列表、团队列表）
        UserAuthorityDTO userAuthorityDTO = iUserServiceApi.getUserAuthority(SecurityUtils.getUserId()).getData();
        param.setAreaScopeList(userAuthorityDTO.getRoleAreaScopeList());
        param.setVertexIdList(userAuthorityDTO.getVertexIdList());
        param.setTeamList(userAuthorityDTO.getUserTeamList());

        resultList = iSaOrderItemsService.queryDeliverUnhandledList(param, pkCountry);

        // 当查询有数据才进行处理
        if (resultList.size() > 0) {
            // 获取行政区划map
            Map<Integer, String> areaMap = iAreaServiceApi.getAreaMap(pkCountry).getData();

            // 获取需要翻译的枚举翻译
            Map<String, String> transactionMap = iTransactionCommonService.exportEnumTransaction(EDelivery.values(), ESupplyWay.values(), ETransportType.values(), EPresaleStatus.values(), EOrderType.values(), EOrderStatus.values(), ESaleType.values(), EShippingChannel.values());

            for (DeliverUnhandledVO deliverUnhandled : resultList) {
                // 省市区处理
                OrderUtil.handleOrderAddress(areaMap, deliverUnhandled);

                deliverUnhandled.setIsGiftVal(transactionMap.get(EnumsPrefixConstants.E_SALE_TYPE + deliverUnhandled.getIsGift()));
                deliverUnhandled.setDeliveryWayVal(transactionMap.get(EnumsPrefixConstants.DELIVERY + deliverUnhandled.getDeliveryWay()));
                deliverUnhandled.setOperateScopeVal(transactionMap.get(EnumsPrefixConstants.SUPPLY_WAY + deliverUnhandled.getOperateScope()));
                deliverUnhandled.setShippingChannelVal(transactionMap.get(EnumsPrefixConstants.E_SHIPPING_CHANNEL + deliverUnhandled.getShippingChannel()));
                deliverUnhandled.setTranTypeVal(transactionMap.get(EnumsPrefixConstants.ENU_TRA + deliverUnhandled.getTranType()));
                deliverUnhandled.setPreSaleStatusVal(transactionMap.get(EnumsPrefixConstants.PRESALE_STATUS + deliverUnhandled.getPreSaleStatus()));
                deliverUnhandled.setOrderTypeVal(transactionMap.get(EnumsPrefixConstants.ORDER_TYPE + deliverUnhandled.getOrderType()));
                deliverUnhandled.setOrderStatusVal(transactionMap.get(EnumsPrefixConstants.ORDER_STATUS + deliverUnhandled.getOrderStatus()));
            }
        }
        ExcelUtil<DeliverUnhandledVO> util = new ExcelUtil<>(DeliverUnhandledVO.class);
        util.exportExcel(response, resultList, "发货清单未合单导出");
    }


    /**
     * 排除产品
     *
     * @param param
     * @return
     */
    @GetMapping("/exclude-product")
    public AjaxResult excludeProduct(DeliverExcludeProductParam param) {
        // 排除产品列表
        List<DeliverExcludeProductVO> resultList;

        // 合单排除产品，只能是已付款的订单
        param.setOrderStatusList(Collections.singletonList(EOrderStatus.PAY.getValue()));

        if (1 == param.getMergeType()) {
            // 合单，需要根据传入的订单明细ID，进行查询
            if (CollectionUtils.isEmpty(param.getIdList())) {
                // 选中合单，必须要传入订单明细
                return AjaxResult.error(TransactionUtils.getContent(CommonMsgConstants.MISSING_PARAM));
            }
            resultList = iSaOrderItemsService.queryExcludeProductByIdList(param.getIdList(), SecurityUtils.getPkCountry());
        } else {
            // 全部合单，需要根据传入的查询条件，进行查询
            resultList = iSaOrderItemsService.queryExcludeProductByQueryParam(param, SecurityUtils.getPkCountry());
        }

        // TODO cabbage 产品库存显示处理

        return AjaxResult.success(resultList);
    }


    /**
     * 生成发货单（合单）
     *
     * @param param 生成入参
     * @return
     */
    @RepeatSubmitSimple
    @Log(module = EOperationModule.DELIVER_ORDER, business = EOperationBusiness.DELIVER_UNHANDLED, method = EOperationMethod.INSERT, remark = "生成发货单")
    @PostMapping("/merge")
    public AjaxResult mergeDeliver(@RequestBody DeliverMergeParam param) {
        DateUtils.handTimeStartAndEnd(param.getCreationTime());
        DateUtils.handTimeStartAndEnd(param.getPayTime());

        // 生成发货单的订单数据
        List<SaOrderItemsExt> dataList;

        // 生成发货单，只能是已付款的订单
        param.setOrderStatusList(Collections.singletonList(EOrderStatus.PAY.getValue()));

        // 获取管理员权限（角色地区范围、体系列表、团队列表）
        UserAuthorityDTO userAuthorityDTO = iUserServiceApi.getUserAuthority(SecurityUtils.getUserId()).getData();
        param.setAreaScopeList(userAuthorityDTO.getRoleAreaScopeList());
        param.setVertexIdList(userAuthorityDTO.getVertexIdList());
        param.setTeamList(userAuthorityDTO.getUserTeamList());

        if (1 == param.getMergeType()) {
            // 合单，需要根据传入的订单明细ID，进行查询
            if (CollectionUtils.isEmpty(param.getIdList())) {
                return AjaxResult.error(TransactionUtils.getContent(CommonMsgConstants.MISSING_PARAM));
            }
            dataList = iSaOrderItemsService.queryMergeByIdList(param.getIdList(), param, SecurityUtils.getPkCountry());
        } else {
            // 全部合单，需要根据传入的查询条件，进行查询
            dataList = iSaOrderItemsService.queryMergeByQueryParam(param, SecurityUtils.getPkCountry());
        }

        return toAjax(iSaDeliverService.mergeDeliver(param, dataList, SecurityUtils.getPkCountry(), SecurityUtils.getUserId()));
    }

    /**
     * 自提发货数据
     *
     * @param orderIdList 订单ID列表
     * @return
     */
    @GetMapping("/self-data")
    public AjaxResult selfData(@RequestParam("orderIdList") List<Long> orderIdList) {
        Integer pkCountry = SecurityUtils.getPkCountry();

        // 订单 + 明细列表
        List<SaOrderExt> saOrderExtList = iSaOrderService.queryOrderListByIdList(orderIdList, pkCountry);

        // 去重订单号列表
        List<String> orderCodeList = saOrderExtList.stream().map(SaOrderExt::getOrderCode).distinct().collect(Collectors.toList());
        // 校验订单是否存在进行中的签呈
        String checkStr = iOrderBusinessService.checkBusinessExist(orderCodeList, pkCountry);
        if (null != checkStr) {
            return AjaxResult.error(checkStr);
        }

        // 提货商品列表
        List<SelfDataProductVO> productList = new ArrayList<>();
        // 追溯码列表
        List<SelfDataBarCodeVO> barCodeList = new ArrayList<>();

        for (SaOrderExt saOrderExt : saOrderExtList) {
            for (SaOrderItemsExt saOrderItemsExt : saOrderExt.getOrderItemsExtList()) {
                if (EOrderStatus.PAY.getValue() != saOrderItemsExt.getOrderStatus()) {
                    // 不为已付款，则不允许进行自提
                    return AjaxResult.error(saOrderItemsExt.getProductName() + TransactionUtils.getContent(SaOrderMsgConstants.DELIVER_NOT_SELF));
                }

                // 自提商品数据
                productList.add(SelfDataProductVO.builder()
                        .itemId(saOrderItemsExt.getPkId())
                        .orderCode(saOrderItemsExt.getOrderCode())
                        .productName(saOrderItemsExt.getProductName())
                        .specsName(saOrderItemsExt.getSpecsName())
                        .quantity(saOrderItemsExt.getQuantity())
                        .memberCode(saOrderItemsExt.getMemberCode())
                        .memberName(saOrderItemsExt.getMemberName())
                        .build());

                for (int i = 0; i < saOrderItemsExt.getQuantity(); i++) {
                    // 追溯码数据
                    barCodeList.add(SelfDataBarCodeVO.builder()
                            .itemId(saOrderItemsExt.getPkId())
                            .orderCode(saOrderItemsExt.getOrderCode())
                            .productId(saOrderItemsExt.getPkProduct())
                            .productName(saOrderItemsExt.getProductName())
                            .specsName(saOrderItemsExt.getSpecsName())
                            .build());
                }
            }
        }

        return AjaxResult.success(SelfDataVO.builder()
                .productList(productList)
                .barCodeList(barCodeList)
                .build());
    }

    /**
     * 自提发货（提交签呈）
     *
     * @param param 自提发货入参
     * @return
     */
    @Log(module = EOperationModule.DELIVER_ORDER, business = EOperationBusiness.DELIVER_UNHANDLED, method = EOperationMethod.SUBMIT, remark = "自提签呈")
    @PostMapping("/self-deliver")
    public AjaxResult selfDeliver(@RequestBody SelfDeliverParam param) {
        if (null == param.getSignType() || CollectionUtil.isEmpty(param.getUserIdList()) || param.getPkStorehouse() == null
                || CollectionUtil.isEmpty(param.getItemIdList()) || CollectionUtil.isEmpty(param.getBarCodeList())) {
            // 缺少参数
            return AjaxResult.error(TransactionUtils.getContent(CommonMsgConstants.MISSING_PARAM));
        }
        Integer pkCountry = SecurityUtils.getPkCountry();
        // 有pk代表是前台发起的自提流程
        if (param.getPkId() != null) {
            SaOrderSelfLog saOrderSelfLog = saOrderSelfLogService.querySaOrderSelfLogById(param.getPkId());
            if (saOrderSelfLog == null || EApproveRechargeStatus.WAIT.getValue() != saOrderSelfLog.getApproveStatus()) {
                return AjaxResult.error(TransactionUtils.getContent(SaOrderMsgConstants.ORDER_EMPTY));
            }
        }

        // 订单明细ID列表
        List<Long> itemIdParamList = param.getItemIdList();
        // 追溯码列表（只保留追溯码不为空的）
        List<SelfDeliverBarCodeParam> barCodeParamList = param.getBarCodeList().stream().filter(selfDeliverBarCodeParam -> StringUtils.isNotEmpty(selfDeliverBarCodeParam.getBarCode())).collect(Collectors.toList());

        // 订单明细数据数量以及状态
        // 待发货订单明细列表
        List<SaOrderItemsExt> orderItemsList = iSaOrderItemsService.queryListByItemId(itemIdParamList, Collections.singletonList(EOrderStatus.PAY.getValue()), pkCountry);
        if (CollectionUtil.isEmpty(orderItemsList) || itemIdParamList.size() != orderItemsList.size()) {
            // 订单发生变化，请刷新后重试
            return AjaxResult.error(TransactionUtils.getContent(SaOrderMsgConstants.DELIVER_SELF_CHECK_CHARGE));
        }

        // 多单自提，如果有邮费，需要校验支付人是同一人才能进行自提
        if (null != param.getPostage()) {
            if (orderItemsList.stream().map(SaOrderItemsExt::getPkCreator).distinct().count() > 1) {
                return AjaxResult.error(TransactionUtils.getContent(SaOrderMsgConstants.DELIVER_SELF_CHECK_CREATE));
            }
        }

        // 是否有进行中的签呈
        List<String> orderCodeList = orderItemsList.stream().map(SaOrderItemsExt::getOrderCode).collect(Collectors.toList());
        // 校验订单是否存在进行中的签呈
        String checkStr = iOrderBusinessService.checkBusinessExist(orderCodeList, pkCountry);
        if (null != checkStr) {
            return AjaxResult.error(checkStr);
        }

        // 追溯码是否被占用
        List<String> barCodeStrList = barCodeParamList.stream().map(SelfDeliverBarCodeParam::getBarCode).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(barCodeStrList)) {
            // 校验条码是否重复
            if (barCodeStrList.size() != barCodeStrList.stream().distinct().count()) {
                // 追溯码存在重复
                return AjaxResult.error(TransactionUtils.getContent(SaOrderMsgConstants.DELIVER_CHECK_BARCODE_REPEAT));
            }

            // 查询已打印未使用的条码数据
            List<BarCodeDTO> barCodeList = iBarCodeServiceApi.queryPrintBarCode(barCodeStrList, pkCountry).getData();
            if (barCodeList.size() < barCodeStrList.size()) {
                // 追溯码不存在
                return AjaxResult.error(TransactionUtils.getContent(SaOrderMsgConstants.DELIVER_CHECK_BARCODE_USED));
            }

            barCodeList = barCodeList.stream().filter((barCodeDTO) -> EBarcodeStatus.BOUND.getValue() != barCodeDTO.getCodeStatus()).collect(Collectors.toList());
            if (barCodeList.size() < barCodeStrList.size()) {
                // 追溯码已使用
                return AjaxResult.error(TransactionUtils.getContent(SaOrderMsgConstants.DELIVER_CHECK_BARCODE_USED));
            }

            // 遍历入参以及条码数据，赋值条码ID用以保存，并且校验条码与产品是否一致
            for (SelfDeliverBarCodeParam barCodeParam : barCodeParamList) {
                for (BarCodeDTO barCodeDTO : barCodeList) {
                    if (barCodeParam.getBarCode().equals(barCodeDTO.getBarCode())) {
                        if (!barCodeParam.getProductId().equals(barCodeDTO.getPkProduct())) {
                            // 追溯码与产品不对应
                            return AjaxResult.error(barCodeParam.getBarCode() + TransactionUtils.getContent(SaOrderMsgConstants.DELIVER_CHECK_BARCODE_NOT));
                        } else {
                            barCodeParam.setBarCodeId(barCodeDTO.getPkId());
                        }
                    }
                }
            }
        }

        // 提交签呈
        String str = iSaDeliverBusinessService.selfDeliverSubmit(param, orderItemsList, barCodeParamList, userTokenService.getLoginUser());
        if (null != str) {
            return AjaxResult.error(str);
        }
        return AjaxResult.success();
    }

}
