package com.hfkj.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.hfkj.channel.hsg.HsgIntegralService;
import com.hfkj.channel.hsg.type.RebateProductTypeEnum;
import com.hfkj.channel.lakala.LaKaLaMerService;
import com.hfkj.channel.lakala.LaKaLaTradeService;
import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.common.utils.DateUtil;
import com.hfkj.common.utils.IDGenerator;
import com.hfkj.common.utils.RequestUtils;
import com.hfkj.config.device.SoundService;
import com.hfkj.dao.BsTradeOrderMapper;
import com.hfkj.entity.*;
import com.hfkj.model.UserDiscount;
import com.hfkj.service.*;
import com.hfkj.sysenum.*;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

@Service("tradeOrderService")
public class BsTradeOrderServiceImpl implements BsTradeOrderService {

    @Resource
    private BsTradeOrderMapper tradeOrderMapper;

    @Resource
    private BsMerService merService;

    @Resource
    private BsSalesmanService salesmanService;

    @Resource
    private BsStoreCidService bsStoreCidService;

    @Resource
    private BsStoreService storeService;

    @Resource
    private BsTradeOrderProfitSharingService tradeOrderProfitSharingService;

    @Resource
    private BsStoreDiscountActivityPartakeUserService discountActivityPartakeUserService;
    @Resource
    private BsDeviceService deviceService;
    @Resource
    private SoundService soundService;

    @Resource
    private UserDiscountService userDiscountService;
    @Resource
    private BsMerRateService merRateService;
    @Resource
    private LaKaLaTradeService laKaLaTradeService;

    @Override
    public void editOrder(BsTradeOrder tradeOrder) {
        if (tradeOrder.getId() == null) {
            tradeOrder.setCreateTime(new Date());
            tradeOrder.setUpdateTime(new Date());
            tradeOrderMapper.insert(tradeOrder);
        } else {
            tradeOrder.setUpdateTime(new Date());
            tradeOrderMapper.updateByPrimaryKey(tradeOrder);
        }
    }

