/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @Title: CollageOrderServiceImpl
 * @Package cn.freemud.service.impl
 * @Description:
 * @author: hui.miao
 * @date: 2020/10/11 20:55
 * @version V1.0
 * @Copyright: 2020 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
package cn.freemud.service.impl;


import cn.freemud.base.entity.BaseResponse;
import cn.freemud.base.log.LogTreadLocal;
import cn.freemud.base.util.DateUtil;
import cn.freemud.entities.dto.order.CreateOrderOperateDto;
import cn.freemud.entities.dto.shoppingCart.CollageOrderDto;
import cn.freemud.entities.dto.wechat.*;
import cn.freemud.entities.vo.CreateOrderResponseVo;
import cn.freemud.entities.vo.QueryOrderVo;
import cn.freemud.enums.ResponseResult;
import cn.freemud.service.thirdparty.EcologyAdminApplicationClient;
import cn.freemud.service.thirdparty.ShoppingCartClient;
import cn.freemud.service.thirdparty.WeChatClient;
import com.freemud.api.assortment.datamanager.entity.vo.AssortmentCustomerInfoVo;
import com.freemud.api.assortment.datamanager.manager.customer.AssortmentCustomerInfoManager;
import com.freemud.application.sdk.api.log.ApiLog;
import com.freemud.application.sdk.api.ordercenter.enums.ResponseResultEnum;
import com.freemud.application.sdk.api.ordercenter.response.orderInfo.OrderCostResp;
import com.freemud.application.sdk.api.ordercenter.response.orderInfo.OrderSettlementResp;
import com.freemud.sdk.api.assortment.order.enums.OldOrderAccountType;
import com.freemud.sdk.api.assortment.order.request.order.BaseQueryOrderRequest;
import com.freemud.sdk.api.assortment.order.request.order.GroupBuyRequest;
import com.freemud.sdk.api.assortment.order.response.order.GroupBuyResponse;
import cn.freemud.entities.vo.CreateOrderVo;
import cn.freemud.entities.vo.WechatGroupBuyVo;
import cn.freemud.enums.OrderMarketType;
import cn.freemud.service.CollageOrderService;
import cn.freemud.utils.ResponseUtil;
import com.freemud.sdk.api.assortment.order.response.order.QueryOrderByIdResponse;
import com.freemud.sdk.api.assortment.order.response.order.QueryOrdersResponse;
import com.freemud.sdk.api.assortment.order.service.OrderCenterSdkService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CollageOrderServiceImpl implements CollageOrderService {
    @Autowired
    private OrderServiceImpl orderService;
    @Autowired
    private OrderCenterSdkService orderCenterSdkService;
    @Autowired
    private AssortmentCustomerInfoManager customerInfoManager;
    @Autowired
    private EcologyAdminApplicationClient ecologyAdminApplicationClient;
    @Autowired
    private WeChatClient weChatClient;
    @Autowired
    private ShoppingCartClient shoppingCartClient;

    /**
     * 创建拼单订单
     */
    @Override
    public BaseResponse create(CreateOrderVo createOrderVo) {
        // 校验当前拼单缓存状态 若不为0-拼单中直接返回错误提示
        CollageOrderDto collageOrderDto = new CollageOrderDto();
        collageOrderDto.setSessionId(createOrderVo.getSessionId());
        collageOrderDto.setPartnerId(createOrderVo.getPartnerId());
        collageOrderDto.setShopId(createOrderVo.getShopId());
        collageOrderDto.setCreateCollageUserId(createOrderVo.getUserId());
        BaseResponse<Integer> collageOrderResponse = shoppingCartClient.getCollageOrderStatus(collageOrderDto);
        if (null == collageOrderResponse || null == collageOrderResponse.getResult() || -1 == collageOrderResponse.getResult()) {
            return ResponseUtil.error(ResponseResult.COLLAGE_ORDER_CREATE_ERROR_NOT_EXIST);
        } else if (1 == collageOrderResponse.getResult()) {
            return ResponseUtil.error(ResponseResult.COLLAGE_ORDER_CREATE_ERROR_PAYED);
        } else if (2 == collageOrderResponse.getResult()) {
            return ResponseUtil.error(ResponseResult.COLLAGE_ORDER_CREATE_ERROR_NOT_EXIST);
        } else if (3 == collageOrderResponse.getResult()) {
            return ResponseUtil.error(ResponseResult.COLLAGE_ORDER_CREATE_ERROR_PAYING);
        }

        // 标记订单类型-4 拼单
        createOrderVo.setMarketingType(OrderMarketType.COLLAGE.getIndex());

        BaseResponse orderCreateResponse = this.orderService.createOrderNew(createOrderVo);

//        if (null != orderCreateResponse && null != orderCreateResponse.getResult()) {
//            Object result = orderCreateResponse.getResult();
//
//            String oid = null;
//
//            if (result instanceof CreateOrderOperateDto) {
//                oid = ((CreateOrderOperateDto) result).getFatherOrderBean().getOid();
//            } else if (result instanceof CreateOrderResponseVo) {
//                oid = ((CreateOrderResponseVo) result).getOid();
//            }
//
//            // 清空拼单购物车
//            collageOrderDto = new CollageOrderDto();
//            collageOrderDto.setSessionId(StringUtils.isBlank(createOrderVo.getSessionId()) ? oid : createOrderVo.getSessionId());
//            collageOrderDto.setPartnerId(createOrderVo.getPartnerId());
//            collageOrderDto.setShopId(createOrderVo.getShopId());
//            collageOrderDto.setCreateCollageUserId(createOrderVo.getUserId());
//            collageOrderDto.setOrderCode(oid);
//            collageOrderDto.setStatus(3);//支付中
//            shoppingCartClient.updateCollageOrder(collageOrderDto);
//        }

        return orderCreateResponse;
    }

    /**
     * 查询拼单详情
     * @param queryOrderVo
     * @return
     */
    @Override
    public BaseResponse queryCollageOrderById(QueryOrderVo queryOrderVo) {
        return this.orderService.queryCollageOrderById(queryOrderVo.getOperation(),queryOrderVo.getSessionId(), queryOrderVo.getOid(),queryOrderVo.getPartnerId(),queryOrderVo.getChannelType());
    }

    /**
     * 群收款详情
     * @param requestVo
     * @return
     */
    @Override
    public BaseResponse groupBuyDetail(WechatGroupBuyVo requestVo) {
        // 获取拼单订单信息
        QueryOrdersResponse.DataBean.OrderBean order = this.queryOrderByOrderCode(requestVo.getPartnerId(), requestVo.getOrderCode());

        if (null == order) {
            return ResponseUtil.error(ResponseResult.ORDER_NOT_EXIST);
        }

        GroupBuyDetailResp groupBuyDetailResp = new GroupBuyDetailResp();
        groupBuyDetailResp.setOrderCode(order.getOid());
        groupBuyDetailResp.setPartnerId(order.getCompanyId());
        groupBuyDetailResp.setShopId(order.getShopId());
        groupBuyDetailResp.setOrderAmount(order.getActualPayAmount());

        List<QueryOrdersResponse.DataBean.OrderBean.ProductBean> productList = order.getProductList();

        // 群收款支付用户列表 商品加购人ID不是订单创建人的列表
        List<GroupBuyDto> list = new ArrayList<>();
        GroupBuyDto groupBuyDto;
        List<String> payerUserIdList = productList.stream().filter(product -> !order.getUserId().equals(product.getUserId())).map(QueryOrdersResponse.DataBean.OrderBean.ProductBean::getUserId).distinct().collect(Collectors.toList());

        // 付款人列表为空时直接返回错误提示
        if (null == payerUserIdList || payerUserIdList.isEmpty()) {
            return ResponseUtil.error(ResponseResult.ORDER_GROUP_BUY_LIST_EMPTY);
        }

        for (String payerUserId : payerUserIdList) {
            groupBuyDto = new GroupBuyDto();
            groupBuyDto.setUserId(payerUserId);
            // 商品费用
            Long itemAmount = productList.stream().filter(product -> (payerUserId.equals(product.getUserId()) && null != product.getSettlementPrice())).map(QueryOrdersResponse.DataBean.OrderBean.ProductBean::getSettlementPrice).reduce(Long::sum).orElse(0L);
            // 包装费用
            Long packAmount = productList.stream().filter(product -> (payerUserId.equals(product.getUserId()) && null != product.getPackPrice())).map(QueryOrdersResponse.DataBean.OrderBean.ProductBean::getPackPrice).reduce(Long::sum).orElse(0L);
            // 运费分摊
            Long deliveryAmount = 0L;
            if (order.getOrderCostDetailList() != null) {
                OrderCostResp orderCostResp = order.getOrderCostDetailList().stream().filter(detail -> (detail.getCostType().equals(2) && detail.getBillType().equals(1))).findFirst().orElse(new OrderCostResp());
                BigDecimal deliveryPrice = orderCostResp.getActualCostAmount() == null ? new BigDecimal(0) : orderCostResp.getActualCostAmount();
                // 运费均摊时算上拼单发起人
                deliveryAmount = Math.floorDiv(deliveryPrice.longValue(), payerUserIdList.size() + 1);
            }
            // 微信拼单优惠分摊
            Long wechatDiscountAmount = 0L;
            if (order.getOrderSettlementDetailList() != null && !order.getOrderSettlementDetailList().isEmpty()) {
                List<OrderSettlementResp> settlements = order.getOrderSettlementDetailList().stream().filter(settlement -> (OldOrderAccountType.WEIXIN.equals(settlement.getSettlementType()))).collect(Collectors.toList());
                for (OrderSettlementResp settlement : settlements) {
                    wechatDiscountAmount += settlement.getShopDiscountAmount() + settlement.getPlatformDiscountAmount();
                }
                wechatDiscountAmount = Math.floorDiv(wechatDiscountAmount, payerUserIdList.size() + 1);
            }

            groupBuyDto.setAmount(itemAmount + packAmount + deliveryAmount - wechatDiscountAmount);
            groupBuyDto.setNickName(productList.stream().filter(product -> payerUserId.equals(product.getUserId())).findFirst().get().getNickName());
            groupBuyDto.setPhotoUrl(productList.stream().filter(product -> payerUserId.equals(product.getUserId())).findFirst().get().getPhotoUrl());
            list.add(groupBuyDto);
        }
        groupBuyDetailResp.setPayerList(list);
        groupBuyDetailResp.setPayerNum(list.size());
        groupBuyDetailResp.setTotalAmount(list.stream().map(GroupBuyDto::getAmount).reduce(Long::sum).get());

        return ResponseUtil.success(groupBuyDetailResp);
    }

    /**
     * 创建群收款
     * @param requestVo
     * @return
     */
    @Override
    public BaseResponse createGroupBuy(WechatGroupBuyVo requestVo) {
        // 获取拼单订单信息
        QueryOrdersResponse.DataBean.OrderBean order = this.queryOrderByOrderCode(requestVo.getPartnerId(), requestVo.getOrderCode());

        if (null == order) {
            ResponseUtil.error(ResponseResult.ORDER_NOT_EXIST);
        }

        // 根据sessionId获取当前用户信息以及appid
        AssortmentCustomerInfoVo userInfo = customerInfoManager.getCustomerInfoByObject(requestVo.getSessionId());
        GetAuthorizerRequestDto getAuthorizerRequestDto = new GetAuthorizerRequestDto();
        getAuthorizerRequestDto.setPartnerId(requestVo.getPartnerId());
        getAuthorizerRequestDto.setAuthorizerAppid(userInfo.getWxAppId());

        // 通过partnerId以及appid获取access_token
        ApiLog.debug("collage access_token request partnerId:{} appId:{}", requestVo.getPartnerId(), userInfo.getWxAppId());
        GetTokenResponseDto getTokenResponseDto = ecologyAdminApplicationClient.getAuthorizerAccessToken(getAuthorizerRequestDto);
        String accessToken = getTokenResponseDto.getResult().getAccessToken();
        ApiLog.debug("collage access_token response access_token:{}", accessToken);

        // 构造群收款订单创建请求对象
        GroupBuyRequest groupBuyRequest = new GroupBuyRequest();

        // 订单编号
        groupBuyRequest.setOut_trade_no(order.getOid());

        // 收款人（拼单发起人）openId
        groupBuyRequest.setRecv_openid(userInfo.getOpenId());

        // 付款人列表（查询拼单订单详情，根据商品自动计算价格，订单级别优惠分摊）
        GroupBuyRequest.PayList payList = new GroupBuyRequest.PayList();
        List<GroupBuyRequest.UserInfo> userInfoList = new ArrayList<>();

        List<QueryOrdersResponse.DataBean.OrderBean.ProductBean> productList = order.getProductList();
        List<OrderSettlementResp> settlementList = order.getOrderSettlementDetailList();

        // 群收款支付用户列表
        List<String> payerOpenIdList = productList.stream().filter(product -> !userInfo.getMemberId().equals(product.getUserId())).map(QueryOrdersResponse.DataBean.OrderBean.ProductBean::getOpenId).distinct().collect(Collectors.toList());

        // 付款人列表为空时直接返回错误提示
        if (null == payerOpenIdList || payerOpenIdList.isEmpty()) {
            return ResponseUtil.error(ResponseResult.ORDER_GROUP_BUY_LIST_EMPTY);
        }

        // 组装群收款付款人列表
        GroupBuyRequest.UserInfo groupBuyUserInfo;
        for (String payerOpenId : payerOpenIdList) {
            // 商品费用
            Long itemAmount = productList.stream().filter(product -> (payerOpenId.equals(product.getOpenId()) && null != product.getSettlementPrice())).map(QueryOrdersResponse.DataBean.OrderBean.ProductBean::getSettlementPrice).reduce(Long::sum).orElse(0L);
            // 包装费用
            Long packAmount = productList.stream().filter(product -> (payerOpenId.equals(product.getOpenId()) && null != product.getPackPrice())).map(QueryOrdersResponse.DataBean.OrderBean.ProductBean::getPackPrice).reduce(Long::sum).orElse(0L);
            // 运费分摊
            Long deliveryAmount = 0L;
            if (order.getOrderCostDetailList() != null && !order.getOrderCostDetailList().isEmpty()) {
                OrderCostResp orderCostResp = order.getOrderCostDetailList().stream().filter(detail -> (detail.getCostType().equals(2) && detail.getBillType().equals(1))).findFirst().orElse(new OrderCostResp());
                BigDecimal deliveryPrice = orderCostResp.getActualCostAmount() == null ? new BigDecimal(0) : orderCostResp.getActualCostAmount();
                deliveryAmount = Math.floorDiv(deliveryPrice.longValue(), payerOpenIdList.size() + 1);
            }
            // 微信拼单优惠分摊
            Long wechatDiscountAmount = 0L;
            if (order.getOrderSettlementDetailList() != null && !order.getOrderSettlementDetailList().isEmpty()) {
                List<OrderSettlementResp> settlements = order.getOrderSettlementDetailList().stream().filter(settlement -> (OldOrderAccountType.WEIXIN.equals(settlement.getSettlementType()))).collect(Collectors.toList());
                for (OrderSettlementResp settlement : settlements) {
                    wechatDiscountAmount += settlement.getShopDiscountAmount() + settlement.getPlatformDiscountAmount();
                }
                wechatDiscountAmount = Math.floorDiv(wechatDiscountAmount, payerOpenIdList.size() + 1);
            }

            Long amount = itemAmount + packAmount + deliveryAmount - wechatDiscountAmount;
            groupBuyUserInfo = new GroupBuyRequest.UserInfo();
            groupBuyUserInfo.setOpenid(payerOpenId);
            groupBuyUserInfo.setAmount(Integer.parseInt(String.valueOf(amount)));
            userInfoList.add(groupBuyUserInfo);
        }

        payList.setUser_info(userInfoList);
        groupBuyRequest.setPay_list(payList);

        // 业务场景 1 其他（暂未解决后端上传收款图问题）
        groupBuyRequest.setScene(1);

        // 描述信息 Desc（订单商户+日期）
        GroupBuyRequest.Desc desc = new GroupBuyRequest.Desc();
        desc.setText_desc(order.getShopName() + DateUtil.getCurrentDate(DateUtil.FORMAT_yyyyMMdd));
        groupBuyRequest.setDesc(desc);

        ApiLog.debug("collage groupBuy request param:{}", groupBuyRequest);
        GroupBuyResponse groupBuyResponse = weChatClient.groupBuyCreateOrder(accessToken, groupBuyRequest);
        ApiLog.debug("collage groupBuy response return:{}", groupBuyResponse);

        if (null != groupBuyResponse && groupBuyResponse.getErrcode() == 0) {
            GroupBuyResp groupBuyResp = new GroupBuyResp();
            groupBuyResp.setGroupBuyOrderId(groupBuyResponse.getOrder_id());
            return ResponseUtil.success(groupBuyResp);
        } else {
            return ResponseUtil.error(null == groupBuyResponse ? ResponseResult.SYSTEM_BUSINESS_ERROR.getCode() : String.valueOf(groupBuyResponse.getErrcode()), null == groupBuyResponse ? "创建群收款失败" : groupBuyResponse.getErrmsg());
        }
    }

    /**
     * 根据orderCode获取订单信息
     * @param orderCode
     * @return
     */
    private QueryOrdersResponse.DataBean.OrderBean queryOrderByOrderCode(String partnerId, String orderCode) {
        // 获取拼单订单信息，若类型不是拼单直接返回报错
        BaseQueryOrderRequest baseQueryOrderRequest = new BaseQueryOrderRequest();
        baseQueryOrderRequest.setPartnerId(partnerId);
        baseQueryOrderRequest.setOrderId(orderCode);
        baseQueryOrderRequest.setTrackingNo(LogTreadLocal.getTrackingNo());
        QueryOrderByIdResponse response = orderCenterSdkService.queryOrderById(baseQueryOrderRequest);

        if (!ResponseResultEnum.SUCCESS.getCode().equals(String.valueOf(response.getErrcode())) || response.getData() == null) {
            return null;
        }

        QueryOrdersResponse.DataBean.OrderBean order = response.getData();

        if (null == order.getMarketingType() || OrderMarketType.COLLAGE.getIndex() != order.getMarketingType()) {
            return null;
        }

        return order;
    }
}
