
package com.tmerclub.cloud.multishop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.tmerclub.cloud.api.auth.bo.UidInfoBO;
import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.auth.dto.AuthAccountDTO;
import com.tmerclub.cloud.api.auth.feign.AccountFeignClient;
import com.tmerclub.cloud.api.biz.feign.AttachFileFeignClient;
import com.tmerclub.cloud.api.biz.feign.NotifyFeignClient;
import com.tmerclub.cloud.api.coupon.feign.CouponFeignClient;
import com.tmerclub.cloud.api.delivery.feign.SameCityFeignClient;
import com.tmerclub.cloud.api.discount.feign.DiscountFeignClient;
import com.tmerclub.cloud.api.feign.SearchSpuFeignClient;
import com.tmerclub.cloud.api.live.feign.LiveFeignClient;
import com.tmerclub.cloud.api.multishop.bo.EsShopDetailBO;
import com.tmerclub.cloud.api.multishop.bo.ShopSimpleBO;
import com.tmerclub.cloud.api.multishop.constant.ShopStatus;
import com.tmerclub.cloud.api.multishop.vo.ShopDetailVO;
import com.tmerclub.cloud.api.payment.constant.PaySysType;
import com.tmerclub.cloud.api.payment.feign.AllinpayFeignClient;
import com.tmerclub.cloud.api.platform.constant.OfflineHandleEventStatus;
import com.tmerclub.cloud.api.platform.constant.OfflineHandleEventType;
import com.tmerclub.cloud.api.platform.dto.OfflineHandleEventDTO;
import com.tmerclub.cloud.api.platform.feign.OfflineHandleEventFeignClient;
import com.tmerclub.cloud.api.platform.vo.OfflineHandleEventVO;
import com.tmerclub.cloud.api.product.feign.*;
import com.tmerclub.cloud.api.seckill.feign.SeckillFeignClient;
import com.tmerclub.cloud.api.user.feign.PopupFeignClient;
import com.tmerclub.cloud.common.cache.constant.CacheNames;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.*;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.order.constant.ShopType;
import com.tmerclub.cloud.common.product.constant.SalesPriceType;
import com.tmerclub.cloud.common.product.constant.SalesType;
import com.tmerclub.cloud.common.product.dto.ProductSearchLimitDTO;
import com.tmerclub.cloud.common.product.vo.search.SpuSearchVO;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.common.util.IpHelper;
import com.tmerclub.cloud.common.util.PrincipalUtil;
import com.tmerclub.cloud.multishop.constant.AuditStatus;
import com.tmerclub.cloud.multishop.dto.*;
import com.tmerclub.cloud.multishop.mapper.CompanyAuditingMapper;
import com.tmerclub.cloud.multishop.mapper.ShopDetailMapper;
import com.tmerclub.cloud.multishop.mapper.ShopUserMapper;
import com.tmerclub.cloud.multishop.mapper.ShopWalletMapper;
import com.tmerclub.cloud.multishop.model.*;
import com.tmerclub.cloud.multishop.service.*;
import com.tmerclub.cloud.multishop.vo.*;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 店铺详情
 *
 * @author tmerclub
 * @date 2020-11-23 16:24:29
 */
@Service
public class ShopDetailServiceImpl implements ShopDetailService {
    private static final Logger log = LoggerFactory.getLogger(ShopDetailServiceImpl.class);

    @Autowired
    private ShopDetailMapper shopDetailMapper;
    @Autowired
    private ShopCompanyService shopCompanyService;
    @Autowired
    private ShopAuditingService shopAuditingService;
    @DubboReference
    private SearchSpuFeignClient searchSpuFeignClient;
    @Autowired
    private ShopWalletMapper shopWalletMapper;
    @Autowired
    private ShopUserService shopUserService;
    @Autowired
    private ShopExtensionService shopExtensionService;
    @DubboReference
    private AccountFeignClient accountFeignClient;
    @DubboReference
    private SpuFeignClient spuFeignClient;
    @Autowired
    private ShopUserMapper shopUserMapper;
    @DubboReference
    private BrandFeignClient brandFeignClient;
    @DubboReference
    private OfflineHandleEventFeignClient offlineHandleEventFeignClient;
    @DubboReference
    private NotifyFeignClient notifyFeignClient;
    @Autowired
    private ShopBankCardService shopBankCardService;
    @DubboReference
    private CategoryShopFeignClient categoryShopFeignClient;
    @DubboReference
    private BrandShopFeignClient brandShopFeignClient;
    @DubboReference
    private SameCityFeignClient sameCityFeignClient;
    @DubboReference
    private ShopCartFeignClient shopCartFeignClient;
    @DubboReference
    private AttachFileFeignClient attachFileFeignClient;
    @DubboReference
    private SeckillFeignClient seckillFeignClient;
    @Autowired
    private IndexImgService indexImgService;
    @DubboReference
    private DiscountFeignClient discountFeignClient;
    @DubboReference
    private CouponFeignClient couponFeignClient;
    @Autowired
    private ShopSubstituteSalesService shopSubstituteSalesService;
    @DubboReference
    private AllinpayFeignClient allinpayFeignClient;
    @Autowired
    private ShopAllinpayService shopAllinpayService;
    @Autowired
    private CompanyAuditingMapper companyAuditingMapper;
    @DubboReference
    private LiveFeignClient liveFeignClient;
    @DubboReference
    private WarehouseFeignClient warehouseFeignClient;
    @DubboReference
    private PopupFeignClient popupFeignClient;

    private static final String DONT_HAVE = "用户不存在。";

