/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @Title: ShoppingCart
 * @Package cn.freemud.controller
 * @Description:
 * @author: ping.wu
 * @date: 2018/5/18 18:07
 * @version V1.0
 * @Copyright: 2018 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
package cn.freemud.demo.controller;

import cn.freemud.base.entity.BaseResponse;
import cn.freemud.demo.adapter.service.*;
import cn.freemud.demo.entities.bo.goods.*;
import cn.freemud.demo.entities.bo.goods.add.BaseAddGoodsBO;
import cn.freemud.demo.entities.bo.goods.list.ListCartGoodsBO;
import cn.freemud.demo.entities.bo.goods.update.UpdateAddGoodsBO;
import cn.freemud.demo.entities.dto.BaseApportionVO;
import cn.freemud.demo.entities.dto.goods.add.BaseAddGoodsVO;
import cn.freemud.demo.entities.dto.goods.add.AddGoodsRequestDTO;
import cn.freemud.demo.entities.dto.goods.add.list.BaseListCartGoodsVO;
import cn.freemud.demo.entities.dto.goods.add.update.BaseUpdateGoodsQtyVO;
import cn.freemud.demo.enums.BizTypeEnum;
import cn.freemud.demo.factory.ServiceFactory;
import cn.freemud.demo.service.ShoppingCartService;
import cn.freemud.demo.service.impl.AbstractAddGoodsService;
import cn.freemud.demo.service.impl.AbstractApportionService;
import cn.freemud.demo.service.impl.AbstractListCartGoodsService;
import cn.freemud.demo.service.impl.AbstractUpdateGoodsQtyService;
import cn.freemud.demo.utils.BizTypeUtil;
import cn.freemud.entities.dto.GetMemberInfoRequestDto;
import cn.freemud.entities.vo.*;
import cn.freemud.enums.OrderChannelType;
import cn.freemud.enums.ResponseResult;
import cn.freemud.service.ShoppingCartNewService;
import cn.freemud.service.impl.ShoppingCartMallServiceImpl;
import cn.freemud.service.impl.ShoppingCartMealServiceImpl;
import cn.freemud.service.impl.ShoppingCartNewServiceImpl;
import cn.freemud.service.impl.ShoppingCartToolsServiceImpl;
import cn.freemud.utils.ResponseUtil;
import com.freemud.api.assortment.datamanager.entity.vo.AssortmentCustomerInfoVo;
import com.freemud.api.assortment.datamanager.enums.IappIdType;
import com.freemud.api.assortment.datamanager.manager.customer.AssortmentCustomerInfoManager;
import com.freemud.application.sdk.api.base.SDKCommonBaseContextWare;
import com.freemud.application.sdk.api.log.ApiAnnotation;
import com.freemud.application.sdk.api.log.LogParams;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.toList;

