package com.iformall.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.IdWorker;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.dto.WxMerchantDto;
import com.iformall.domain.po.*;
import com.iformall.domain.po.base.BaseEntity;
import com.iformall.domain.vo.WxMerchantSimpleVo;
import com.iformall.domain.vo.WxMerchantTradeDetailVo;
import com.iformall.domain.vo.WxMerchantTradeVo;
import com.iformall.domain.vo.WxMerchantVo;
import com.iformall.enums.*;
import com.iformall.exception.MallinkException;
import com.iformall.mapper.*;
import com.iformall.service.*;
import com.iformall.utils.DateUtils;
import com.iformall.utils.EventUtil;
import jodd.util.CollectionUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @author gongbiao
 */
@Service
public class WxMerchantServiceImpl implements WxMerchantService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    WxMerchantMapper wxMerchantMapper;

    @Autowired
    WxShopMapper wxShopMapper;

    @Autowired
    WxMerchantShopMapper wxMerchantShopMapper;

    @Autowired
    WxMerchantBUserMapper wxMerchantBUserMapper;

    @Autowired
    WxAppinfoMapper wxAppinfoMapper;

    @Autowired
    WxRentContractMapper wxRentContractMapper;

    @Autowired
    WxBillRentMapper wxBillRentMapper;

    @Autowired
    WxCouponMapper wxCouponMapper;

    @Autowired
    WxCouponService wxCouponService;

    @Autowired
    WxProfitSharingReceiverService wxProfitSharingReceiverService;

    @Autowired
    WxBillDepositMapper wxBillDepositMapper;

    @Autowired
    WxMerchantCorpMapper wxMerchantCorpMapper;

    @Autowired
    WxMerchantTaxMapper wxMerchantTaxMapper;

    @Autowired
    WxCouponMerchantMapper wxCouponMerchantMapper;

    @Autowired
    WxRentContractService wxRentContractService;

    @Autowired
    WxLevelConfigService wxLevelConfigService;

    @Autowired
    ExcelService excelService;

    @Autowired
    WxPropertyContractMapper wxPropertyContractMapper;

    @Autowired
    WxProfitSharingReceiverMapper wxProfitSharingReceiverMapper;

    @Autowired
    WxPropertyContractService wxPropertyContractService;

    @Override
    public PageInfo<WxMerchant> listAsPage(WxMerchant record, Integer pageIndex, Integer pageSize) {
        PageHelper.startPage(pageIndex, pageSize);
        List<WxMerchant> merchants = wxMerchantMapper.findList(record);
        PageInfo<WxMerchant> pageInfo = new PageInfo<>(merchants);
        return pageInfo;
    }


    @Override
    public PageInfo<WxMerchantVo> listAsPageCVo(WxMerchantDto record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxMerchantMapper.findListCVo(record));
    }

    @Override
    public WxMerchantVo getMerchantInfo(HashMap<String, String> params) {
        return wxMerchantMapper.getMerchantByCode(params);
    }

    @Override
    public List<WxMerchant> etcpList(WxMerchant record) {
        record.setCarVendorType(EnumCarVendor.CAR_ETCP.getCode());
        return wxMerchantMapper.findList(record);
    }

    @Override
    public List<WxMerchant> findList(WxMerchant record) {
        return wxMerchantMapper.findList(record);
    }

    @Override
    public List<WxMerchantSimpleVo> findList(String tenantId) {
        WxMerchant wxMerchant = new WxMerchant();
        wxMerchant.setTenantId(tenantId);
        wxMerchant.setStatus(EnumMerchantStatus.VALID.getCode());
        List<WxMerchant> wxMerchantList = wxMerchantMapper.findList(wxMerchant);
        List<WxMerchantSimpleVo> collect = wxMerchantList.stream().map(x -> {
            WxMerchantSimpleVo wxMerchantSimpleVo = new WxMerchantSimpleVo();
            wxMerchantSimpleVo.setId(x.getId());
            wxMerchantSimpleVo.setMerchantName(x.getName());
            wxMerchantSimpleVo.setBusinessId(x.getBusinessId());
            return wxMerchantSimpleVo;
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public WxMerchant getById(Long id) {
        WxMerchant wxMerchant = wxMerchantMapper.selectById(id);
        if(wxMerchant==null){
            return null;
        }
        WxMerchantShop wxMerchantShop = new WxMerchantShop();
        wxMerchantShop.setMerchantId(wxMerchant.getId());
        wxMerchantShop.setIsDel(EnumDelStatus.NOT_DEL.getCode());
        List<Map<String, Object>> shops = new ArrayList<>();


        WxRentContract wxRentContract = new WxRentContract();
        wxRentContract.setMerchantId(wxMerchant.getId());
        List<WxRentContract> lrc = wxRentContractMapper.selectRentContractByMerchantId(wxRentContract);
        if (!lrc.isEmpty()) {
            wxMerchant.setRentalStartDate(lrc.get(0).getRentalStartDate());
            wxMerchant.setRentalEndDate(lrc.get(0).getRentalEndDate());
        }
        
        List<WxMerchantShop> wxMerchantShopList = wxMerchantShopMapper.findList(wxMerchantShop);
        for (WxMerchantShop merchantShop : wxMerchantShopList) {
            WxShop record = new WxShop();
            record.setId(merchantShop.getShopId());
            List<Map<String, Object>> shoplist = wxShopMapper.findListMap(record);
            if (shoplist.size() > 0) {
                shops.add(shoplist.get(0));
            }
        }

        wxMerchant.setShoplist(shops);

        WxMerchantBUser wxMerchantBUser = new WxMerchantBUser();
        wxMerchantBUser.setMerchantId(wxMerchant.getId());
        wxMerchantBUser.setStatus(EnumMerchantBUserStatus.VALID.getCode());
        List<WxMerchantBUser> userList = wxMerchantBUserMapper.findList(wxMerchantBUser);
        wxMerchant.setUsers(userList);

        //分账信息
        WxProfitSharingReceiver receiver = wxProfitSharingReceiverService.findReceiver(wxMerchant);
        if (receiver != null) {
            wxMerchant.setWxProfitSharingReceiver(receiver);
            wxMerchant.setAccountId(receiver.getReceiverAccount());
            wxMerchant.setAccountName(receiver.getTrueName());
            wxMerchant.setAccountTypeValue(receiver.getReceiverType());
        }

        WxMerchantCorp wxMerchantCorp = new WxMerchantCorp();
        wxMerchantCorp.setMerchantId(wxMerchant.getId());
        List<WxMerchantCorp> corps = wxMerchantCorpMapper.findList(wxMerchantCorp);
        if(!corps.isEmpty()){
            wxMerchant.setWxMerchantCorp(corps.get(0));
        }else{
            wxMerchant.setWxMerchantCorp(new WxMerchantCorp());
        }

        WxMerchantTax wxMerchantTax = new WxMerchantTax();
        wxMerchantTax.setMerchantId(wxMerchant.getId());
        List<WxMerchantTax> taxes = wxMerchantTaxMapper.findList(wxMerchantTax);
        if(!taxes.isEmpty()){
            wxMerchant.setWxMerchantTax(taxes.get(0));
        }else{
            wxMerchant.setWxMerchantTax(new WxMerchantTax());
        }

        WxLevelConfig wxLevelConfig = new WxLevelConfig();
        wxLevelConfig.setTenantId(wxMerchant.getTenantId());
        wxLevelConfig.setSortColumns(BaseEntity.SortField.Points_ASC);
        wxMerchant.setLevelConfigList(wxLevelConfigService.listByMerchantId(wxMerchant.getId(),wxLevelConfig));

        return wxMerchant;
    }


    @Override
    public void deleteById(Long id) {
        wxMerchantMapper.deleteById(id);
    }


    private boolean isCouponMerchantValid(Long couponId) {
        Map paramMap = new HashMap<>();
        paramMap.put("productId",couponId);
        List<WxMerchantVo> merchantVoList = wxCouponMerchantMapper.findMerchantNameList(paramMap);
        if (merchantVoList.stream().anyMatch((cm->cm.getMerchantStatus().equals(EnumMerchantStatus.VALID.getCode())))){
            return true;
        }
        return false;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void disable(Long id) {
        WxMerchant wxMerchant = wxMerchantMapper.selectById(id);
        if (wxMerchant == null) {
            logger.info("未发现要停用的商户");
            return;
        }

        if(!wxMerchant.getCarVendorType().equals(EnumCarVendor.CAR_NOTFOUND.getCode())){
            logger.info("不能停用停车商户");
            return;
        }

        wxMerchant.setStatus(EnumMerchantStatus.NOT_VALID.getCode());
        wxMerchantMapper.updateById(wxMerchant);
        //是否有租赁合同
        WxRentContract wxRentContract = new WxRentContract();
        wxRentContract.setMerchantId(id);
        long countRentContract = wxRentContractMapper.selectList(new QueryWrapper<>(wxRentContract)).parallelStream().
                filter(c -> c.getStatus().equals(EnumRentContractStatus.SIGNED_RENT_UNPAID.getCode()) ||
                        c.getStatus().equals(EnumRentContractStatus.RENT_PAID.getCode()) ||
                        c.getStatus().equals(EnumRentContractStatus.CONTRACT_END_SOON.getCode())).count();
        //是否有物业合同
        WxPropertyContract wxPropertyContract = new WxPropertyContract();
        wxPropertyContract.setMerchantId(id);
        long countPropertyContract = wxPropertyContractMapper.selectList(new QueryWrapper<>(wxPropertyContract)).parallelStream().
                filter(c -> c.getStatus().equals(EnumRentContractStatus.SIGNED_RENT_UNPAID.getCode()) ||
                        c.getStatus().equals(EnumRentContractStatus.RENT_PAID.getCode()) ||
                        c.getStatus().equals(EnumRentContractStatus.CONTRACT_END_SOON.getCode())).count();
        //解绑商铺-没有租赁合同或物业合同才可以
        if (countRentContract == 0 || countPropertyContract == 0) {
            WxMerchantShop wxMerchantShopQuery = new WxMerchantShop();
            wxMerchantShopQuery.setTenantId(wxMerchant.getTenantId());
            wxMerchantShopQuery.setMerchantId(wxMerchant.getId());
            wxMerchantShopQuery.setIsDel(EnumDelStatus.NOT_DEL.getCode());
            List<WxMerchantShop> wxMerchantShopList = wxMerchantShopMapper.findList(wxMerchantShopQuery);
            for (WxMerchantShop wxMerchantShop : wxMerchantShopList) {
                wxMerchantShop.setIsDel(EnumDelStatus.DEL.getCode());
                wxMerchantShopMapper.updateById(wxMerchantShop);
                //更新商铺状态
                WxShop wxShop = new WxShop();
                wxShop.setTenantId(wxMerchant.getTenantId());
                wxShop.setId(wxMerchantShop.getShopId());
                wxShop.setStatus(EnumShopStatus.NOT_RENT.getCode());
                wxShopMapper.updateById(wxShop);
            }
        }
        //解绑用户
        WxMerchantBUser bUser = new WxMerchantBUser();
        bUser.setMerchantId(wxMerchant.getId());
        List<WxMerchantBUser> wxMerchantBUserMapperList = wxMerchantBUserMapper.findList(bUser);
        for (WxMerchantBUser wxMerchantBUser : wxMerchantBUserMapperList) {
            wxMerchantBUser.setStatus(EnumMerchantBUserStatus.INVALID.getCode());
            wxMerchantBUserMapper.updateById(wxMerchantBUser);
        }
        //作废卡券
        WxCouponMerchant wxCouponMerchant = new WxCouponMerchant();
        wxCouponMerchant.setTenantId(wxMerchant.getTenantId());
        wxCouponMerchant.setMerchantId(wxMerchant.getId());
        wxCouponMerchant.setStatus(EnumCouponMerchantStatus.COUPON_MERCHANT_STATUS_VALID.getCode());
        List<WxCouponMerchant> wxCouponMerchantList = wxCouponMerchantMapper.findList(wxCouponMerchant);
        List<Long> couponIds = wxCouponMerchantList.stream().map(cm->cm.getProductId()).collect(Collectors.toList());

        couponIds.stream().filter(cid->!isCouponMerchantValid(cid)).forEach(cid->{
            WxCoupon wxCoupon = new WxCoupon();
            wxCoupon.setId(cid);
            wxCoupon.setTenantId(wxMerchant.getTenantId());
            wxCoupon.setStatus(EnumCouponStatus.COUPON_STATUS_TAKE_OFFF.getCode());
            wxCouponService.saveOrUpdate(wxCoupon);
        });
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData addMerchant(WxMerchant wxMerchant, Long userId) {
        try {

            final IdWorker idWorker = IdWorker.get();
            long merchantId = idWorker.nextId();
            //检查商户名称
            if (hasMerchant(wxMerchant)) {
                return new ResultData(ErrorCode.MERCHANT_NAME_IS_FOUND);
            }
            //保存商户商铺的关联
            List<Long> shopidlist = wxMerchant.getShopids();
            if (shopidlist.isEmpty()) {
                return new ResultData(ErrorCode.SHOP_NOT_SELECTED);
            }

            //更新商铺
            for (long shopid : shopidlist) {
                WxShop shop = wxShopMapper.selectById(shopid);
                if (shop.getStatus().equals(EnumShopStatus.RENT.getCode())) {
                    return new ResultData(ErrorCode.SHOP_IS_RENT.getCode(), "店铺 " + shop.getShopNumber() + " 已出租");
                }
                WxMerchantShop wxMerchantShop = new WxMerchantShop();
                wxMerchantShop.setShopId(shopid);
                wxMerchantShop.setIsDel(EnumDelStatus.NOT_DEL.getCode());
                int count = wxMerchantShopMapper.selectCount(new QueryWrapper(wxMerchantShop));
                if (count > 0) {
                    return new ResultData(ErrorCode.SHOP_IS_RENT.getCode(), "店铺 " + shop.getShopNumber() + " 已出租");
                }
                //更新商铺状态
                shop.setStatus(EnumShopStatus.RENT.getCode());
                wxShopMapper.updateById(shop);
                //关联表插入
                wxMerchantShop.setId(idWorker.nextId());
                wxMerchantShop.setMerchantId(merchantId);
                wxMerchantShop.setTenantId(wxMerchant.getTenantId());
                wxMerchantShop.setShopId(shopid);
                wxMerchantShop.setIsDel(EnumDelStatus.NOT_DEL.getCode());
                Date shopdate = new Date();
                wxMerchantShop.setUpdateDate(shopdate);
                wxMerchantShop.setCreateDate(shopdate);
                wxMerchantShopMapper.insert(wxMerchantShop);
            }

            wxMerchant.setId(merchantId);
            Date date = new Date();
            wxMerchant.setStatus(EnumMerchantStatus.VALID.getCode());
            if(wxMerchant.getIsAdmin() == null) {
                wxMerchant.setIsAdmin(EnumYesOrNo.NO.getCode());
            }
            wxMerchant.setUpdateDate(date);
            wxMerchant.setCreateDate(date);
            if (StringUtils.isNotBlank(wxMerchant.getCoverPicture())) {
                List<String> coverPicture = JSONArray.parseArray(wxMerchant.getCoverPicture(), String.class);
                if (!coverPicture.isEmpty()) {
                    wxMerchant.setImgUrl(coverPicture.get(0));
                }
            } else {
                if (StringUtils.isNotBlank(wxMerchant.getImgUrl())) {
                    List<String> strList = new ArrayList<String>();
                    strList.add(wxMerchant.getImgUrl());
                    wxMerchant.setCoverPicture(JSONArray.toJSONString(strList));
                }
            }
            wxMerchantMapper.insert(wxMerchant);

            //关联合同
            if (wxMerchant.getRentContractId() != null) {
                WxRentContract wxRentContract = wxRentContractMapper.selectById(wxMerchant.getRentContractId());
                if (wxRentContract == null) {
                    return new ResultData(ErrorCode.RENT_CONTRACT_IS_NOT_FOUND);
                }
                if (wxRentContract.getStatus().equals(EnumRentContractStatus.CONTRACT_TERMINATE)) {
                    return new ResultData(ErrorCode.RENT_CONTRACT_IS_TERMINATED);
                }
                wxRentContract.setMerchantId(merchantId);
                wxRentContract.setUpdatetime(new Date());
                if (wxRentContract.getRentalStartDate().before(new Date())) {
                    wxRentContract.setStatus(EnumRentContractStatus.RENT_PAID.getCode());
                } else {
                    wxRentContract.setStatus(EnumRentContractStatus.SIGNED_RENT_UNPAID.getCode());
                }
                wxRentContractMapper.updateById(wxRentContract);

                EventUtil.publistRentEvent(wxRentContractService,wxRentContract);
                //预览账单改为正式,并写入商户id(租赁合同需要绑定商户才变成已签约)
                WxBillRent billRent = new WxBillRent();
                billRent.setRentContractId(wxMerchant.getRentContractId());
                billRent.setIsPreview(EnumIsPreview.NO.getCode());
                billRent.setMerchantId(merchantId);
                wxBillRentMapper.updatePreviewStatus(billRent);
                //创建押金
                wxRentContractService.buildDeposit(wxMerchant, userId,wxMerchant.getRentContractId());
                //作废合同
                wxRentContractService.updateInvalidContract(wxMerchant.getRentContractId());
                //合并合同-更新物业账单
                if (wxRentContract.getOperationType().equals(EnumContractOperationType.WHOLE.getCode())) {
                    wxRentContractService.updatePropertyPreviewBill(wxRentContract);
                }
            }
            return new ResultData(Result.SUCCESS, "商户创建成功", merchantId);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("db failed: 商户创建失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }

    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchant(WxMerchant wxMerchant) {

        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }

            if(wxMerchant.getIsDel() != null && wxMerchant.getIsDel().equals(EnumDelStatus.DEL.getCode())) {
                // 停用商户
                WxMerchant oldMerchant = wxMerchantMapper.selectById(wxMerchant.getId());
                if(!oldMerchant.getCarVendorType().equals(EnumCarVendor.CAR_NOTFOUND.getCode())){
                    // 停车商户
                    logger.error("停车商户不能被删除");
                    return new ResultData(ErrorCode.MERCHANT_CAR_NOT_DEL);
                }
            } else {
                //检查商户名称
                if (hasMerchant(wxMerchant)) {
                    return new ResultData(ErrorCode.MERCHANT_NAME_IS_FOUND);
                }
            }
            Date date = new Date();
            wxMerchant.setUpdateDate(date);
            wxMerchantMapper.updateById(wxMerchant);
            return new ResultData(Result.SUCCESS, "商户更新成功");
        } catch (Exception e) {
            logger.error("db failed: 商户更新失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }

    }

    @Transactional(isolation=Isolation.SERIALIZABLE, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchantAccount(WxMerchant wxMerchant) {
        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }
            //添加商户的分账账户（不是必选）
            if (wxMerchant.getAccountId() != null
                    && wxMerchant.getAccountName() != null
                    && !wxMerchant.getAccountId().isEmpty()
                    && !wxMerchant.getAccountName().isEmpty()) {
                WxProfitSharingReceiver receiver = new WxProfitSharingReceiver();
                receiver.setReceiverAccount(wxMerchant.getAccountId());
                receiver.setReceiverComments(wxMerchant.getName());
                receiver.setReceiverType(wxMerchant.getAccountTypeValue());
                receiver.setTrueName(wxMerchant.getAccountName());
                receiver.setParameter(wxMerchant.getAccountParameter());
                return wxProfitSharingReceiverService.updateReceiver(wxMerchant, receiver);
            }
        } catch (Exception e) {
            logger.error("db failed: 账户操作失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "操作成功");

    }


    @Transactional(isolation=Isolation.SERIALIZABLE, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchantCorp(WxMerchant wxMerchant) {
        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }
            WxMerchantCorp wxMerchantCorp = new WxMerchantCorp();
            wxMerchantCorp.setMerchantId(wxMerchant.getId());
            List<WxMerchantCorp> list = wxMerchantCorpMapper.findList(wxMerchantCorp);
            if(list.isEmpty()){
                final IdWorker idWorker = IdWorker.get();
                WxMerchantCorp record = wxMerchant.getWxMerchantCorp();
                record.setId(idWorker.nextId());
                record.setTenantId(wxMerchant.getTenantId());
                record.setMerchantId(wxMerchant.getId());
                Date date = new Date();
                record.setCreateDate(date);
                record.setUpdateDate(date);
                wxMerchantCorpMapper.insert(record);
            }else{
                WxMerchantCorp record = wxMerchant.getWxMerchantCorp();
                Date date = new Date();
                record.setUpdateDate(date);
                wxMerchantCorpMapper.updateById(record);
            }
        } catch (Exception e) {
            logger.error("db failed: 操作法人信息失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "操作成功");

    }

    @Transactional(isolation=Isolation.SERIALIZABLE, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchantTax(WxMerchant wxMerchant) {
        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }
            WxMerchantTax wxMerchantTax = new WxMerchantTax();
            wxMerchantTax.setMerchantId(wxMerchant.getId());
            List<WxMerchantTax> list = wxMerchantTaxMapper.findList(wxMerchantTax);
            if(list.isEmpty()){
                final IdWorker idWorker = IdWorker.get();
                WxMerchantTax record = wxMerchant.getWxMerchantTax();
                record.setId(idWorker.nextId());
                record.setTenantId(wxMerchant.getTenantId());
                record.setMerchantId(wxMerchant.getId());
                Date date = new Date();
                record.setCreateDate(date);
                record.setUpdateDate(date);
                wxMerchantTaxMapper.insert(record);
            }else{
                WxMerchantTax record = wxMerchant.getWxMerchantTax();
                Date date = new Date();
                record.setUpdateDate(date);
                wxMerchantTaxMapper.updateById(record);
            }
        } catch (Exception e) {
            logger.error("db failed: 操作税务信息失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "操作成功");

    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public ResultData updateMerchantAdmin(WxMerchant wxMerchant) {
        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }
            WxAppinfo wxAppinfo = new WxAppinfo();
            wxAppinfo.setTenantId(wxMerchant.getTenantId());
            wxAppinfo.setType(EnumAppType.B.getCode());
            List<WxAppinfo> list = wxAppinfoMapper.findList(wxAppinfo);
            if (list.size() == 0) {
                return new ResultData(ErrorCode.APP_ID_NOT_FOUND);
            }
            wxAppinfo = list.get(0);
            List<WxMerchantBUser> users = wxMerchant.getUsers();

            //删除之前的关联用户
            WxMerchantBUser bUser = new WxMerchantBUser();
            bUser.setMerchantId(wxMerchant.getId() != null ? wxMerchant.getId() : 0);
            List<WxMerchantBUser> wxMerchantBUserMapperList = wxMerchantBUserMapper.findList(bUser);
            for (WxMerchantBUser wxMerchantBUser : wxMerchantBUserMapperList) {
                wxMerchantBUser.setStatus(EnumMerchantBUserStatus.INVALID.getCode());
                wxMerchantBUserMapper.updateById(wxMerchantBUser);
            }
            final IdWorker idWorker = IdWorker.get();
            //保存商户关联用户
            for (WxMerchantBUser user : users) {
                if (user.getId() == null) {
                    long id = idWorker.nextId();
                    user.setId(id);
                    user.setMerchantId(wxMerchant.getId());
                    user.setTenantId(wxMerchant.getTenantId());
                    user.setAppId(wxAppinfo.getAppId());
                    Date date = new Date();
                    user.setCreateDate(date);
                    user.setUpdateDate(date);
                    user.setStatus(EnumMerchantBUserStatus.VALID.getCode());
                    wxMerchantBUserMapper.insert(user);
                } else {//有id的更新
                    user.setMerchantId(wxMerchant.getId());
                    user.setTenantId(wxMerchant.getTenantId());
                    user.setAppId(wxAppinfo.getAppId());
                    Date date = new Date();
                    user.setUpdateDate(date);
                    user.setStatus(EnumMerchantBUserStatus.VALID.getCode());
                    wxMerchantBUserMapper.updateById(user);
                }
            }
            return new ResultData(Result.SUCCESS, "账号操作成功");
        } catch (Exception e) {
            logger.error("db failed: 账号操作失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
    }

    @Override
    public ResultData updateMerchantLevel(WxMerchant wxMerchant) {
        try {
            if (wxMerchant.getId() == null) {
                return new ResultData(ErrorCode.MERCHANT_INFO_NOT_FOUND);
            }
            wxMerchantMapper.updateById(wxMerchant);
            wxLevelConfigService.batchSaveByMerchantId(wxMerchant.getTenantId(), wxMerchant.getId(), wxMerchant.getLevelConfigList());
        } catch (Exception e) {
            logger.error("db failed: 账号操作失败, e:" + e.getMessage());
            throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage());
        }
        return new ResultData(Result.SUCCESS, "操作成功");
    }

    @Override
    public WxMerchantVo findMerchantById(Long id) {
        WxMerchantDto merchant = new WxMerchantDto();
        merchant.setId(id);
        List<WxMerchantVo> listCVo = wxMerchantMapper.findListCVo(merchant);
        return listCVo.isEmpty() ? new WxMerchantVo() : listCVo.get(0);
    }

    @Override
    public WxMerchant findOne(WxMerchant wxMerchant) {
        return wxMerchantMapper.selectOne(new QueryWrapper(wxMerchant));
    }

    @Override
    public void exportData(WxMerchant wxMerchant, HttpServletRequest request, HttpServletResponse response) {
        List<WxMerchant> list = wxMerchantMapper.findList(wxMerchant);

        list.stream().forEach(m->{
            //分账信息
            WxProfitSharingReceiver receiver = wxProfitSharingReceiverService.findReceiver(m);
            if (receiver != null) {
                m.setAccountId(receiver.getReceiverAccount());
                m.setAccountName(receiver.getTrueName());
                m.setAccountTypeValue(receiver.getReceiverType());
            }
            WxRentContract wxRentContract = new WxRentContract();
            wxRentContract.setMerchantId(m.getId());
            List<WxRentContract> lrc = wxRentContractMapper.selectRentContractByMerchantId(wxRentContract);
            if (!lrc.isEmpty()) {
                m.setRentalStartDate(lrc.get(0).getRentalStartDate());
                m.setRentalEndDate(lrc.get(0).getRentalEndDate());
            }

            //商铺信息
            m.setShopVos(wxShopMapper.findShopVoList(m.getId()));

            //店员信息
            WxMerchantBUser wxMerchantBUser = new WxMerchantBUser();
            wxMerchantBUser.setMerchantId(m.getId());
            wxMerchantBUser.setStatus(EnumMerchantBUserStatus.VALID.getCode());
            m.setUsers(wxMerchantBUserMapper.findList(wxMerchantBUser));
        });
        excelService.exportExcel(list, null, "商户信息", WxMerchant.class, "商户信息数据.xlsx", response, false);
    }

    @Override
    public ResultData top(WxMerchant wxMerchant) {
        if (wxMerchant == null) {
            return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(), "未选择要置顶的商户");
        }
        if (wxMerchant.getId() == null) {
            return new ResultData(ErrorCode.SYS_PARAMETER_ERROR.getCode(), "未选择要置顶的商户");
        }
        wxMerchant.setTopTime(new Date());
        wxMerchantMapper.updateById(wxMerchant);
        return new ResultData(Result.SUCCESS, "操作成功");
    }

    @Override
    public ResultData useAccount(WxProfitSharingReceiver wxProfitSharingReceiver) {
        WxProfitSharingReceiver profitSharingReceiver = wxProfitSharingReceiverMapper.selectById(wxProfitSharingReceiver.getId());
        profitSharingReceiver.setIsUse(wxProfitSharingReceiver.getIsUse());
        profitSharingReceiver.setUpdateTime(new Date());
        wxProfitSharingReceiverMapper.updateById(profitSharingReceiver);

        Long merchantId = profitSharingReceiver.getMerchantId();
        String accout = profitSharingReceiver.getReceiverAccount();
        WxMerchant wxMerchant = wxMerchantMapper.selectById(merchantId);
        String linkPhone = wxMerchant.getLinkPhone();
        String merchantName = wxMerchant.getName();
        String tenantId = wxProfitSharingReceiver.getTenantId();
        if (StringUtils.isEmpty(linkPhone)) {
            return new ResultData(Result.SUCCESS, "操作成功");
        }
        //发信息
        Integer isUse = wxProfitSharingReceiver.getIsUse();
        Integer type = EnumMsgModel.ACCEPT_SHARING_ACCOUNT_NOTIFY_MANAGER.getCode();
        if (isUse.equals(EnumProfitSharingUse.NO.getCode())) {
            type = EnumMsgModel.ACCEPT_SHARING_ACCOUNT_NOTIFY_MANAGER.getCode();
        }
        wxProfitSharingReceiverService.sendMsg(linkPhone, accout, merchantName, null, type, tenantId);
        return new ResultData(Result.SUCCESS, "操作成功");
    }

    @Override
    public boolean hasMerchant(WxMerchant wxMerchant) {
        wxMerchant.setStatus(EnumMerchantStatus.VALID.getCode());
        return wxMerchantMapper.hasMerchant(wxMerchant) > 0 ? true : false;
    }

    @Override
    public Optional<WxMerchant> findByName(String name) {
        WxMerchant wxMerchant = new WxMerchant();
        wxMerchant.setName(name);
        wxMerchant.setIsDel(EnumDelStatus.NOT_DEL.getCode());
        wxMerchant.setStatus(EnumMerchantStatus.VALID.getCode());

        List<WxMerchant> merchantList = wxMerchantMapper.selectList(new QueryWrapper(wxMerchant));
        if (merchantList.size() == 1)
            return Optional.of(merchantList.get(0));
        return Optional.empty();
    }

    @Override
    public PageInfo<WxMerchant> listVoAsPage(WxMerchant record, Integer pageIndex, Integer pageSize) {
        PageHelper.startPage(pageIndex, pageSize);
        List<WxMerchant> merchants = wxMerchantMapper.findListVo(record);
        for (WxMerchant merchant : merchants) {
            if (record.getRentShopType() != null) {
                List<Map<String, Object>> shops = new ArrayList<>();
                WxMerchantShop wxMerchantShop = new WxMerchantShop();
                wxMerchantShop.setMerchantId(merchant.getId());
                wxMerchantShop.setIsDel(EnumDelStatus.NOT_DEL.getCode());
                List<WxMerchantShop> wxMerchantShopList = wxMerchantShopMapper.findList(wxMerchantShop);
                for (WxMerchantShop merchantShop : wxMerchantShopList) {
                    WxShop shop = new WxShop();
                    shop.setId(merchantShop.getShopId());
                    List<Map<String, Object>> shoplist = wxShopMapper.findListMap(shop);
                    if (shoplist.size() > 0) {
                        shops.add(shoplist.get(0));
                    }
                }
                merchant.setShoplist(shops);
            }

            WxRentContract rc = new WxRentContract();
            rc.setMerchantId(record.getId());
            rc.setTenantId(record.getTenantId());
            List<WxRentContract> rentContractList = wxRentContractMapper.findList(rc);
            if(CollectionUtils.isEmpty(rentContractList)){
                merchant.setHasContract(EnumHasContract.NO.getCode());
            }else{
                merchant.setHasContract(EnumHasContract.HAS.getCode());
            }
        }
        PageInfo<WxMerchant> pageInfo = new PageInfo<>(merchants);
        return pageInfo;
    }

    @Override
    public PageInfo<WxMerchantTradeVo> userTradeList(WxMerchant record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxMerchantMapper.userTradeList(record));
    }

    @Override
    public void exportUserTradeList(WxMerchant record,HttpServletRequest request, HttpServletResponse response) {
        List<WxMerchantTradeDetailVo> datalist = wxMerchantMapper.userTradeDetailList(record);
        datalist.stream().forEach(e->{
            if(e.getTradeDate() != null) {
                e.setTradeDateStr(DateUtils.formatDateTime(e.getTradeDate()));
            }
            BigDecimal bigDecimal = new BigDecimal(e.getCouponPrice());
            e.setCouponPriceStr(bigDecimal.divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP).toString());
            bigDecimal = new BigDecimal(e.getCouponSale());
            e.setCouponSaleStr(bigDecimal.divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP).toString());
            bigDecimal = new BigDecimal(e.getTradeAmt());
            e.setTradeAmtStr(bigDecimal.divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP).toString());

        });
        excelService.exportExcel(datalist, null, "商户会员消费列表", WxMerchantTradeDetailVo.class, "商户会员消费列表.xlsx", response, false);
    }

    @Override
    public PageInfo<WxMerchantTradeDetailVo> userTradeDetailList(WxMerchant record, Integer pageIndex, Integer pageSize) {
        return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxMerchantMapper.userTradeDetailList(record));
    }
}
