package cn.freemud.service.impl;

import cn.freemud.adapter.LightApplicationConvertToAssortmentSdkAdapter;
import cn.freemud.base.util.DateUtil;
import cn.freemud.constant.ResponseCodeConstant;
import cn.freemud.entities.bo.CheckSvcAmountBo;
import cn.freemud.entities.bo.CheckSvcAmountResponse;
import cn.freemud.entities.dto.ConfirmOrderDto;
import cn.freemud.entities.dto.StoreResponseDto;
import cn.freemud.entities.dto.order.CreateCashierOrderDto;
import cn.freemud.entities.dto.order.CreatePrepayRequestDto;
import cn.freemud.entities.dto.store.StoreMixResponseDto;
import cn.freemud.entities.vo.CreateOrderResponseVo;
import cn.freemud.entities.vo.PaysuccessNoticeMessage;
import cn.freemud.entities.vo.order.CashierCheckResponseVo;
import cn.freemud.enums.OrderBeanType;
import cn.freemud.enums.ResponseResult;
import cn.freemud.enums.UserLoginChannelEnum;
import cn.freemud.interceptor.ServiceException;
import cn.freemud.service.CashierOrderService;
import cn.freemud.service.business.OrderBusinessService;
import cn.freemud.service.store.StoreManager;
import cn.freemud.utils.AppLogUtil;
import com.alibaba.fastjson.JSONObject;
import com.freemud.api.assortment.datamanager.entity.vo.AssortmentCustomerInfoVo;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import com.freemud.application.sdk.api.ordercenter.adapter.OrderCenterSdkAdapter;
import com.freemud.application.sdk.api.ordercenter.entities.v1.OrderBeanV1;
import com.freemud.application.sdk.api.ordercenter.enums.*;
import com.freemud.application.sdk.api.ordercenter.request.OrderChangeStateReq;
import com.freemud.application.sdk.api.ordercenter.request.OrderExtInfoDto;
import com.freemud.application.sdk.api.ordercenter.request.OrderExtendedReq;
import com.freemud.application.sdk.api.ordercenter.request.create.CreateOrderRequest;
import com.freemud.application.sdk.api.ordercenter.response.OrderBaseResp;
import com.freemud.application.sdk.api.ordercenter.response.orderInfo.OrderInfoReqs;
import com.freemud.application.sdk.api.ordercenter.service.OrderSdkService;
import com.freemud.sdk.api.assortment.order.request.order.ConfirmOrderRequest;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * @author Clover.z
 * @Date 2021/10/20
 * @Desc
 */
@Service
@RequiredArgsConstructor
public class CashierOrderServiceImpl implements CashierOrderService {

    private final StoreManager storeManager;
    private final OrderSdkService orderSdkService;
    private final PayServiceImpl payService;
//    private final OrderSdkAdapter orderSdkAdapter;
    private final OrderCenterSdkAdapter orderCenterSdkAdapter;
    private final OrderBusinessService orderBusinessService;

    /**
     * 创建无单收银订单
     * 不需要查询购物车，没有商品，流程上 只需要创建一个订单然后唤起预支付就行了
     *
     * @param createOrderDto   请求数据
     * @param member      会员信息
     * @return 预支付信息
     */
    @Override
    public CreateOrderResponseVo createOrder(CreateCashierOrderDto createOrderDto, AssortmentCustomerInfoVo member) {
        // 查询门店和配置信息
        StoreMixResponseDto storeMix = storeManager.queryStoreMixInfo(createOrderDto.getPartnerId(), createOrderDto.getStoreCode(), query -> {
            query.setQueryBusinessInfo(true); query.setQueryStoreInfo(true);
        });
        if (null == storeMix.getStoreInfo() || null == storeMix.getBusinessInfo()) throw new ServiceException(ResponseResult.STORE_DATE_ERROR);
        // 门店未配置收银买单开关或者未配置为 1-开启， 则不允许下单
        if (! Objects.equals(storeMix.getBusinessInfo().getSupportCashierPay(), 1)) throw new ServiceException(ResponseResult.STORE_CASHIER_CONFIG_ERROR);

        //创建订单
        CreateOrderRequest request = this.generateCreateOrderRequest(storeMix.getStoreInfo(), createOrderDto.getOrderAmount(), member);
        OrderBaseResp<OrderInfoReqs> response = orderSdkService.createOrder(request, LogThreadLocal.getTrackingNo());
        if (null == response || !ResponseCodeConstant.RESPONSE_SUCCESS_STR.equals(response.getCode())) {
            throw new ServiceException(ResponseResult.ORDER_CREATE_ERROR);
        }

        //创建预支付
        CreatePrepayRequestDto createPrepayRequestDto = new CreatePrepayRequestDto();
        createPrepayRequestDto.setPartnerId(createOrderDto.getPartnerId());
        createPrepayRequestDto.setTransId(response.getResult().getOrderCode());
        createPrepayRequestDto.setWxAppId(member.getWxAppId());
        createPrepayRequestDto.setOpenId(member.getOpenId());
        createPrepayRequestDto.setTotalAmount(createOrderDto.getOrderAmount());
        createPrepayRequestDto.setChannel(Objects.requireNonNull(PayChannelType.getByIndex(request.getPayChannelType())).getIndex().toString());
        createPrepayRequestDto.setCardCode(createOrderDto.getCardCode());
        OrderBeanV1 orderBeanV1 = orderCenterSdkAdapter.convent2NEWOrderInfo(response.getResult());
        createPrepayRequestDto.setProductOrderBean(orderBeanV1);
        createPrepayRequestDto.setFatherOrderBean(orderBeanV1);
        OrderExtInfoDto orderExtInfoDto = new OrderExtInfoDto();
        orderExtInfoDto.setOpenid(member.getOpenId());
        orderExtInfoDto.setAppid(member.getWxAppId());
        orderExtInfoDto.setSessionId(member.getSessionId());
        orderExtInfoDto.setVersion(createOrderDto.getVersion());
        orderExtInfoDto.setSessionKey(member.getSessionKey());
        orderExtInfoDto.setFromAppId(member.getWxAppId());
        createPrepayRequestDto.setOrderExtInfoDTO(orderExtInfoDto);
        return payService.createPrepayOrder(createPrepayRequestDto);
    }