    @Override
    public PageVO<ShopDetailVO> page(PageDTO pageDTO, ShopDetailDTO shopDetailDTO) {
        Integer paySysType = shopAllinpayService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value();
        shopDetailDTO.setPaySysType(paySysType);
        PageVO<ShopDetailVO> page = PageUtil.doPage(pageDTO, () -> shopDetailMapper.list(shopDetailDTO));
        if (shopAllinpayService.getIsAllinpay()) {
            for (ShopDetailVO shopDetailVO : page.getList()) {
                setAllinpayShopStatus(shopDetailVO);
            }
        }
        return page;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public ShopDetailVO getByShopId(Long shopId) {
        ShopDetailVO shopDetailVO = shopDetailMapper.getByShopId(shopId);
        boolean shopTypeCheck = Objects.nonNull(shopDetailVO) && !Objects.equals(shopDetailVO.getShopId(),Constant.PLATFORM_SHOP_ID);
        if (shopTypeCheck && shopAllinpayService.getIsAllinpay()) {
            // 通联是上线待审核的话店铺状态也做对应展示
            setAllinpayShopStatus(shopDetailVO);
        }
        return shopDetailVO;
    }

    private static void setAllinpayShopStatus(ShopDetailVO shopDetailVO) {
        if (Objects.isNull(shopDetailVO)) {
            return;
        }
        if (Objects.equals(shopDetailVO.getAllinpayShopStatus(), AllinpayShopStatus.WAIT_AUDIT.value())) {
            shopDetailVO.setShopStatus(ShopStatus.OFFLINE_AWAIT_AUDIT.value());
        }
        if (Objects.equals(shopDetailVO.getAllinpayShopStatus(), AllinpayShopStatus.OPEN_WAIT_AUDIT.value())) {
            shopDetailVO.setShopStatus(ShopStatus.OPEN_AWAIT_AUDIT.value());
        }
        if (Objects.equals(shopDetailVO.getAllinpayShopStatus(), AllinpayShopStatus.OFFLINE.value()) ||
                Objects.equals(shopDetailVO.getAllinpayShopStatus(), AllinpayShopStatus.UN_AVAILABLE.value())) {
            shopDetailVO.setShopStatus(ShopStatus.OFFLINE.value());
        }
        if (Objects.equals(shopDetailVO.getCompanyInfoProcessStatus(), CompanyInfoProcessStatus.FAIL.value())
                && Objects.equals(shopDetailVO.getAllinpayShopStatus(), AllinpayShopStatus.OFFLINE.value())) {
            shopDetailVO.setShopStatus(ShopStatus.AUDIT_FAIL.value());
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopDetailDTO.shopId")
    @Transactional(rollbackFor = Exception.class)
    public void update(ShopDetailDTO shopDetailDTO) {
        ShopDetail shopDetail = BeanUtil.map(shopDetailDTO, ShopDetail.class);
        // 若经纬度数据变更，需清空同城配送中的位置信息
        ShopDetailVO dbShopDetail = shopDetailMapper.getByShopId(shopDetail.getShopId());
        if (!PrincipalUtil.isDbPhone(shopDetail.getContactPhone(), dbShopDetail.getContactPhone(), false)) {
            throw new LuckException("请输入正确的手机号");
        }
        if (shopDetail.getContactPhone().contains(Constant.ASTERISK)) {
            shopDetail.setContactPhone(dbShopDetail.getContactPhone());
        }
        // 给还没创建通联会员的商家创建
        if (shopAllinpayService.getIsAllinpay() && Objects.equals(dbShopDetail.getIsCreateMember(), 0)) {
            createAllinpayMemberByShopId(shopDetail.getShopId());
        }
        this.checkShopInfo(shopDetailDTO, false);

        // 更新商品
        spuFeignClient.updateSpuByShopId(shopDetail.getShopId(), SysTypeEnum.MULTISHOP.value());
        shopDetailMapper.update(shopDetail);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public void deleteById(Long shopId) {
        shopDetailMapper.deleteById(shopId);
    }

    @Override
    public List<ShopDetail> listByShopIds(List<Long> shopIds) {
        if (CollUtil.isEmpty(shopIds)) {
            return new ArrayList<>(0);
        }
        return shopDetailMapper.listByShopIds(shopIds);
    }

    @Override
    public PageVO<ShopDetailAppVO> shopSearchPage(PageDTO pageDTO, ShopDetailDTO shopDetailDTO) {
        shopDetailDTO.setPaySysType(shopAllinpayService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value());
        PageVO<ShopDetailAppVO> page = PageUtil.doPage(pageDTO, () -> shopDetailMapper.shopSearchList(shopDetailDTO));
        List<Long> spuIds = page.getList().stream().map(ShopDetailAppVO::getShopId).collect(Collectors.toList());
        if (Objects.isNull(shopDetailDTO.getSpuNum()) || shopDetailDTO.getSpuNum() <= 0) {
            return page;
        }
        ProductSearchLimitDTO productSearchLimitDTO = new ProductSearchLimitDTO(shopDetailDTO.getSpuNum());
        productSearchLimitDTO.setShopIds(spuIds);
        ServerResponseEntity<List<SpuSearchVO>> spuResponse = searchSpuFeignClient.limitSpuList(productSearchLimitDTO);
        if (!Objects.equals(spuResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(spuResponse.getMsg());
        } else if (CollUtil.isEmpty(spuResponse.getData())) {
            return page;
        }
        List<SpuSearchVO> data = spuResponse.getData();
        Map<Long, List<SpuSearchVO>> shopMap = data.stream().collect(Collectors.groupingBy(SpuSearchVO::getShopId));
        for (ShopDetailAppVO shopDetail : page.getList()) {
            List<SpuSearchVO> spuSearchVOList = shopMap.get(shopDetail.getShopId());
            if (CollUtil.isEmpty(spuSearchVOList)) {
                spuSearchVOList = new ArrayList<>(0);
            }
            shopDetail.setSpuList(spuSearchVOList);
        }
        return page;
    }

    @Override
    public ShopDetailVO getShopByShopId(Long shopId) {
        return shopDetailMapper.getShopByShopId(shopId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void applyShop(ShopDetailDTO shopDetailDTO) {
        checkShopInfo(shopDetailDTO, true);
        ShopDetail newShopDetail = BeanUtil.map(shopDetailDTO, ShopDetail.class);
        // 申请开店
        newShopDetail.setShopStatus(ShopStatus.APPLYING.value());
        newShopDetail.setType(ShopType.STOP.value());
        shopDetailMapper.save(newShopDetail);
        shopDetailDTO.setShopId(newShopDetail.getShopId());

        // 插入一条审核记录
        ShopAuditing auditing = new ShopAuditing();
        auditing.setShopId(newShopDetail.getShopId());
        auditing.setCreateTime(new Date());
        auditing.setStatus(AuditStatus.WAITAUDIT.value());
        auditing.setUpdateTime(new Date());
        auditing.setRemarks(shopDetailDTO.getRemarks());
        shopAuditingService.save(auditing);
        // 创建账号
        createShopAccount(shopDetailDTO, StatusEnum.DELETE);
    }

    /**
     * 审核商家信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void audit(ShopAuditingDTO shopAuditingDTO) {
        Date now = new Date();
        ShopAuditingVO dbShopAyditing = shopAuditingService.getByshopId(shopAuditingDTO.getShopId());
        if (Objects.isNull(dbShopAyditing)) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }
        shopAuditingDTO.setShopAuditingId(dbShopAyditing.getShopAuditingId());
        // 非待审核的店铺，不能再进行审核
        if (!Objects.equals(dbShopAyditing.getStatus(), AuditStatus.WAITAUDIT.value())) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }
        // 修改店铺状态
        ShopDetailVO shopDetailVO = getByShopId(shopAuditingDTO.getShopId());
        if (shopDetailVO == null) {
            // 店铺信息不存在
            throw new LuckException("店铺信息不存在");
        }
        // 查询店铺账号（审核期间店铺有且仅有一个账号）
        ShopUserDTO shopUserDTO = new ShopUserDTO();
        shopUserDTO.setShopId(shopDetailVO.getShopId());
        List<ShopUserVO> shopUserVOList = shopUserService.listShopUser(shopUserDTO);
        if (CollectionUtils.isEmpty(shopUserVOList)) {
            throw new LuckException("店铺账号不存在");
        }
        ShopUserVO shopUserVO = shopUserVOList.get(0);
        // 修改店铺账号缓存信息
        ShopDetail shopDetail = BeanUtil.map(shopDetailVO, ShopDetail.class);
        UidInfoBO uidInfoBO = new UidInfoBO();
        uidInfoBO.setUserId(shopUserVO.getShopUserId());
        uidInfoBO.setUsername(shopUserVO.getNickName());
        uidInfoBO.setSysType(SysTypeEnum.MULTISHOP.value());
        uidInfoBO.setTenantId(shopAuditingDTO.getShopId());
        uidInfoBO.setIsAdmin(UserAdminType.ADMIN.value());
        // 审核不通过
        if (Objects.equals(shopAuditingDTO.getStatus(), AuditStatus.FAILAUDIT.value())) {
            if (!shopAllinpayService.getIsAllinpay() || !Objects.equals(shopDetailVO.getType(), ShopType.SELF_SHOP.value())) {
                shopDetail.setShopStatus(ShopStatus.APPLYING.value());
            }
        }
        // 审核通过
        else {
            shopDetail.setType(shopAuditingDTO.getShopType());
            if (shopAllinpayService.getIsAllinpay()) {
                shopDetail.setShopStatus(ShopStatus.OPEN.value());
            } else {
                handleContract(shopDetail, shopAuditingDTO.getContractStartTime(), shopAuditingDTO.getContractEndTime(), now);
            }
            shopDetail.setIsPreferred(IsPassShopEnum.NO.value());
            updateShopCompanyStatus(shopDetail.getShopId(), AuditStatus.SUCCESSAUDIT.value());
            if (!shopAllinpayService.getIsAllinpay()) {
                uidInfoBO.setIsPassShop(IsPassShopEnum.YES.value());
                uidInfoBO.setSysType(SysTypeEnum.MULTISHOP.value());
                ServerResponseEntity<Void> updateTenantIdRes = accountFeignClient.updateNoAuditUidInfo(uidInfoBO);
                if (!updateTenantIdRes.isSuccess()) {
                    throw new LuckException("审核失败");
                }
            }
            // 把商家自定义品牌添加为平台品牌
            brandFeignClient.updateCustomBrandToPlatformBrandByShopId(shopAuditingDTO.getShopId(), SysTypeEnum.MULTISHOP.value());
            // 新店初始化事件 (分销设置（暂无）), 分销设置是平台统一设置，店铺暂无分销设置
            // 创建默认仓库
            warehouseFeignClient.createWarehouseByShopId(shopAuditingDTO.getShopId(), SysTypeEnum.MULTISHOP.value(), shopDetail.getContactPhone(), shopDetail.getContactName());
        }
        shopAuditingDTO.setAuditorId(Objects.isNull(AuthUserContext.get()) ? null : AuthUserContext.get().getUserId());
        shopAuditingService.update(BeanUtil.map(shopAuditingDTO, ShopAuditing.class));
        shopDetailMapper.update(shopDetail);
    }

    private void handleContract(ShopDetail shopDetail, Date startTime, Date endTime, Date now) {
        shopDetail.setContractStartTime(DateUtil.beginOfDay(startTime));
        shopDetail.setContractEndTime(Objects.isNull(endTime) ? endTime : getSaveEndOfDay(endTime));
        if ( now.compareTo(shopDetail.getContractStartTime()) >= 0 && (Objects.isNull(shopDetail.getContractEndTime()) || now.compareTo(shopDetail.getContractEndTime()) < 0)) {
            // 如果店铺的签约时间包含当前时间，则把店铺状态置为营业中
            shopDetail.setShopStatus(ShopStatus.OPEN.value());
        } else {
            // 如果店铺的签约时间不包含当前时间，则把店铺状态置为停业中
            shopDetail.setShopStatus(ShopStatus.STOP.value());
        }
    }

    /**
     *  更新店铺工商信息审核状态
     * @param shopId
     * @param status
     */
    private void updateShopCompanyStatus(Long shopId, Integer status) {
        ShopCompanyVO shopCompanyWaitAudit = shopCompanyService.getShopCompanyByShopIdAndStatus(shopId, AuditStatus.WAITAUDIT.value());
        if (Objects.isNull(shopCompanyWaitAudit)) {
            throw new LuckException("缺少店铺工商资料");
        }
        ShopCompany shopCompany = BeanUtil.map(shopCompanyWaitAudit, ShopCompany.class);
        shopCompany.setStatus(status);
        shopCompanyService.updateByShopId(shopCompany, shopId, 0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void changeSpuStatus(Long shopId, Integer shopStatus) {
        shopDetailMapper.changeShopStatus(shopId, shopStatus);
        // 店铺
        if (!StatusEnum.offlineOrDelete(shopStatus)) {
            return;
        }
        // 将该店铺所有的商品下线
        ServerResponseEntity<Void> spuResponse = spuFeignClient.offlineSpuByShopId(shopId);
        if (!Objects.equals(spuResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(spuResponse.getMsg());
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public void removeCacheByShopId(Long shopId) {
    }

    @Override
    public EsShopDetailBO shopExtensionData(Long shopId) {
        return shopDetailMapper.shopExtensionData(shopId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void createShop(ShopDetailDTO shopDetailDTO) {
        checkShopInfo(shopDetailDTO, true);
        ShopDetail shopDetail = BeanUtil.map(shopDetailDTO, ShopDetail.class);
        // 赋默认值
        shopDetail.setType(ShopType.STOP.value());
        shopDetail.setShopStatus(ShopStatus.APPLYING.value());
        shopDetailMapper.save(shopDetail);
        // 通联创建企业会员
        shopAllinpayService.createAllinpayCompanyMember(shopDetail.getShopId());
        // 创建店铺数据
        addShopInfo(shopDetail.getShopId());

        Long shopUserId = AuthUserContext.get().getUserId();
        // 更新文件记录表中shopId
        ServerResponseEntity<Void> attachRes = attachFileFeignClient.updateShopIdByUid(shopDetail.getShopId());
        if (!attachRes.isSuccess()) {
            throw new LuckException(attachRes.getMsg());
        }
        // 保存shopId到店铺用户表
        if (shopUserMapper.updateShopIdByShopUserId(shopDetail.getShopId(), shopUserId) != 1) {
            throw new LuckException("保存店铺信息错误");
        }
        // 保存shopId到账号表
        UidInfoBO userInfoInTokenBO = AuthUserContext.get();
        userInfoInTokenBO.setTenantId(shopDetail.getShopId());
        ServerResponseEntity<Void> updateTenantIdRes = accountFeignClient.updateNoAuditUidInfo(userInfoInTokenBO);
        if (!updateTenantIdRes.isSuccess()) {
            throw new LuckException(updateTenantIdRes.getMsg());
        }

        // 保存店铺代销设置默认值
        ShopSubstituteSales shopSubstituteSales = new ShopSubstituteSales();
        shopSubstituteSales.setShopId(shopDetail.getShopId());
        shopSubstituteSales.setSalesType(SalesType.MANUAL_OPERATION_PRICE.value());
        shopSubstituteSales.setOrderShape(0);
        shopSubstituteSales.setSalesPriceType(SalesPriceType.PROPORTION_PRICE.value());
        shopSubstituteSales.setSalesPrice(0L);
        shopSubstituteSalesService.save(shopSubstituteSales);
    }

    @Override
    public List<ShopDetailVO> getShopDetailByShopIdsShopName(List<Long> shopIds, String shopName) {
        return shopDetailMapper.getShopDetailByShopIdsShopName(null, shopName);
    }

    @Override
    public ShopDetailVO getShoExtensionsByShopId(Long shopId) {
        ShopDetailVO shopDetailVO = shopDetailMapper.getShopExtensionsByShopId(shopId);
        // 通联是上线待审核的话店铺状态也做对应展示
        setAllinpayShopStatus(shopDetailVO);
        return shopDetailVO;
    }

    @Override
    public Integer countByMobile(String mobile) {
        return shopDetailMapper.countByMobile(mobile);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopDetailVO.shopId")
    @GlobalTransactional(rollbackFor = Exception.class)
    public void offline(ShopDetailVO shopDetailVO, String offlineReason, Long sysUserId) {
        Integer sysType = SysTypeEnum.MULTISHOP.value();
        // 添加下线处理记录
        OfflineHandleEventDTO offlineHandleEventDTO = new OfflineHandleEventDTO();
        offlineHandleEventDTO.setHandleId(shopDetailVO.getShopId());
        offlineHandleEventDTO.setHandleType(OfflineHandleEventType.SHOP.getValue());
        offlineHandleEventDTO.setOfflineReason(offlineReason);
        offlineHandleEventDTO.setHandlerId(sysUserId);
        offlineHandleEventDTO.setSysType(sysType);
        offlineHandleEventDTO.setStatus(shopAllinpayService.getIsAllinpay() ? OfflineHandleEventStatus.APPLY_BY_SHOP.getValue() : OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        offlineHandleEventDTO.setShopId(shopDetailVO.getShopId());
        ServerResponseEntity<OfflineHandleEventVO> processingEventByHandleTypeAndHandleId = offlineHandleEventFeignClient.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.SHOP.getValue(), shopDetailVO.getShopId(), sysType);
        if (processingEventByHandleTypeAndHandleId.isSuccess() && Objects.nonNull(processingEventByHandleTypeAndHandleId.getData())) {
            offlineHandleEventFeignClient.update(offlineHandleEventDTO);
        } else {
            offlineHandleEventFeignClient.save(offlineHandleEventDTO);
        }
        // 更新店铺状态为下线
        shopDetailMapper.changeShopStatus(shopDetailVO.getShopId(), ShopStatus.OFFLINE.value());

        // 将店铺所有商品下线
        ServerResponseEntity<Void> spuResponseEntity = spuFeignClient.offlineSpuByShopId(shopDetailVO.getShopId());
        if (!spuResponseEntity.isSuccess()) {
            throw new LuckException(spuResponseEntity.getMsg());
        }

        // 失效秒杀活动
        ServerResponseEntity<Void> seckillResponseEntity = seckillFeignClient.offlineSeckillByShopId(shopDetailVO.getShopId());
        if (!seckillResponseEntity.isSuccess()) {
            throw new LuckException(seckillResponseEntity.getMsg());
        }

        // 下线满减优惠券直播活动
        offlineShopActivity(Collections.singletonList(shopDetailVO.getShopId()), ShopStatus.STOP.value());

        //解绑平台轮播图商品
        offlineIndexImg(shopDetailVO.getShopId());

        // 失效弹窗
        ServerResponseEntity<Void> response = popupFeignClient.offlineShop(shopDetailVO.getShopId());
        if (!response.isSuccess()) {
            throw new LuckException(response.getMsg());
        }
    }

    private void offlineIndexImg(Long shopId) {
        ServerResponseEntity<List<Long>> spuIdsEntity = spuFeignClient.listSpuIdsByShopId(shopId);
        if (!spuIdsEntity.isSuccess()) {
            throw new LuckException(spuIdsEntity.getMsg());
        }
        List<Long> spuIds = spuIdsEntity.getData();
        if (CollUtil.isNotEmpty(spuIds)) {
            indexImgService.offlineSpuBySpuIds(Constant.PLATFORM_SHOP_ID, spuIds);
        }
    }

    @Override
    public Long countByShopStatus(Integer shopStatus) {
        return shopDetailMapper.countByShopStatus(shopStatus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void platformCreateShop(ShopCreateInfoDTO shopCreateInfoDTO) {
        boolean isAllinpay = shopAllinpayService.getIsAllinpay();
        // 1、校验验证码信息
        ShopUserRegisterDTO shopUserRegisterInfo = shopCreateInfoDTO.getShopUserRegisterInfo();
        ServerResponseEntity<Boolean> sendNotifyResponse = notifyFeignClient.checkValidCode(shopUserRegisterInfo.getMobile(), shopUserRegisterInfo.getValidCode(), SendTypeEnum.VALID);
        Boolean data = sendNotifyResponse.getData();
        //TODO 去掉验证码校验
//        if (Objects.equals(sendNotifyResponse.getCode(), ResponseEnum.OK.value()) && Objects.nonNull(data) && !data) {
//            throw new LuckException("验证码有误或已过期!");
//        }
        // 2、保存店铺基本信息
        Date now = new Date();
        ShopDetailDTO shopDetailDTO = shopCreateInfoDTO.getShopDetail();
        this.checkShopInfo(shopDetailDTO, true);
        ShopDetail shopDetail = saveAndGetShopDetail(now, shopDetailDTO, isAllinpay);
        // 通联创建企业会员
        shopAllinpayService.createAllinpayCompanyMember(shopDetail.getShopId());
        Long shopId = shopDetail.getShopId();
        // 3、保存店铺账号信息
        ShopUser shopUser = new ShopUser();
        shopUser.setNickName(shopUserRegisterInfo.getUsername());
        shopUser.setPhoneNum(shopUserRegisterInfo.getMobile());
        shopUser.setHasAccount(1);
        shopUser.setShopId(shopId);
        shopUserService.save(shopUser, null);
        // 4、初始化店铺数据
        addShopInfo(shopId);
        // 5、初始化店铺审核信息，平台端创建店铺默认为审核成功
        ShopAuditing shopAuditing = new ShopAuditing();
        shopAuditing.setShopId(shopId);
        shopAuditing.setUserId(shopUser.getShopUserId());
        shopAuditing.setAuditorId(AuthUserContext.get().getUserId());
        shopAuditing.setStatus(isAllinpay ? AuditStatus.WAITAUDIT.value() : AuditStatus.SUCCESSAUDIT.value());
        shopAuditingService.save(shopAuditing);
        // 6、保存店铺工商信息
        ShopCompanyDTO shopCompanyDTO = shopCreateInfoDTO.getShopCompany();
        shopCompanyDTO.setShopId(shopDetail.getShopId());
        ShopCompany shopCompany = BeanUtil.map(shopCompanyDTO, ShopCompany.class);
        shopCompany.setStatus(isAllinpay ? AuditStatus.WAITAUDIT.value() : AuditStatus.SUCCESSAUDIT.value());
        shopCompanyService.save(shopCompany, true);

        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setPhone(shopUserRegisterInfo.getMobile());
        authAccountDTO.setPassword(shopUserRegisterInfo.getPassword());
        authAccountDTO.setStatus(StatusEnum.ENABLE.value());
        authAccountDTO.setCreateIp(IpHelper.getIpAddr());
        authAccountDTO.setSysType(SysTypeEnum.MULTISHOP.value());
        authAccountDTO.setIsAdmin(UserAdminType.ADMIN.value());
        authAccountDTO.setTenantId(shopId);
        authAccountDTO.setIsPassShop(isAllinpay ? IsPassShopEnum.NO.value() : IsPassShopEnum.YES.value());
        authAccountDTO.setUsername(shopUserRegisterInfo.getUsername());
        authAccountDTO.setUserId(shopUser.getShopUserId());
        ServerResponseEntity<Long> save = accountFeignClient.save(authAccountDTO);
        if (!Objects.equals(save.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(save.getMsg());
        }
        // 8、保存分类签约信息
        ServerResponseEntity<Void> categoryRes = categoryShopFeignClient.insertBatchByShopId(shopCreateInfoDTO.getCategorySigningList(), shopId, SysTypeEnum.MULTISHOP.value());
        if (!categoryRes.isSuccess()) {
            throw new LuckException(categoryRes.getMsg());
        }
        // 9、保存品牌签约信息
        ServerResponseEntity<Void> brandRes = brandShopFeignClient.insertBatchByShopId(shopCreateInfoDTO.getBrandSigningList(), shopId, SysTypeEnum.MULTISHOP.value());
        if (!brandRes.isSuccess()) {
            throw new LuckException(brandRes.getMsg());
        }

        // 保存店铺代销设置默认值
        ShopSubstituteSales shopSubstituteSales = new ShopSubstituteSales();
        shopSubstituteSales.setShopId(shopDetail.getShopId());
        shopSubstituteSales.setSalesType(SalesType.MANUAL_OPERATION_PRICE.value());
        shopSubstituteSales.setOrderShape(0);
        shopSubstituteSalesService.save(shopSubstituteSales);
        // 7、保存店铺银行卡信息
        saveShopBankCard(shopCreateInfoDTO, shopId, shopCompany);

        // 10、保存仓库信息
        ServerResponseEntity<Void> warehouseRes =  warehouseFeignClient.createWarehouseByShopId(shopId, SysTypeEnum.MULTISHOP.value(), shopDetailDTO.getContactPhone(), shopDetailDTO.getContactName());
        if (!warehouseRes.isSuccess()) {
            throw new LuckException(warehouseRes.getMsg());
        }
    }

    private ShopDetail saveAndGetShopDetail(Date now, ShopDetailDTO shopDetailDTO, boolean isAllinpay) {
        ShopDetail shopDetail = BeanUtil.map(shopDetailDTO, ShopDetail.class);
        if (!isAllinpay) {
            if (Objects.isNull(shopDetail.getContractStartTime())) {
                throw new LuckException("店铺签约时间不能为空");
            }
            handleContract(shopDetail, shopDetail.getContractStartTime(), shopDetail.getContractEndTime(), now);
        } else {
            shopDetail.setShopStatus(ShopStatus.OPEN.value());
            shopDetail.setType(ShopType.SELF_SHOP.value());
        }
        shopDetail.setIsPreferred(IsPassShopEnum.NO.value());
        shopDetailMapper.save(shopDetail);
        return shopDetail;
    }

    private void saveShopBankCard(ShopCreateInfoDTO shopCreateInfoDTO, Long shopId, ShopCompany shopCompany) {
        if (shopAllinpayService.getIsAllinpay()) {
            AllinpayShopBankCardDTO allinpayShopBankCardDTO = shopCreateInfoDTO.getAllinpayShopBankCardDTO();
            if (Objects.isNull(allinpayShopBankCardDTO)) {
                throw new LuckException("至少绑定一个对公户账户");
            }
            // 设置企业信息
            shopBankCardService.insertAndSetCompanyInfo(allinpayShopBankCardDTO, shopId, BeanUtil.map(shopCompany, ShopCompanyVO.class));
        } else {
            shopBankCardService.insertBatch(shopCreateInfoDTO.getShopBankCardList(), shopId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void changeShopStatusByContractTime(Date now) {
        // 获取状态需要改变为停业状态的店铺id列表
        List<Long> shopIdsToStop = shopDetailMapper.listShopIdsOfStatusChangeToStopByContractTime(now);
        // 获取状态需要改变为营业状态的店铺id列表
        List<Long> shopIdsToOpen = shopDetailMapper.listShopIdsOfStatusChangeToOpenByContractTime(now);
        if (CollUtil.isEmpty(shopIdsToStop) && CollUtil.isEmpty(shopIdsToOpen)) {
            // 没有店铺状态需要改变
            return;
        }
        // 根据签约时间修改店铺状态
        shopDetailMapper.changeShopStatusByContractTime(now);
        if (CollUtil.isNotEmpty(shopIdsToStop)) {
            // 失效商品活动信息，不需要下架商品
            spuFeignClient.offlineSpuActivityByShopIds(shopIdsToStop);
            // 下架店铺商品
            spuFeignClient.offlineSpuByShopIds(shopIdsToStop);
        }
        // 修改购物车项中店铺是否停业属性
        ServerResponseEntity<Void> shopCartToStopRes = shopCartFeignClient.updateIsClosedByShopIds(shopIdsToStop, 0);
        if (!shopCartToStopRes.isSuccess()) {
            throw new LuckException(shopCartToStopRes.getMsg());
        }
        ServerResponseEntity<Void> shopCartToOpenRes = shopCartFeignClient.updateIsClosedByShopIds(shopIdsToOpen, 1);
        if (!shopCartToOpenRes.isSuccess()) {
            throw new LuckException(shopCartToOpenRes.getMsg());
        }
        // 下线优惠券满减活动
        offlineShopActivity(shopIdsToStop, ShopStatus.STOP.value());
        if (CollUtil.isNotEmpty(shopIdsToStop)) {
            ServerResponseEntity<Void> response = popupFeignClient.deleteShopLinkBatch(shopIdsToOpen);
            if (!response.isSuccess()) {
                throw new LuckException(response.getMsg());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopSigningInfoDTO.shopId")
    public void updateSigningInfo(ShopSigningInfoDTO shopSigningInfoDTO) {
        ShopDetailVO oldShopDetail = shopDetailMapper.getByShopId(shopSigningInfoDTO.getShopId());
        ShopDetail newShopDetail = BeanUtil.map(oldShopDetail, ShopDetail.class);
        // 赋值
        newShopDetail.setType(shopSigningInfoDTO.getType());
        newShopDetail.setContractStartTime(DateUtil.beginOfDay(shopSigningInfoDTO.getContractStartTime()));
        newShopDetail.setContractEndTime(Objects.isNull(shopSigningInfoDTO.getContractEndTime()) ? null : getSaveEndOfDay(shopSigningInfoDTO.getContractEndTime()));
        // 当店铺状态处于营业中或者停业中时，店铺状态会受签约时间改变
        if (Objects.equals(newShopDetail.getShopStatus(), ShopStatus.OPEN.value()) || Objects.equals(newShopDetail.getShopStatus(), ShopStatus.STOP.value())) {
            Date now = new Date();
            // 记录店铺状态是否发生改变
            boolean isChangeStatus = false;
            boolean isContain = now.compareTo(newShopDetail.getContractStartTime()) >= 0 && (Objects.isNull(newShopDetail.getContractEndTime()) || now.compareTo(newShopDetail.getContractEndTime()) < 0);
            if (isContain || shopAllinpayService.getIsAllinpay()) {
                // 如果店铺的签约时间包含当前时间，则把店铺状态置为营业中
                isChangeStatus = Objects.equals(oldShopDetail.getShopStatus(), ShopStatus.STOP.value());
                newShopDetail.setShopStatus(ShopStatus.OPEN.value());
                shopDetailMapper.update(newShopDetail);
            } else if (now.compareTo(newShopDetail.getContractStartTime()) < 0 || now.compareTo(newShopDetail.getContractEndTime()) >= 0) {
                // 如果店铺的签约时间不包含当前时间，则把店铺状态置为停业中
                isChangeStatus = Objects.equals(oldShopDetail.getShopStatus(), ShopStatus.OPEN.value());
                newShopDetail.setShopStatus(ShopStatus.STOP.value());
                shopDetailMapper.update(newShopDetail);
            }
            ServerResponseEntity<Void> spuRes = spuFeignClient.updateSpuUpdateTimeByShopIds(Collections.singletonList(shopSigningInfoDTO.getShopId()), SysTypeEnum.MULTISHOP.value());
            if (!spuRes.isSuccess()) {
                throw new LuckException(spuRes.getMsg());
            }
            // 如果店铺状态发生变化
            if (isChangeStatus) {
                // 更新购物车项店铺是否停业状态
                ServerResponseEntity<Void> shopCartRes = shopCartFeignClient.updateIsClosedByShopIds(Collections.singletonList(newShopDetail.getShopId()), Objects.equals(newShopDetail.getShopStatus(), ShopStatus.STOP.value()) ? 0 : 1);
                if (!shopCartRes.isSuccess()) {
                    throw new LuckException(shopCartRes.getMsg());
                }
                if (Objects.equals(oldShopDetail.getShopStatus(), ShopStatus.OPEN.value())) {
                    // 店铺营业状态变为停业，需要下架商品活动
                    ServerResponseEntity<Void> offlineSpuActivityResp = spuFeignClient.offlineSpuActivityByShopIds(Collections.singletonList(newShopDetail.getShopId()));
                    if (!offlineSpuActivityResp.isSuccess()) {
                        log.info("店铺营业状态变为停业，下架商品活动失败，店铺id：{}", newShopDetail.getShopId());
                        throw new LuckException(offlineSpuActivityResp.getMsg());
                    }
                    // 下架店铺商品
                    ServerResponseEntity<Void> offlineSpuResp = spuFeignClient.offlineSpuByShopIds(Collections.singletonList(newShopDetail.getShopId()));
                    if (!offlineSpuResp.isSuccess()) {
                        log.info("店铺营业状态变为停业，下架店铺商品失败，店铺id：{}", newShopDetail.getShopId());
                        throw new LuckException(offlineSpuResp.getMsg());
                    }
                    // 下线满减和优惠券活动
                    offlineShopActivity(Collections.singletonList(newShopDetail.getShopId()), ShopStatus.STOP.value());
                }
            }
        }
        // 店铺违规下线、违规提交审核时，修改签约时间和店铺类型，不修改状态
        else {
            shopDetailMapper.update(newShopDetail);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#offlineHandleEventDTO.handleId")
    public void auditApply(OfflineHandleEventDTO offlineHandleEventDTO) {
        ShopDetailVO shopDetailVO = getByShopId(offlineHandleEventDTO.getHandleId());
        if (Objects.isNull(shopDetailVO)) {
            throw new LuckException("店铺不存在");
        }
        if (!Objects.equals(shopDetailVO.getShopStatus(), ShopStatus.OFFLINE.value())) {
            throw new LuckException("店铺状态已发生变化，请刷新后重试");
        }
        // 更新事件状态
        ServerResponseEntity<Void> offlineRes = offlineHandleEventFeignClient.updateToApply(offlineHandleEventDTO);
        if (!offlineRes.isSuccess()) {
            throw new LuckException(offlineRes.getMsg());
        }
        // 更改店铺状态为上线申请待审核
        shopDetailMapper.changeShopStatus(offlineHandleEventDTO.getHandleId(), ShopStatus.OFFLINE_AWAIT_AUDIT.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#offlineHandleEventDTO.handleId")
    public void onlineAudit(OfflineHandleEventDTO offlineHandleEventDTO) {
        ShopDetailVO shopDetail = getByShopId(offlineHandleEventDTO.getHandleId());
        if (Objects.isNull(shopDetail)) {
            throw new LuckException("店铺不存在");
        }
        if (!Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AWAIT_AUDIT.value())) {
            throw new LuckException("店铺状态已发生变化，请刷新后重试");
        }
        // 审核
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.auditOfflineEvent(offlineHandleEventDTO);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        Long shopId = offlineHandleEventDTO.getHandleId();
        // 审核通过
        if (Objects.equals(offlineHandleEventDTO.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            Date now = new Date();
            auditSuccess(shopDetail, now, shopId);
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventDTO.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            shopDetailMapper.changeShopStatus(shopId, ShopStatus.OFFLINE.value());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#offlineHandleEventDTO.handleId")
    public void onlineOpenShop(OfflineHandleEventDTO offlineHandleEventDTO) {
        if (!shopAllinpayService.getIsAllinpay()) {
            throw new LuckException("开通通联支付后才可以直接上线商家");
        }
        ShopDetailService shopDetailService = (ShopDetailService) AopContext.currentProxy();
        ShopDetailVO shopDetail = shopDetailService.getByShopId(offlineHandleEventDTO.getHandleId());
        if (Objects.isNull(shopDetail)) {
            throw new LuckException("店铺不存在");
        }
        if (!Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AWAIT_AUDIT.value()) && !Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
            throw new LuckException("店铺状态已发生变化，请刷新后重试");
        }
        // 审核
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.auditOfflineEvent(offlineHandleEventDTO);
        if (!responseEntity.isSuccess()) {
            throw new LuckException(responseEntity.getMsg());
        }
        // 审核通过
        auditSuccess(shopDetail, new Date(), offlineHandleEventDTO.getHandleId());
    }

    private void auditSuccess(ShopDetailVO shopDetail, Date now, Long shopId) {
        if (shopAllinpayService.getIsAllinpay()) {
            // 把店铺状态置为营业中
            shopDetailMapper.changeShopStatus(shopId, ShopStatus.OPEN.value());
            // 更新购物车项店铺是否停业状态
            shopCartFeignClient.updateIsClosedByShopIds(Collections.singletonList(shopDetail.getShopId()), 1);
            spuFeignClient.updateSpuUpdateTimeByShopIds(Collections.singletonList(shopId), SysTypeEnum.MULTISHOP.value());
            return;
        }
        if (now.compareTo(shopDetail.getContractStartTime()) >= 0 && (Objects.isNull(shopDetail.getContractEndTime()) || now.compareTo(shopDetail.getContractEndTime()) < 0)) {
            // 如果店铺的签约时间包含当前时间，则把店铺状态置为营业中
            shopDetailMapper.changeShopStatus(shopId, ShopStatus.OPEN.value());
            // 更新购物车项店铺是否停业状态
            shopCartFeignClient.updateIsClosedByShopIds(Collections.singletonList(shopDetail.getShopId()), 1);
        } else {
            // 如果店铺的签约时间不包含当前时间，则把店铺状态置为停业中
            shopDetailMapper.changeShopStatus(shopId, ShopStatus.STOP.value());
            // 更新购物车项店铺是否停业状态
            shopCartFeignClient.updateIsClosedByShopIds(Collections.singletonList(shopDetail.getShopId()), 0);
        }
        spuFeignClient.updateSpuUpdateTimeByShopIds(Collections.singletonList(shopId), SysTypeEnum.MULTISHOP.value());
    }

    @Override
    public List<ShopSimpleBO> listSimple(ShopSimpleBO shopSimpleBO) {
        return shopDetailMapper.listSimple(shopSimpleBO);
    }

    @Override
    public Boolean checkShopName(String shopName) {
        return shopDetailMapper.countShopName(shopName, null) > 0;
    }

    @Override
    public List<Long> getShopIdByShopStatus(Integer shopStatus) {
        return shopDetailMapper.getShopIdsByShopStatus(shopStatus);
    }

    @Override
    public void offlineShopActivity(List<Long> shopIds, Integer shopStatus) {
        if (!Objects.equals(shopStatus, ShopStatus.STOP.value()) && Objects.equals(shopStatus, ShopStatus.OFFLINE.value())) {
            return;
        }
        //下线满减活动
        ServerResponseEntity<Void> handleDiscountOffline = discountFeignClient.handleShopOffline(shopIds);
        if (!handleDiscountOffline.isSuccess()) {
            throw new LuckException(handleDiscountOffline.getMsg());
        }
        //下线优惠券
        ServerResponseEntity<Void> handleCouponOffline = couponFeignClient.handleShopOffline(shopIds);
        if (!handleCouponOffline.isSuccess()) {
            throw new LuckException(handleCouponOffline.getMsg());
        }
        //下线直播间
        ServerResponseEntity<Void> liveResponse = liveFeignClient.endLiveRoom(shopIds);
        if (!liveResponse.isSuccess()) {
            throw new LuckException(liveResponse.getMsg());
        }
    }

    @Override
    public List<Long> getShopIdsLikeName(String name) {
        return shopDetailMapper.selectShopIdsLikeName(name);
    }

    @Override
    public PageVO<ShopHeadInfoVO> renovationShopPage(PageDTO pageDTO, ShopSearchDTO shopSearchDTO, Integer sysType) {
        shopSearchDTO.setPaySysType(shopAllinpayService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value());
        if (Objects.equals(sysType, SysTypeEnum.ORDINARY.value())) {
            PageUtil.doPage(pageDTO, () -> shopDetailMapper.apiSearchShops(shopSearchDTO));
        }
        return PageUtil.doPage(pageDTO, () -> shopDetailMapper.searchShops(shopSearchDTO));
    }

    @Override
    public List<ShopHeadInfoVO> listRenovationShop(ShopSearchDTO shopSearchDTO) {
        if (CollUtil.isEmpty(shopSearchDTO.getShopIds())) {
            return new ArrayList<>(0);
        }
        return shopDetailMapper.listRenovationShop(shopSearchDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createAllinpayMember() {
        // 获取还没创建通联会员的商家id列表
        List<Long> shopIds = shopDetailMapper.listUnCreateMemberShopIds();
        if (CollUtil.isEmpty(shopIds)) {
            return;
        }

        shopDetailMapper.updateShopIsCreate(shopIds);
        // 已经开店的
        // 更新商家信息并且将对应商家的通联商家改完平台下线，等绑定了手机，设置了企业信息，影印件审核通过后，通联审核通过即可恢复原状态
        shopDetailMapper.updateShopToStop(shopIds);

        // 提交开店申请的
        // 找出已经提交申请的商家的审核信息给予驳回，然后更改状态为申请中
        shopDetailMapper.updateShopToApplying(shopIds);
        shopAuditingService.updateToFail(shopIds);

        // 修改工商信息的
        // 给予驳回，更改最后成功的工商信息为待审核
        List<ShopCompanyAuditingVO> needAuditList = companyAuditingMapper.getNeedAuditList();
        if (CollUtil.isNotEmpty(needAuditList)) {
            for (ShopCompanyAuditingVO companyAuditing : needAuditList) {
                companyAuditing.setStatus(AuditStatus.FAILAUDIT.value());
                companyAuditing.setRemarks("通联信息待完善");
                companyAuditingMapper.update(BeanUtil.map(companyAuditing, ShopCompanyAuditing.class));
                // 把对应的工商信息设置为审核未通过状态
                ShopCompany shopCompany = new ShopCompany();
                shopCompany.setShopCompanyId(companyAuditing.getShopCompanyId());
                shopCompany.setStatus(AuditStatus.FAILAUDIT.value());
                shopCompanyService.updateById(shopCompany);
            }
        }
        shopCompanyService.updateStatusToWaitAudit();

        // 给所有商家都新增一个通联的钱包
        List<String> keys = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (Long shopId : shopIds) {
            saveShopWallet(shopId, true);
            // 删除商家的银行卡，需要重新绑定
            shopBankCardService.deleteByShopId(shopId);
            keys.add(CacheNames.SHOP_DETAIL_ID_KEY + CacheNames.UNION + shopId);

            // 将该店铺所有的商品下线
            ServerResponseEntity<Void> spuResponse = spuFeignClient.offlineSpuByShopId(shopId);
            if (!Objects.equals(spuResponse.getCode(), ResponseEnum.OK.value())) {
                throw new LuckException(spuResponse.getMsg());
            }
        }
        RedisUtil.del(keys);

        List<String> bizUserIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (Long shopId : shopIds) {
            bizUserIds.add(AllinpayConstant.SHOP + shopId);
        }
        // 批量创建会员
        ServerResponseEntity<Void> response = allinpayFeignClient.batchCreateMember(bizUserIds);
        if (!response.isSuccess()) {
            throw new LuckException(response.getMsg());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createAllinpayMemberByShopId(Long shopId) {
        // 该方法通联独有,可能平台开启通联支付的时候参数没配好，所以导致商家没能创建成功会员，那么在商家端登录的时候就要给商家无感创建一个
        if (!shopAllinpayService.getIsAllinpay()) {
            return;
        }
        // 确保商家还没有创建
        ShopDetailVO shopDetail = shopDetailMapper.getShopByShopId(shopId);
        if (Objects.equals(shopDetail.getIsCreateMember(), 1)) {
            return;
        }
        shopDetailMapper.updateShopIsCreate(Collections.singletonList(shopId));
        Integer shopStatus = shopDetail.getShopStatus();
        if (Objects.equals(shopStatus, ShopStatus.OPEN.value())
                || Objects.equals(shopStatus, ShopStatus.STOP.value())
                || Objects.equals(shopStatus, ShopStatus.OFFLINE.value())
                || Objects.equals(shopStatus, ShopStatus.OFFLINE_AWAIT_AUDIT.value())) {
            // 已经开店的
            // 更新商家信息并且将对应商家的通联商家改完平台下线，等绑定了手机，设置了企业信息，影印件审核通过后，通联审核通过即可恢复原状态
            shopDetailMapper.updateShopToStop(Collections.singletonList(shopId));
        } else if (Objects.equals(shopStatus, ShopStatus.OPEN_AWAIT_AUDIT.value())) {
            // 提交开店申请的
            // 找出已经提交申请的商家的审核信息给予驳回，然后更改状态为申请中
            shopDetailMapper.updateShopToApplying(Collections.singletonList(shopId));
            shopAuditingService.updateToFail(Collections.singletonList(shopId));
        }
        ShopCompanyAuditingVO companyAuditingVO = companyAuditingMapper.getLatestAuditingByShopId(shopId);
        if (Objects.nonNull(companyAuditingVO)) {
            if (Objects.equals(companyAuditingVO.getStatus(), AuditStatus.WAITAUDIT.value())) {
                // 修改工商信息的
                // 给予驳回，更改最后成功的工商信息为待审核
                companyAuditingVO.setRemarks("通联信息待完善");
                companyAuditingVO.setStatus(AuditStatus.FAILAUDIT.value());
                companyAuditingMapper.update(BeanUtil.map(companyAuditingVO, ShopCompanyAuditing.class));
                // 把对应的工商信息设置为审核未通过状态
                ShopCompany shopCompany = new ShopCompany();
                shopCompany.setStatus(AuditStatus.FAILAUDIT.value());
                shopCompany.setShopCompanyId(companyAuditingVO.getShopCompanyId());
                shopCompanyService.updateById(shopCompany);
            }
        }
        // 修改商家成功的工商信息为待审核
        shopCompanyService.batchUpdateStatus(shopId, AuditStatus.WAITAUDIT.value(), AuditStatus.SUCCESSAUDIT.value());

        // 给商家新增一个通联的钱包
        saveShopWallet(shopId, true);
        // 删除商家的银行卡，需要重新绑定
        shopBankCardService.deleteByShopId(shopId);
        // 将该店铺所有的商品下线
        ServerResponseEntity<Void> spuResponse = spuFeignClient.offlineSpuByShopId(shopId);
        if (!Objects.equals(spuResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(spuResponse.getMsg());
        }
        // 创建会员
        ServerResponseEntity<Void> response = allinpayFeignClient.batchCreateMember(Collections.singletonList(AllinpayConstant.SHOP + shopId));
        if (!response.isSuccess()) {
            throw new LuckException(response.getMsg());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAllinpayIdCardStatus(String bizUserId, Integer status) {
        Long shopId = Long.valueOf(bizUserId.substring(AllinpayConstant.SHOP_LENGTH));
        log.info("店铺{}影印件更新，影印件状态为{}", shopId, Objects.requireNonNull(IdCardCollectProcessStatus.instance(status)).str());
        // 影印件回调只会在企业审核通过后，所以这里再次更新一下，可能之前设置企业信息回调失败了
        shopBankCardService.updateShopAllinpayStatusToSuccess(shopId);
        shopDetailMapper.updateAllinpayIdCardStatus(shopId, status);
        if (!Objects.equals(status, IdCardCollectProcessStatus.ALL.value())) {
            log.info("店铺{}影印件更新，影印件状态为{}，未全部通过审核", shopId, Objects.requireNonNull(IdCardCollectProcessStatus.instance(status)).str());
            return;
        }
        // 如果审核都通过，将对应店铺上线
        shopDetailMapper.updateShopToOpen(shopId);
        ShopAuditingVO shopAuditing = shopAuditingService.getByshopId(shopId);
        if (!Objects.equals(shopAuditing.getStatus(), AuditStatus.SUCCESSAUDIT.value())) {
            log.info("店铺{}影印件更新,全部通过审核,进行开店回调，自动审核店铺", shopId);
            // 审核还没成功代表这是开店的回调
            ShopAuditingDTO shopAuditingDTO = BeanUtil.map(shopAuditing, ShopAuditingDTO.class);
            shopAuditingDTO.setStatus(AuditStatus.SUCCESSAUDIT.value());
            // 自动审核店铺
            audit(shopAuditingDTO);
        } else {
            log.info("店铺{}影印件更新,全部通过审核,进行修改工商信息回调，自动审核工商信息", shopId);
            // 修改工商信息回调
            ShopCompanyAuditingVO companyAuditing = companyAuditingMapper.getLatestAuditingByShopId(shopId);
            if (Objects.isNull(companyAuditing)) {
                log.error("影印件回调，工商审核信息不存在{}", bizUserId);
                return;
            }
            if (Objects.equals(companyAuditing.getStatus(), AuditStatus.WAITAUDIT.value())) {
                log.info("店铺{}影印件更新,全部通过审核,进行修改工商信息回调，工商信息为待审核状态", shopId);
                companyAuditing.setStatus(AuditStatus.SUCCESSAUDIT.value());
                companyAuditingMapper.update(BeanUtil.map(companyAuditing, ShopCompanyAuditing.class));

                shopCompanyService.batchUpdateStatus(companyAuditing.getShopId(), AuditStatus.FAILAUDIT.value(), null);
                // 把对应的工商信息设置为启用状态
                ShopCompany shopCompany = new ShopCompany();
                shopCompany.setShopCompanyId(companyAuditing.getShopCompanyId());
                shopCompany.setStatus(AuditStatus.SUCCESSAUDIT.value());
                shopCompanyService.updateById(shopCompany);
            } else if (Objects.equals(companyAuditing.getStatus(), AuditStatus.FAILAUDIT.value())) {
                log.info("店铺{}影印件更新,全部通过审核,进行修改工商信息回调，工商信息为失败状态", shopId);
                // 审核不通过的工商信息删了
                shopCompanyService.deleteByShopIdAndStatus(shopId, AuditStatus.FAILAUDIT.value());
            }
        }
    }

    @Override
    public List<ShopDetailVO> listShopIds() {
        return shopDetailMapper.listShopIds();
    }

    /**
     * 添加店铺钱包
     * @param shopId
     * @return
     */
    public void addShopInfo(Long shopId) {
        ShopExtension shopExtension = new ShopExtension();
        shopExtension.setShopId(shopId);
        shopExtensionService.save(shopExtension);

        saveShopWallet(shopId, shopAllinpayService.getIsAllinpay());
    }

    private void saveShopWallet(Long shopId, boolean isAllinpay) {
        ShopWallet shopWallet = new ShopWallet();
        shopWallet.setVersion(0L);
        shopWallet.setUnsettledAmount(0L);
        shopWallet.setSettledAmount(0L);
        shopWallet.setFreezeAmount(0L);
        shopWallet.setTotalSettledAmount(0L);
        shopWallet.setSmsNum(0);
        shopWallet.setShopId(shopId);
        shopWallet.setPaySysType(isAllinpay ? 1 : 0);
        shopWalletMapper.save(shopWallet);
    }

    /**
     * 检验店铺信息是否正确
     * @param shopDetailDTO 店铺基本信息
     * @param isCreate true: 创建时校验， false: 更新时校验
     */
    private void checkShopInfo(ShopDetailDTO shopDetailDTO, Boolean isCreate) {
        if (!isCreate) {
            ShopAuditingVO shopAuditingVO = shopAuditingService.getByshopId(shopDetailDTO.getShopId());
            if (Objects.nonNull(shopAuditingVO) && Objects.equals(shopAuditingVO.getStatus(), AuditStatus.WAITAUDIT.value())) {
                throw new LuckException("店铺处于待审核状态无法修改信息");
            }
        }
        // 店铺名称
        if (StrUtil.isNotBlank(shopDetailDTO.getShopName())) {
            shopDetailDTO.setShopName(shopDetailDTO.getShopName().trim());
        }
        if (shopDetailMapper.countShopName(shopDetailDTO.getShopName(), shopDetailDTO.getShopId()) > 0) {
            throw new LuckException("店铺名称已存在");
        }
        if (!isCreate) {
            // 更新店铺基本信息不用校验用户信息
            return;
        }
        if (StrUtil.isNotBlank(shopDetailDTO.getContactPhone())) {
            shopDetailDTO.setPhone(shopDetailDTO.getContactPhone().trim());
        }
    }

    /**
     * 创建店铺初始账号
     * @param shopDetailDTO
     * @param statusEnum
     */
    public void createShopAccount(ShopDetailDTO shopDetailDTO, StatusEnum statusEnum) {
        ShopUser shopUser = new ShopUser();
        shopUser.setShopId(shopDetailDTO.getShopId());
        shopUser.setNickName(shopDetailDTO.getUsername());
        shopUser.setHasAccount(1);
        shopUserService.save(shopUser, null);

        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setPhone(shopDetailDTO.getPhone());
        authAccountDTO.setUsername(shopDetailDTO.getUsername());
        authAccountDTO.setPassword(shopDetailDTO.getPassword().trim());
        authAccountDTO.setStatus(statusEnum.value());
        authAccountDTO.setSysType(SysTypeEnum.MULTISHOP.value());
        authAccountDTO.setCreateIp(IpHelper.getIpAddr());
        authAccountDTO.setTenantId(shopDetailDTO.getShopId());
        authAccountDTO.setUserId(shopUser.getShopUserId());
        authAccountDTO.setIsAdmin(UserAdminType.ADMIN.value());
        ServerResponseEntity<Long> save = accountFeignClient.save(authAccountDTO);
        if (!Objects.equals(save.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(save.getMsg());
        }
    }

    private Date getSaveEndOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtil.endOfDay(date));
        // 防止时间进位
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
}