    @Override
    public Map<String, Object> createOrder(Long storeId, BigDecimal tradeAmount, BsStoreDiscountActivity storeDiscount, String userPhone, UserDiscount userDiscount, Map<String, Object> param, HttpServletRequest request) {
        // 查询门店信息
        BsStore store = storeService.getStoreById(storeId);
        if (store == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到门店");
        }
        if (!store.getStatus().equals(StoreStatusEnum.status2.getNumber())) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "无法支付！门店状态不正常");
        }
        // 查询商户信息
        BsMer mer = merService.getMer(store.getMerId());
        if (mer == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到商户");
        }
        if (!mer.getMerStatus().equals(MerStatusEnum.status1.getNumber())) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "无法支付！商户状态不正常");
        }
        BsTradeOrder tradeOrder = new BsTradeOrder();
        tradeOrder.setCreateType(TradeOrderCreateTypeEnum.type1.getCode());
        tradeOrder.setCompanyId(mer.getCompanyId());
        tradeOrder.setAgentId(mer.getAgentId());
        tradeOrder.setSalesmanId(mer.getSalesmanId());
        tradeOrder.setSalesmanName(mer.getSalesmanName());
        tradeOrder.setMerId(store.getMerId());
        tradeOrder.setMerNo(mer.getMerNo());
        tradeOrder.setMerName(mer.getMerName());
        tradeOrder.setMerAbbreviate(mer.getMerAbbreviate());
        tradeOrder.setStoreId(storeId);
        tradeOrder.setStoreName(store.getName());
        tradeOrder.setStatus(TradeOrderStatusEnum.status1.getNumber());
        tradeOrder.setTradeAmount(tradeAmount);
        tradeOrder.setTradeActualAmount(tradeAmount);
        tradeOrder.setStoreDiscountSatisfy(false);
        tradeOrder.setUserPhone(userPhone);
        tradeOrder.setProfitSharingStatus(false);
        tradeOrder.setRequestIp(RequestUtils.getIpAddress(request));

        // 门店优惠
        if (storeDiscount != null) {
            tradeOrder.setProfitSharingStatus(true);
            tradeOrder.setStoreDiscountId(storeDiscount.getId());
            tradeOrder.setStoreDiscountName(storeDiscount.getName());
            tradeOrder.setStoreDiscountType(storeDiscount.getDiscountType());
            tradeOrder.setStoreDiscountCondition(storeDiscount.getDiscountCondition());
            tradeOrder.setStoreDiscountPrice(storeDiscount.getDiscountPrice());
            tradeOrder.setStoreDiscountFinalCostPrice(storeDiscount.getFinalCostPrice());
            if (storeDiscount.getDiscountType().equals(StoreDiscountActivityTypeEnum.type1.getNumber())) {
                // 未达到满减门槛
                if (tradeOrder.getTradeAmount().compareTo(storeDiscount.getDiscountCondition()) < 0) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "满减优惠，未达到满减条件");
                } else {
                    tradeOrder.setStoreDiscountSatisfy(true);
                    tradeOrder.setStoreDiscountActualPrice(storeDiscount.getDiscountPrice());
                }
                tradeOrder.setTradeActualAmount(tradeOrder.getTradeActualAmount().subtract(tradeOrder.getStoreDiscountActualPrice()));
                // 实际交易金额 - 平台交易成本价 = 利润
                tradeOrder.setStoreDiscountProfitPrice(tradeOrder.getStoreDiscountFinalCostPrice().subtract(tradeOrder.getStoreDiscountActualPrice()));

            } else if (storeDiscount.getDiscountType().equals(StoreDiscountActivityTypeEnum.type3.getNumber())) {
                // 优惠比例 / 100 = 最终优惠比例
                tradeOrder.setStoreDiscountSatisfy(true);
                BigDecimal priceRate = tradeOrder.getStoreDiscountPrice().divide(new BigDecimal("100").setScale(2, BigDecimal.ROUND_DOWN));
                tradeOrder.setStoreDiscountActualPrice(tradeOrder.getTradeActualAmount().subtract(tradeOrder.getTradeActualAmount().multiply(priceRate).setScale(2, BigDecimal.ROUND_HALF_UP)));
                tradeOrder.setTradeActualAmount(tradeOrder.getTradeActualAmount().subtract(tradeOrder.getStoreDiscountActualPrice()));
                // 平台交易成本价
                BigDecimal finalCostPrice = tradeOrder.getTradeAmount().multiply(tradeOrder.getStoreDiscountFinalCostPrice().divide(new BigDecimal("100"))).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                // 实际交易金额 - 平台交易成本价 = 利润
                tradeOrder.setStoreDiscountProfitPrice(tradeOrder.getTradeActualAmount().subtract(finalCostPrice));
            } else {
                tradeOrder.setStoreDiscountSatisfy(true);
                tradeOrder.setStoreDiscountActualPrice(storeDiscount.getDiscountPrice());
                tradeOrder.setTradeActualAmount(tradeOrder.getTradeActualAmount().subtract(tradeOrder.getStoreDiscountActualPrice()));
                // 实际交易金额 - 平台交易成本价 = 利润
                tradeOrder.setStoreDiscountProfitPrice(tradeOrder.getStoreDiscountFinalCostPrice().subtract(tradeOrder.getStoreDiscountActualPrice()));
            }
        }

        // 用户优惠券
        if (userDiscount != null) {
            tradeOrder.setUserDiscountId(userDiscount.getId());
            tradeOrder.setUserDiscountName(userDiscount.getDiscountName());
            tradeOrder.setUserDiscountType(userDiscount.getDiscountType());
            tradeOrder.setUserDiscountPrice(userDiscount.getDiscountPrice());
            if (userDiscount.getDiscountType().equals(UserDiscountTypeEnum.type1.getNumber())) {
                if (tradeOrder.getTradeAmount().compareTo(userDiscount.getDiscountCondition()) < 0) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "优惠券未达到满减门槛");
                }
                tradeOrder.setUserDiscountActualPrice(userDiscount.getDiscountPrice());
                tradeOrder.setTradeActualAmount(tradeOrder.getTradeActualAmount().subtract(tradeOrder.getUserDiscountActualPrice()));

            } else if (userDiscount.getDiscountType().equals(UserDiscountTypeEnum.type3.getNumber())) {
                // 优惠比例 / 100 = 最终优惠比例
                BigDecimal priceRate = tradeOrder.getUserDiscountPrice().setScale(2, BigDecimal.ROUND_DOWN);
                tradeOrder.setUserDiscountActualPrice(tradeOrder.getTradeActualAmount().subtract(tradeOrder.getTradeActualAmount().multiply(priceRate).setScale(2, BigDecimal.ROUND_HALF_UP)));
                tradeOrder.setTradeActualAmount(tradeOrder.getTradeActualAmount().subtract(tradeOrder.getUserDiscountActualPrice()));
            } else {
                tradeOrder.setUserDiscountActualPrice(userDiscount.getDiscountPrice());
                tradeOrder.setTradeActualAmount(tradeOrder.getTradeActualAmount().subtract(tradeOrder.getUserDiscountActualPrice()));
            }
        }

        // 生成订单号
        String tradeNo = "ZF1130"+DateUtil.format(new Date(), DateUtil.YMDHMS) + IDGenerator.nextId(10);
        tradeOrder.setOutTradeNo(tradeNo);

        if (StringUtils.isNotBlank(MapUtils.getString(param, "payMode"))) {
            tradeOrder.setPayMode(MapUtils.getString(param, "payMode"));
        }
        if (StringUtils.isNotBlank(MapUtils.getString(param, "payUserId"))) {
            tradeOrder.setPayUserId(MapUtils.getString(param, "payUserId"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "deviceSN"))) {
            tradeOrder.setDeviceSn(MapUtils.getString(param, "deviceSN"));
        }

        if (MapUtils.getLong(param, "deviceId") != null) {
            tradeOrder.setDeviceId(MapUtils.getLong(param, "deviceId"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "qrCodeSN"))) {
            tradeOrder.setQrCodeSn(MapUtils.getString(param, "qrCodeSN"));
        }

        if (MapUtils.getLong(param, "qrCodeId") != null) {
            tradeOrder.setQrCodeId(MapUtils.getLong(param, "qrCodeId"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "transType"))) {
            tradeOrder.setTransType(MapUtils.getString(param, "transType"));
        }

        editOrder(tradeOrder);

        Map<String, Object> returnParam = new HashMap<>();
        returnParam.put("outTradeNo", tradeNo);
        return returnParam;
    }

    @Override
    public void paySuccess(String outTradeNo, String transactionId, PlatformTypeEnum platformType, TradeOrderPayModeEnum tradeOrderPayMode, BigDecimal tradeActualAmount, String subMchId, Map<String,Object> other) {
        // 查询订单
        BsTradeOrder tradeOrder = getOrderByOutTradeNo(outTradeNo);
        if (tradeOrder != null && tradeOrder.getStatus().equals(TradeOrderStatusEnum.status1.getNumber())) {
            tradeOrder.setPayMode(tradeOrderPayMode.getCode());
            tradeOrder.setPlatformType(platformType.getNumber());
            tradeOrder.setPlatformMerNo(subMchId);
            tradeOrder.setPlatformTradeNo(transactionId);
            tradeOrder.setTradeActualAmount(tradeActualAmount);
            tradeOrder.setStatus(TradeOrderStatusEnum.status3.getNumber());
            tradeOrder.setPayTime(new Date());

            if (StringUtils.isNotBlank(MapUtils.getString(other, "log_no"))) {
                tradeOrder.setPlatformLogNo(MapUtils.getString(other, "log_no"));
            }
            if (StringUtils.isNotBlank(MapUtils.getString(other, "acc_trade_no"))) {
                tradeOrder.setAccTradeNo(MapUtils.getString(other, "acc_trade_no"));
            }
            if (StringUtils.isNotBlank(MapUtils.getString(other, "card_type"))) {
                tradeOrder.setCardType(MapUtils.getString(other, "card_type"));
            }
            tradeOrder.setAccSettleAmount(
                    StringUtils.isNotBlank(MapUtils.getString(other, "acc_settle_amount"))
                    ?new BigDecimal(MapUtils.getString(other, "acc_settle_amount"))
                    :new BigDecimal("0"));

            tradeOrder.setAccDiscountAmount(
                    StringUtils.isNotBlank(MapUtils.getString(other, "acc_discount_amount"))
                    ?new BigDecimal(MapUtils.getString(other, "acc_discount_amount"))
                    :new BigDecimal("0"));

            tradeOrder.setAccMdiscountAmount(
                    StringUtils.isNotBlank(MapUtils.getString(other, "acc_mdiscount_amount"))
                    ?new BigDecimal(MapUtils.getString(other, "acc_mdiscount_amount"))
                    :new BigDecimal("0"));

            tradeOrder.setSettleAmount(
                    StringUtils.isNotBlank(MapUtils.getString(other, "settleAmount"))
                            ?new BigDecimal(MapUtils.getString(other, "settleAmount"))
                            :null);

            tradeOrder.setSettleDate(
                    MapUtils.getLong(other, "settleDate")!=null
                            ?new Date(MapUtils.getLong(other, "settleDate"))
                            :null);

            editOrder(tradeOrder);

            if (tradeOrder.getCreateType() != null && !tradeOrder.getCreateType().equals(TradeOrderCreateTypeEnum.type3.getCode())) {
                Map<String,Object> param = new HashMap<>();
                param.put("storeId", tradeOrder.getStoreId());
                param.put("deviceType", DeviceTypeEnum.type1.getNumber());
                param.put("status", DeviceStatusEnum.status1.getNumber());
                List<BsDevice> deviceList = deviceService.getDeviceList(param);
                for (BsDevice device : deviceList) {
                     soundService.sendPayMsg(device.getDeviceNo(), tradeOrder.getTradeAmount());
                }

                if (tradeOrder.getStoreDiscountId() != null && StringUtils.isNotBlank(tradeOrder.getUserPhone())) {
                    // 支付返积分
                    HsgIntegralService.rebate(RebateProductTypeEnum.type2,
                            tradeOrder.getUserPhone(),
                            tradeOrder.getOutTradeNo(),
                            tradeOrder.getId(),
                            tradeOrder.getStoreDiscountProfitPrice(),
                            tradeOrder.getStoreName(),
                            tradeOrder.getCreateTime());

                    BsStoreDiscountActivityPartakeUser partakeUser = discountActivityPartakeUserService.getPartakeUser(tradeOrder.getUserPhone(), tradeOrder.getStoreDiscountId());
                    if (partakeUser != null) {
                        partakeUser.setPartakeSurplusNum(partakeUser.getPartakeSurplusNum() - 1);
                        partakeUser.setPartakeUseNum(partakeUser.getPartakeUseNum() + 1);
                        discountActivityPartakeUserService.editData(partakeUser);
                    }
                }

                if (tradeOrder.getUserDiscountId() != null && StringUtils.isNotBlank(tradeOrder.getUserPhone())) {
                    userDiscountService.userDiscountUse(tradeOrder.getUserDiscountId(), tradeOrder.getUserPhone());
                }

                if (StringUtils.isNotBlank(tradeOrder.getUserPhone())) {
                    // 支付返积分
                    HsgIntegralService.rebate(RebateProductTypeEnum.type1,
                            tradeOrder.getUserPhone(),
                            tradeOrder.getOutTradeNo(),
                            tradeOrder.getId(),
                            tradeOrder.getTradeActualAmount(),
                            tradeOrder.getStoreName(),
                            tradeOrder.getCreateTime());
                }

                JSONObject objectPush = new JSONObject();

                objectPush.put("storeId" , tradeOrder.getStoreId());
                objectPush.put("price" , tradeOrder.getTradeAmount());
                bsStoreCidService.storePush(objectPush);

                // 创建分账
                if (tradeOrder.getProfitSharingStatus().equals(true)) {
                    tradeOrderProfitSharingService.createProfitSharing(tradeOrder);
                }
            }
        }
    }

    @Override
    public BsTradeOrder getOrderByOutTradeNo(String outTradeNo) {
        BsTradeOrderExample example = new BsTradeOrderExample();
        example.createCriteria().andOutTradeNoEqualTo(outTradeNo);
        List<BsTradeOrder> list = tradeOrderMapper.selectByExample(example);
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public BsTradeOrder getOrderByOutTradeNoOrPlatformTradeNo(String tradeNo) {
        BsTradeOrderExample example = new BsTradeOrderExample();
        example.createCriteria().andOutTradeNoEqualTo(tradeNo);
        example.or().andPlatformTradeNoEqualTo(tradeNo);
        List<BsTradeOrder> list = tradeOrderMapper.selectByExample(example);
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public BsTradeOrder getOrderByTradeNoId(Long tradeOrderId) {
        return tradeOrderMapper.selectByPrimaryKey(tradeOrderId);
    }

    @Override
    public List<BsTradeOrder> getTradeOrderList(Map<String, Object> param) {
        BsTradeOrderExample example = new BsTradeOrderExample();
        BsTradeOrderExample.Criteria criteria = example.createCriteria();

        if (MapUtils.getLong(param, "agentId") != null) {
            criteria.andAgentIdEqualTo(MapUtils.getLong(param, "agentId"));
        }

        if (MapUtils.getLong(param, "salesmanId") != null) {
            criteria.andSalesmanIdEqualTo(MapUtils.getLong(param, "salesmanId"));
        }

        if (MapUtils.getLong(param, "merId") != null) {
            criteria.andMerIdEqualTo(MapUtils.getLong(param, "merId"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "merNo"))) {
            criteria.andMerNoLike("%"+MapUtils.getString(param, "merNo")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "merName"))) {
            criteria.andMerNameLike("%"+MapUtils.getString(param, "merName")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "merAbbreviate"))) {
            criteria.andMerAbbreviateLike("%"+MapUtils.getString(param, "merAbbreviate")+"%");
        }

        if (MapUtils.getLong(param, "storeId") != null) {
            criteria.andStoreIdEqualTo(MapUtils.getLong(param, "storeId"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "storeName"))) {
            criteria.andStoreNameLike("%"+MapUtils.getString(param, "storeName")+"%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "payMode"))) {
            criteria.andPayModeEqualTo(MapUtils.getString(param, "payMode"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "outTradeNo"))) {
            criteria.andOutTradeNoEqualTo(MapUtils.getString(param, "outTradeNo"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "accTradeNo"))) {
            criteria.andAccTradeNoEqualTo(MapUtils.getString(param, "accTradeNo"));
        }

        if (MapUtils.getLong(param, "payTimeS") != null) {
            criteria.andPayTimeGreaterThanOrEqualTo(new Date(MapUtils.getLong(param, "payTimeS")));
        }

        if (MapUtils.getLong(param, "payTimeE") != null) {
            criteria.andPayTimeLessThanOrEqualTo(new Date(MapUtils.getLong(param, "payTimeE")));
        }

        if (MapUtils.getInteger(param, "platformType") != null) {
            criteria.andPlatformTypeEqualTo(MapUtils.getInteger(param, "platformType"));
        }

        if (MapUtils.getInteger(param, "status") != null) {
            criteria.andStatusEqualTo(MapUtils.getInteger(param, "status"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "statusList"))) {
            String[] statusLists = MapUtils.getString(param, "statusList").split(",");
            List<Integer> statusList = new ArrayList<>();
            for (String s : statusLists) {
                statusList.add(Integer.parseInt(s));
            }
            criteria.andStatusIn(statusList);
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "settleAmountIsNull"))) {
            criteria.andSettleAmountIsNull();
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "shdFeeAmtIsNull"))) {
            criteria.andShdFeeAmtIsNull();
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "specialField"))) {
            criteria.andSpecialFieldLike("%"+MapUtils.getString(param, "specialField")+"%");
        }

        example.setOrderByClause("create_time desc");
        return tradeOrderMapper.selectByExample(example);
    }

    @Override
    public Map<String,Object> countTradeOrderPrice(Map<String, Object> param) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.putAll(param);

        if (StringUtils.isBlank(MapUtils.getString(paramMap, "outTradeNo"))) {
            paramMap.remove("outTradeNo");
        }

        if (MapUtils.getLong(param, "payTimeS") != null) {
            paramMap.put("payTimeS", DateUtil.date2String(new Date(MapUtils.getLong(param, "payTimeS")), DateUtil.Y_M_D_HMS));
        }
        if (MapUtils.getLong(param, "payTimeE") != null) {
            paramMap.put("payTimeE", DateUtil.date2String(new Date(MapUtils.getLong(param, "payTimeE")), DateUtil.Y_M_D_HMS));
        }
        return tradeOrderMapper.countTradeOrderPrice(paramMap);
    }

}