    private CreateOrderRequest generateCreateOrderRequest(StoreResponseDto storeInfo, Long orderAmount, AssortmentCustomerInfoVo member) {
        CreateOrderRequest request = new CreateOrderRequest();
        request.setPartnerId(storeInfo.getPartnerId());
        request.setStoreId(storeInfo.getStoreCode());
        request.setStoreName(storeInfo.getStoreName());
        request.setUserId(member.getMemberId());
        request.setUserName(member.getNickName());
        request.setSettlementAmount(orderAmount);
        request.setActualPayAmount(orderAmount);
        request.setOriginalAmount(orderAmount);
        request.setOrderType(OrderType.GENERAL_DINE_IN.getIndex());
        request.setBizType(BizTypeEnum.ORDINARY.getBizType());
        request.setMarketingType(MarketTypeEnum.CASHIER.getIndex());
        switch (UserLoginChannelEnum.get(member.getChannel())) {
            case ALIPAY:
                request.setPayChannel(PayChannelType.ALIPAY.getIndex().toString());
                request.setPayChannelType(PayChannelType.ALIPAY.getIndex());
                request.setOrderClient(OrderClientType.ALIPAY.getIndex());
                break;
            case WEIXIN:
                request.setPayChannel(PayChannelType.WECHAT.getIndex().toString());
                request.setPayChannelType(PayChannelType.WECHAT.getIndex());
                request.setOrderClient(OrderClientType.SAAS.getIndex());
                break;
            default:
                throw new ServiceException(ResponseResult.OPERATE_NOT_SUPPORT);
        }
        // 无单收银没有商品信息， 这里防止基础服务处理NPE，传一个空的商品集合
        request.setOrderItemList(new ArrayList<>());
        OrderExtendedReq orderExtended = new OrderExtendedReq();
        orderExtended.setOrderClientGroupCode(storeInfo.getParentCode());
        orderExtended.setOrderClientGroup(storeInfo.getParentName());
        request.setOrderExtended(orderExtended);
        request.setOperator(member.getNickName());
        request.setAppId(member.getWxAppId());
        return request;
    }


    /**
     * 支付成功回调处理
     *
     * @param message         支付消息
     * @param confirmOrderDto 支付成功消息dto
     * @param orderBeans      订单信息
     * @return 处理结果json字符串
     */
    @Override
    public String paySuccessCallback(PaysuccessNoticeMessage message, ConfirmOrderDto confirmOrderDto, Map<String, OrderBeanV1> orderBeans) {
        OrderBeanV1 orderBean = orderBeans.get(OrderBeanType.SAASORDER.getCode());

        ConfirmOrderRequest var1 = LightApplicationConvertToAssortmentSdkAdapter.confirmOrderDtoConvertToConfirmOrderRequest(confirmOrderDto, orderBeans.get(OrderBeanType.MERMBERORDER.getCode()));
        var1.setPartnerId(orderBean.getCompanyId());
        var1.setUserId(orderBean.getUserId());
        var1.setStoreId(orderBean.getShopId());
        var1.setOrderType(orderBean.getOrderType());
        var1.setProductOrderCode(orderBean.getOid());
        var1.setPayDate(DateUtil.convert2String(new Date(), "yyyy-MM-dd HH:mm:ss"));
        var1.setPayTransId(message.getOut_trade_no());
        var1.setOperator(orderBean.getUserName());
        var1.setEndTransId(message.getEndTransId());
        var1.setExtInfo(orderBean.getExtInfo());
        if(orderBean.getGmtExpect() != null && orderBean.getGmtExpect() != 0){
            var1.setExpectTime(DateUtil.convert2String(new Date(orderBean.getGmtExpect()),DateUtil.FORMAT_YYYY_MM_DD_HHMMSS));
        }
        try {
            // 订单支付成功
            orderBusinessService.payAccess(var1);
        }catch (Exception e){
            AppLogUtil.errorLog("sellCouponPayAccessError", JSONObject.toJSONString(var1),null,e);
        }
        //支付成功直接完成
        OrderChangeStateReq request = new OrderChangeStateReq();
        request.setOrderCode(orderBean.getOid());
        request.setOrderState(NewOrderStatus.COMPLETE.getIndex());
        request.setOperator(orderBean.getUserName());
        request.setPartnerId(orderBean.getCompanyId());
        request.setRemark("已完成");
        orderSdkService.updateOrderState(request, LogThreadLocal.getTrackingNo());
        Map<String, Object> map = Maps.newTreeMap();
        map.put("code", 100);
        map.put("message", "success");
        return JSONObject.toJSONString(map);
    }

    /**
     * 无单收银使用储值卡混合支付
     */
    @Override
    public CashierCheckResponseVo cashierCheck(CreateCashierOrderDto createOrderDto, AssortmentCustomerInfoVo member) {
        CheckSvcAmountBo bo = new CheckSvcAmountBo();
        BeanUtils.copyProperties(createOrderDto, bo);

        CheckSvcAmountResponse checkSvcAmountResponse = payService.checkSvcAmount(bo);
        CashierCheckResponseVo responseVo = new CashierCheckResponseVo();
        BeanUtils.copyProperties(checkSvcAmountResponse, responseVo);
        return responseVo;
    }
}