@RestController
@RequestMapping(value = "/shoppingCart/demo", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
@Api(value = "购物车 controller", tags = {"购物车管理接口"})
public class ShoppingCartDemoController {

    @Autowired
    private AssortmentCustomerInfoManager customerInfoManager;

    @Autowired
    private AddGoodsBOAdapter addGoodsBOAdapter;

    @Autowired
    private AddGoodsVOAdapter addGoodsVOAdapter;

    @Autowired
    private UpdateGoodsQtyBOAdapter updateGoodsQtyBOAdapter;

    @Autowired
    private UpdateGoodsQtyVOAdapter updateGoodsQtyVOAdapter;

    @Autowired
    private ListCartGoodsBOAdapter listCartGoodsBOAdapter;

    @Autowired
    private ListCartGoodsVOAdapter listCartGoodsVOAdapter;

    @Autowired
    private ApportionBOAdapter apportionBOAdapter;

    @Autowired
    private ApportionVOAdapter apportionVOAdapter;

    @Resource
    private MapperFacade mapperFacade;

    @Autowired
    private ShoppingCartService shoppingCartService;
    /**
     * 向购物车中添加商品
     */
    @ApiAnnotation(logMessage = "addGoods")
    @PostMapping(value = "/addGoods")
    public BaseResponse addGoods(@LogParams @RequestBody Map<String, Object> request) {

        AddGoodsRequestDTO baseRequestDTO = mapperFacade.map(request, AddGoodsRequestDTO.class);

        /**
         * 业务判断
         */
        BizTypeEnum bizType = BizTypeUtil.getBizType(baseRequestDTO.getPartnerId());
        /**
         * 工程模式创建service
         */
        AbstractAddGoodsService addGoodsServiceInstance = ServiceFactory.createAddGoodsServiceInstance(bizType.getCode());
        /**
         * dto -> bo
         */
        BaseAddGoodsBO addGoodsBOInstance = addGoodsBOAdapter.convert2AddGoodsBO(bizType.getCode(), baseRequestDTO);
        /**
         * 具体业务逻辑
         */
        ShoppingCartGoodsBO addGoodsResponseBO = addGoodsServiceInstance.addGoods(addGoodsBOInstance);
        /**
         * bo -> vo
         */
        BaseAddGoodsVO baseAddGoodsVO = addGoodsVOAdapter.convert2AddGoodsVO(bizType.getCode(), addGoodsResponseBO);

        return ResponseUtil.success(baseAddGoodsVO);

    }

    /**
     * 修改购物车中商品数量
     */
    @ApiAnnotation(logMessage = "updateGoodsQty")
    @PostMapping(value = "/updateGoodsQty")
    public BaseResponse updateGoodsQty(@LogParams @RequestBody Map<String, Object> request) {

        UpdateGoodsQtyRequestDTO baseRequestDTO = mapperFacade.map(request, UpdateGoodsQtyRequestDTO.class);

        /**
         * 是否用新字段,还是沿用老逻辑
         */
        BizTypeEnum bizType = BizTypeUtil.getBizType(baseRequestDTO.getPartnerId());
        AbstractUpdateGoodsQtyService updateGoodsQtyServiceInstance = ServiceFactory.createUpdateGoodsQtyServiceInstance(bizType.getCode());
        UpdateAddGoodsBO addGoodsBOInstance = updateGoodsQtyBOAdapter.convert2UpdateAddGoodsBO(bizType.getCode(), baseRequestDTO);
        ShoppingCartGoodsBO addGoodsResponseBO = updateGoodsQtyServiceInstance.updateGoodsQty(addGoodsBOInstance);
        BaseUpdateGoodsQtyVO baseAddGoodsVO = updateGoodsQtyVOAdapter.convert2AddGoodsVO(bizType.getCode(), addGoodsResponseBO);

        return ResponseUtil.success(baseAddGoodsVO);

    }

    /**
     * 查询购物车信息
     */
    @ApiAnnotation(logMessage = "listCartGoods")
    @PostMapping(value = "/listCartGoods")
    public BaseResponse listCartGoods(@LogParams @RequestBody Map<String, Object> request) {

        /**
         * 这里是为了兼容老入口,老入口不用之后,这里可以直接删掉
         */
        List<ShoppingCartInfoRequestVo.SendGoods> sendGoods = (List<ShoppingCartInfoRequestVo.SendGoods>)request.get("sendGoods");
        /**
         * 这里是为了兼容老入口,老入口不用之后,这里可以直接删掉
         */
        ListCartGoodsRequestDTO baseRequestDTO = mapperFacade.map(request, ListCartGoodsRequestDTO.class);
        if (CollectionUtils.isNotEmpty(sendGoods)){
            List<ListCartGoodsBO.SendGoods> newSendGoods = mapperFacade.mapAsList(sendGoods, ListCartGoodsBO.SendGoods.class);
            baseRequestDTO.setSendGoods(newSendGoods);
        }

        /**
         * 是否用新字段,还是沿用老逻辑
         */
        BizTypeEnum bizType = BizTypeUtil.getBizType(baseRequestDTO.getPartnerId());
        AbstractListCartGoodsService listCartGoodsServiceInstance = ServiceFactory.createListCartGoodsServiceInstance(bizType.getCode());
        ListCartGoodsBO listCartGoodsBO = listCartGoodsBOAdapter.convert2ListCartGoodsBO(bizType.getCode(), baseRequestDTO);
        ShoppingCartGoodsBO addGoodsResponseBO = listCartGoodsServiceInstance.listCartGoods(listCartGoodsBO);
        BaseListCartGoodsVO baseListCartGoodsVO = listCartGoodsVOAdapter.convert2ListCartGoodsVO(bizType.getCode(), addGoodsResponseBO);

        // 添加购物车商品总价和加价购商品总价,现在是自己计算,后面需要优化为促销计算, 这段要删除
        baseListCartGoodsVO.setShoppingCartGoodsAmount(0L);
        if (CollectionUtils.isNotEmpty(baseListCartGoodsVO.getProducts())){
            long shoppincCartGoodsAmount = baseListCartGoodsVO.getProducts().stream().mapToLong(CartGoods::getAmount).sum();
            baseListCartGoodsVO.setShoppingCartGoodsAmount(shoppincCartGoodsAmount);
        }

        if (CollectionUtils.isNotEmpty(listCartGoodsBO.getSendGoods())){
            PremiumExchangeRequestVo premiumRequest = new PremiumExchangeRequestVo();
            premiumRequest.setPartnerId(listCartGoodsBO.getPartnerId());
            premiumRequest.setActivityCode(listCartGoodsBO.getActivityCode());
            premiumRequest.setCouponCode(listCartGoodsBO.getCouponCode());
            premiumRequest.setMenuType(listCartGoodsBO.getMenuType());
            premiumRequest.setOrderType(listCartGoodsBO.getOrderType());
            premiumRequest.setSessionId(listCartGoodsBO.getSessionId());
            premiumRequest.setShopId(listCartGoodsBO.getShopId());
            premiumRequest.setVersion(listCartGoodsBO.getVersion());
            BaseResponse<PremiumExchangeResponseVo> premiumExchangeResponseVoBaseResponse = SDKCommonBaseContextWare.getBean(ShoppingCartNewServiceImpl.class).premiumExchange(premiumRequest);
            List<PremiumExchangeResponseVo.PremiumExchangeProduct> chooseSendGoodList = null;
            if (premiumExchangeResponseVoBaseResponse != null && ResponseResult.SUCCESS.getCode().equals(premiumExchangeResponseVoBaseResponse.getCode())
                    && premiumExchangeResponseVoBaseResponse.getResult() != null && CollectionUtils.isNotEmpty(premiumExchangeResponseVoBaseResponse.getResult().getProducts())){
                List<PremiumExchangeResponseVo.PremiumExchangeProduct> products = premiumExchangeResponseVoBaseResponse.getResult().getProducts();
                List<String> sendGoodsIdList = listCartGoodsBO.getSendGoods().stream().map(p -> p.getGoodsId()).collect(toList());
                chooseSendGoodList = products.stream().filter(p -> sendGoodsIdList.contains(p.getSkuId()) || sendGoodsIdList.contains(p.getSpuId())).collect(toList());
                long sendGoodsAmount = chooseSendGoodList.stream().mapToLong(PremiumExchangeResponseVo.PremiumExchangeProduct::getNowPrice).sum();
                baseListCartGoodsVO.setSendGoodsAmount(sendGoodsAmount);
            }
            shoppingCartService.updateForPopupWindow(baseListCartGoodsVO,premiumExchangeResponseVoBaseResponse.getResult().getShowType(),chooseSendGoodList,baseRequestDTO.getSendGoods());
        }
        // 添加购物车商品总价和加价购商品总价,现在是自己计算,后面需要优化为促销计算, 这段要删除

        return ResponseUtil.success(baseListCartGoodsVO);

    }

    /**
     * 获取购物车均摊详情，点 "去支付" 时调用
     *
     * @param getShoppingCartGoodsApportionRequestVo
     * @return
     */
    @ApiAnnotation(logMessage = "getShoppingCartGoodsApportion")
    @PostMapping(value = "/getShoppingCartGoodsApportion")
    public BaseResponse getShoppingCartGoodsApportion(@Validated @LogParams @RequestBody GetShoppingCartGoodsApportionRequestVo getShoppingCartGoodsApportionRequestVo) {
        if (getShoppingCartGoodsApportionRequestVo == null || getShoppingCartGoodsApportionRequestVo.getShoppingCartInfoRequestVo() == null) {
            return ResponseUtil.error(ResponseResult.NOT_LOGIN);
        }
        ShoppingCartInfoRequestVo shoppingCartInfoRequestVo = getShoppingCartGoodsApportionRequestVo.getShoppingCartInfoRequestVo();
        ShoppingCartNewService instanceByRequest = getInstanceByRequest(shoppingCartInfoRequestVo);
        if (instanceByRequest instanceof ShoppingCartNewServiceImpl){
            /**
             * 是否用新字段,还是沿用老逻辑
             */
            BizTypeEnum bizType = BizTypeUtil.getBizType(shoppingCartInfoRequestVo.getPartnerId());
            AbstractApportionService apportionServiceInstance = ServiceFactory.createGetShoppingCartGoodsApportionServiceInstance(bizType.getCode());
            ShoppingCartGoodsApportionBO shoppingCartGoodsApportionBO = apportionBOAdapter.convert2ApportionBO(bizType.getCode(), getShoppingCartGoodsApportionRequestVo);
            ShoppingCartApportionBO apportion = apportionServiceInstance.getApportion(shoppingCartGoodsApportionBO);
            BaseApportionVO baseApportionVO = apportionVOAdapter.convert2ApportionVO(bizType.getCode(), apportion);
            return ResponseUtil.success(baseApportionVO);

        }
        return getInstanceByRequest(shoppingCartInfoRequestVo).
                getShoppingCartGoods(shoppingCartInfoRequestVo,
                        getShoppingCartGoodsApportionRequestVo.getPremiumExchangeActivity());
    }


    private ShoppingCartNewService getInstanceByRequest(BaseRequestVo requestVo) {
        if(requestVo.getChannelType() != null && OrderChannelType.SAASMALL.getCode().equals(requestVo.getChannelType())) {
            return SDKCommonBaseContextWare.getBean(ShoppingCartMallServiceImpl.class);
        } else {
            return getInstanceBySessionId(requestVo.getSessionId());
        }
    }

    private ShoppingCartNewService getInstanceBySessionId(String sessionId) {

        AssortmentCustomerInfoVo assortmentCustomerInfoVo = customerInfoManager.getCustomerInfoByObject(sessionId);
        if (assortmentCustomerInfoVo == null || StringUtils.isBlank(assortmentCustomerInfoVo.getIappId())) {
            return getInstanceByIAppId(IappIdType.IBZ_DC_XCX.getCode());
        }
        String iAppId = assortmentCustomerInfoVo.getIappId();
        return getInstanceByIAppId(iAppId);
    }

    private ShoppingCartNewService getInstanceByIAppId(String iAppId) {
        if (IappIdType.WC_XCX.getCode().equals(iAppId)) {
            //围餐
            return SDKCommonBaseContextWare.getBean(ShoppingCartMealServiceImpl.class);
        }
        return SDKCommonBaseContextWare.getBean(ShoppingCartNewServiceImpl.class);
    }

    /**
     * 清空购物车{技术支持用}
     */
    @ApiAnnotation(logMessage = "clear/goods")
    @PostMapping(value = "/clearGoods")
    public BaseResponse clearGoods(@Validated @LogParams @RequestBody ShoppingCartClearToolsRequestVo request) {
        return SDKCommonBaseContextWare.getBean(ShoppingCartToolsServiceImpl.class).clear(request);
    }


    /**
     * 线下订单查询接口
     */
    @ApiAnnotation(logMessage = "/getMemberInfo")
    @PostMapping(value = "/getMemberInfo")
    public BaseResponse getMemberInfo(@LogParams @RequestBody GetMemberInfoRequestDto request) {
        return SDKCommonBaseContextWare.getBean(ShoppingCartNewServiceImpl.class).getMemberInfo(request);
    }

}
