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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
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.auth.vo.AuthAccountVO;
import com.tmerclub.cloud.api.biz.feign.AttachFileFeignClient;
import com.tmerclub.cloud.api.biz.feign.NotifyFeignClient;
import com.tmerclub.cloud.api.product.feign.WarehouseFeignClient;
import com.tmerclub.cloud.api.feign.SearchSpuFeignClient;
import com.tmerclub.cloud.api.multishop.constant.ShopStatus;
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.BrandFeignClient;
import com.tmerclub.cloud.api.product.feign.BrandShopFeignClient;
import com.tmerclub.cloud.api.product.feign.CategoryShopFeignClient;
import com.tmerclub.cloud.api.product.feign.SpuFeignClient;
import com.tmerclub.cloud.api.supplier.bo.SupplierDetailBO;
import com.tmerclub.cloud.api.supplier.bo.SupplierSimpleBO;
import com.tmerclub.cloud.api.supplier.constant.SupplierStatus;
import com.tmerclub.cloud.api.supplier.vo.SupplierApiDetailVO;
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.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.supplier.constant.AuditStatus;
import com.tmerclub.cloud.supplier.constant.SupplierType;
import com.tmerclub.cloud.supplier.dto.*;
import com.tmerclub.cloud.supplier.mapper.SupplierCompanyAuditingMapper;
import com.tmerclub.cloud.supplier.mapper.SupplierDetailMapper;
import com.tmerclub.cloud.supplier.mapper.SupplierUserMapper;
import com.tmerclub.cloud.supplier.mapper.SupplierWalletMapper;
import com.tmerclub.cloud.supplier.model.*;
import com.tmerclub.cloud.supplier.service.*;
import com.tmerclub.cloud.supplier.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 lhd
 */
@Service
public class SupplierDetailServiceImpl implements SupplierDetailService {

    private static final Logger log = LoggerFactory.getLogger(SupplierDetailServiceImpl.class);

    @Autowired
    private SupplierDetailMapper supplierDetailMapper;
    @DubboReference
    private CategoryShopFeignClient categoryShopFeignClient;
    @Autowired
    private SupplierCompanyService supplierCompanyService;
    @Autowired
    private SupplierAuditingService supplierAuditingService;
    @DubboReference
    private SearchSpuFeignClient searchSpuFeignClient;
    @Autowired
    private SupplierWalletMapper supplierWalletMapper;
    @Autowired
    private SupplierUserService supplierUserService;
    @Autowired
    private SupplierExtensionService supplierExtensionService;
    @DubboReference
    private AccountFeignClient accountFeignClient;
    @DubboReference
    private SpuFeignClient spuFeignClient;
    @Autowired
    private SupplierUserMapper supplierUserMapper;
    @DubboReference
    private BrandFeignClient brandFeignClient;
    @DubboReference
    private OfflineHandleEventFeignClient offlineHandleEventFeignClient;
    @DubboReference
    private NotifyFeignClient notifyFeignClient;
    @Autowired
    private SupplierBankCardService supplierBankCardService;
    @DubboReference
    private BrandShopFeignClient brandSupplierFeignClient;
    @DubboReference
    private AttachFileFeignClient attachFileFeignClient;
    @DubboReference
    private AllinpayFeignClient allinpayFeignClient;
    @Autowired
    private SupplierAllinpayService supplierAllinpayService;
    @Autowired
    private SupplierCompanyAuditingMapper supplierCompanyAuditingMapper;
    @DubboReference
    private WarehouseFeignClient warehouseFeignClient;

    @Override
    public PageVO<SupplierApiDetailVO> page(PageDTO pageDTO, SupplierDetailDTO supplierDetailDTO) {
        Integer paySysType = supplierAllinpayService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value();
        supplierDetailDTO.setPaySysType(paySysType);
        PageVO<SupplierApiDetailVO> page = PageUtil.doPage(pageDTO, () -> supplierDetailMapper.list(supplierDetailDTO));
        if (supplierAllinpayService.getIsAllinpay()) {
            for (SupplierApiDetailVO supplierApiDetailVO : page.getList()) {
                setAllinpaySupplierStatus(supplierApiDetailVO);
            }
        }
        return page;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierId")
    public SupplierApiDetailVO getBySupplierId(Long supplierId) {
        SupplierApiDetailVO supplierApiDetailVO = supplierDetailMapper.getBySupplierId(supplierId);
        ServerResponseEntity<AuthAccountVO> responseEntity = accountFeignClient.getAccountInfoByTenantId(supplierId, SysTypeEnum.SUPPLIER.value());
        if (responseEntity.isSuccess() && Objects.nonNull(responseEntity.getData())) {
            AuthAccountVO authAccountVO = responseEntity.getData();
            supplierApiDetailVO.setAccountStatus(authAccountVO.getStatus());
        }
        if (supplierAllinpayService.getIsAllinpay()) {
            setAllinpaySupplierStatus(supplierApiDetailVO);
        }
        return supplierApiDetailVO;
    }

    private static void setAllinpaySupplierStatus(SupplierApiDetailVO supplierApiDetailVO) {
        if (Objects.isNull(supplierApiDetailVO)) {
            return;
        }
        if (Objects.equals(supplierApiDetailVO.getAllinpaySupplierStatus(), AllinpayShopStatus.WAIT_AUDIT.value())) {
            supplierApiDetailVO.setSupplierStatus(ShopStatus.OFFLINE_AWAIT_AUDIT.value());
        }
        if (Objects.equals(supplierApiDetailVO.getAllinpaySupplierStatus(), AllinpayShopStatus.OPEN_WAIT_AUDIT.value())) {
            supplierApiDetailVO.setSupplierStatus(ShopStatus.OPEN_AWAIT_AUDIT.value());
        }
        if (Objects.equals(supplierApiDetailVO.getAllinpaySupplierStatus(), AllinpayShopStatus.OFFLINE.value()) ||
                Objects.equals(supplierApiDetailVO.getAllinpaySupplierStatus(), AllinpayShopStatus.UN_AVAILABLE.value())) {
            supplierApiDetailVO.setSupplierStatus(ShopStatus.OFFLINE.value());
        }
        if (Objects.equals(supplierApiDetailVO.getCompanyInfoProcessStatus(), CompanyInfoProcessStatus.FAIL.value())
                && Objects.equals(supplierApiDetailVO.getAllinpaySupplierStatus(), AllinpayShopStatus.OFFLINE.value())) {
            supplierApiDetailVO.setSupplierStatus(ShopStatus.AUDIT_FAIL.value());
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierDetailDTO.supplierId")
    public void update(SupplierDetailDTO supplierDetailDTO) {
        SupplierDetail supplierDetail = BeanUtil.map(supplierDetailDTO, SupplierDetail.class);
        // 给还没创建通联会员的供应商创建
        SupplierApiDetailVO dbSupplierDetail = supplierDetailMapper.getBySupplierId(supplierDetailDTO.getSupplierId());
        if (!PrincipalUtil.isDbPhone(supplierDetail.getContactPhone(), dbSupplierDetail.getContactPhone(), false)) {
            throw new LuckException("请输入正确的手机号");
        }
        if (supplierDetail.getContactPhone().contains(Constant.ASTERISK)) {
            supplierDetail.setContactPhone(dbSupplierDetail.getContactPhone());
        }
        if (supplierAllinpayService.getIsAllinpay() && Objects.equals(dbSupplierDetail.getIsCreateMember(), 0)) {
            createAllinpayMemberBySupplierId(supplierDetail.getSupplierId());
        }
        this.checkSupplierInfo(supplierDetailDTO, false);
        // 更新商品
        spuFeignClient.updateSpuByShopId(supplierDetail.getSupplierId(), SysTypeEnum.SUPPLIER.value());
        supplierDetailMapper.update(supplierDetail);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierId")
    public void deleteById(Long supplierId) {
        supplierDetailMapper.deleteById(supplierId);
    }

    @Override
    public List<SupplierDetail> listBySupplierIds(List<Long> supplierIds) {
        if (CollUtil.isEmpty(supplierIds)) {
            return new ArrayList<>(0);
        }
        return supplierDetailMapper.listBySupplierIds(supplierIds);
    }

    @Override
    public PageVO<SupplierDetailAppVO> supplierSearchPage(PageDTO pageDTO, SupplierDetailDTO supplierDetailDTO) {
        supplierDetailDTO.setPaySysType(supplierAllinpayService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value());
        PageVO<SupplierDetailAppVO> page = PageUtil.doPage(pageDTO, () -> supplierDetailMapper.supplierSearchList(supplierDetailDTO));
        Set<Long> spuIdSet = page.getList().stream().map(SupplierDetailAppVO::getSupplierId).collect(Collectors.toSet());
        if (Objects.isNull(supplierDetailDTO.getSpuNum()) || supplierDetailDTO.getSpuNum() <= 0) {
            return page;
        }
        ProductSearchLimitDTO productSearchLimitDTO = new ProductSearchLimitDTO(supplierDetailDTO.getSpuNum());
        productSearchLimitDTO.setSupplierIds(new ArrayList<>(spuIdSet));
        ServerResponseEntity<List<SpuSearchVO>> spuResponse = searchSpuFeignClient.limitSpuList(productSearchLimitDTO);
        if (!Objects.equals(spuResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(spuResponse.getMsg());
        } else if (CollectionUtil.isEmpty(spuResponse.getData())) {
            return page;
        }
        List<SpuSearchVO> data = spuResponse.getData();
        Map<Long, List<SpuSearchVO>> supplierMap = data.stream().collect(Collectors.groupingBy(SpuSearchVO::getSupplierId));
        for (SupplierDetailAppVO supplierDetail : page.getList()) {
            List<SpuSearchVO> spuSearchVOList = supplierMap.get(supplierDetail.getSupplierId());
            if (CollUtil.isEmpty(spuSearchVOList)) {
                spuSearchVOList = new ArrayList<>(0);
            }
            supplierDetail.setSpuList(spuSearchVOList);
        }
        return page;
    }

    @Override
    public SupplierApiDetailVO getSupplierBySupplierId(Long supplierId) {
        return supplierDetailMapper.getSupplierBySupplierId(supplierId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void applySupplier(SupplierDetailDTO supplierDetailDTO) {
        checkSupplierInfo(supplierDetailDTO, true);
        SupplierDetail newSupplierDetail = BeanUtil.map(supplierDetailDTO, SupplierDetail.class);
        // 申请开店
        newSupplierDetail.setSupplierStatus(SupplierStatus.APPLYING.value());
        newSupplierDetail.setType(SupplierType.STOP.value());
        supplierDetailMapper.save(newSupplierDetail);
        supplierDetailDTO.setSupplierId(newSupplierDetail.getSupplierId());

        // 插入一条审核记录
        SupplierAuditing auditing = new SupplierAuditing();
        auditing.setSupplierId(newSupplierDetail.getSupplierId());
        auditing.setCreateTime(new Date());
        auditing.setStatus(AuditStatus.WAITAUDIT.value());
        auditing.setUpdateTime(new Date());
        auditing.setRemarks(supplierDetailDTO.getRemarks());
        supplierAuditingService.save(auditing);
        // 创建账号
        createSupplierAccount(supplierDetailDTO, StatusEnum.DELETE);
    }

    /**
     * 审核供应商信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void audit(SupplierAuditingDTO supplierAuditingDTO) {
        Date now = new Date();
        SupplierAuditingVO dbSupplierAyditing = supplierAuditingService.getBySupplierId(supplierAuditingDTO.getSupplierId());
        if (Objects.isNull(dbSupplierAyditing)) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }
        supplierAuditingDTO.setSupplierAuditingId(dbSupplierAyditing.getSupplierAuditingId());
        // 非待审核的供应商，不能再进行审核
        if (!Objects.equals(dbSupplierAyditing.getStatus(), AuditStatus.WAITAUDIT.value())) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }

        // 修改供应商状态
        SupplierApiDetailVO supplierApiDetailVO = getBySupplierId(supplierAuditingDTO.getSupplierId());
        if (supplierApiDetailVO == null) {
            // 供应商信息不存在
            throw new LuckException("供应商信息不存在");
        }
        // 查询供应商账号信息（审核期间供应商有且仅有一个账号）
        SupplierUserDTO supplierUserDTO = new SupplierUserDTO();
        supplierUserDTO.setSupplierId(supplierApiDetailVO.getSupplierId());
        List<SupplierUserVO> supplierUserVOList = supplierUserService.listBySupplierId(supplierUserDTO);
        if (CollectionUtils.isEmpty(supplierUserVOList)) {
            throw new LuckException("供应商账号不存在");
        }
        SupplierUserVO supplierUserVO = supplierUserVOList.get(0);
        // 修改供应商账号缓存信息
        SupplierDetail supplierDetail = BeanUtil.map(supplierApiDetailVO, SupplierDetail.class);
        UidInfoBO uidInfoBO = new UidInfoBO();
        uidInfoBO.setUserId(supplierUserVO.getSupplierUserId());
        uidInfoBO.setUsername(supplierUserVO.getNickName());
        uidInfoBO.setSysType(SysTypeEnum.SUPPLIER.value());
        uidInfoBO.setTenantId(supplierAuditingDTO.getSupplierId());
        uidInfoBO.setIsAdmin(UserAdminType.ADMIN.value());
        // 审核不通过
        if (Objects.equals(supplierAuditingDTO.getStatus(), AuditStatus.FAILAUDIT.value())) {
            if (!supplierAllinpayService.getIsAllinpay() || !Objects.equals(supplierApiDetailVO.getType(), SupplierType.SELF_SHOP.value())) {
                supplierDetail.setSupplierStatus(SupplierStatus.APPLYING.value());
            }
        }
        // 审核通过
        else {
            supplierDetail.setType(supplierAuditingDTO.getSupplierType());
            if (supplierAllinpayService.getIsAllinpay()) {
                supplierDetail.setSupplierStatus(SupplierStatus.OPEN.value());
            } else {
                handleContract(supplierDetail, supplierAuditingDTO.getContractStartTime(), supplierAuditingDTO.getContractEndTime(), now);
            }
            supplierDetail.setIsPreferred(IsPassShopEnum.NO.value());
            updateSupplierCompanyStatus(supplierDetail.getSupplierId(), AuditStatus.SUCCESSAUDIT.value());
            if (!supplierAllinpayService.getIsAllinpay()) {
                uidInfoBO.setIsPassShop(IsPassShopEnum.NO.value());
                String uid = AuthUserContext.getUid(uidInfoBO);
                uidInfoBO.setIsPassShop(IsPassShopEnum.YES.value());
                uidInfoBO.setSysType(SysTypeEnum.SUPPLIER.value());
                ServerResponseEntity<Void> updateTenantIdRes = accountFeignClient.updateNoAuditUidInfo(uidInfoBO);
                if (!updateTenantIdRes.isSuccess()) {
                    throw new LuckException("审核失败");
                }
            }
            // 把商家自定义品牌添加为平台品牌
            brandFeignClient.updateCustomBrandToPlatformBrandByShopId(supplierAuditingDTO.getSupplierId(), SysTypeEnum.SUPPLIER.value());
            // 新店初始化事件 (分销设置（暂无）), 分销设置是平台统一设置，供应商暂无分销设置
            // 创建默认仓库
            warehouseFeignClient.createWarehouseByShopId(supplierAuditingDTO.getSupplierId(), SysTypeEnum.SUPPLIER.value(), supplierDetail.getContactPhone(), supplierDetail.getContactName());
        }
        supplierAuditingDTO.setAuditorId(Objects.isNull(AuthUserContext.get()) ? null : AuthUserContext.get().getUserId());
        supplierAuditingService.update(BeanUtil.map(supplierAuditingDTO, SupplierAuditing.class));
        supplierDetailMapper.update(supplierDetail);
    }

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

    /**
     *  更新供应商工商信息审核状态
     * @param supplierId
     * @param status
     */
    private void updateSupplierCompanyStatus(Long supplierId, Integer status) {

        SupplierCompanyVO supplierCompanyWaitAudit = supplierCompanyService.getSupplierCompanyBySupplierIdAndStatus(supplierId, AuditStatus.WAITAUDIT.value());
        if (Objects.isNull(supplierCompanyWaitAudit)) {
            throw new LuckException("缺少供应商工商资料");
        }
        SupplierCompany supplierCompany = BeanUtil.map(supplierCompanyWaitAudit, SupplierCompany.class);
        supplierCompany.setStatus(status);
        supplierCompanyService.updateBySupplierId(supplierCompany, supplierId, 0);
    }

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

    @Override
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierId")
    public void removeCacheBySupplierId(Long supplierId) {
    }

    @Override
    public SupplierDetailBO supplierExtensionData(Long supplierId) {
        return supplierDetailMapper.supplierExtensionData(supplierId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void createSupplier(SupplierDetailDTO supplierDetailDTO) {
        checkSupplierInfo(supplierDetailDTO, true);
        SupplierDetail supplierDetail = BeanUtil.map(supplierDetailDTO, SupplierDetail.class);
        // 赋默认值
        supplierDetail.setType(SupplierType.STOP.value());
        supplierDetail.setSupplierStatus(SupplierStatus.APPLYING.value());
        supplierDetailMapper.save(supplierDetail);
        // 通联创建企业会员
        supplierAllinpayService.createAllinpayCompanyMember(supplierDetail.getSupplierId());
        // 创建供应商数据
        addSupplierInfo(supplierDetail.getSupplierId());

        Long supplierUserId = AuthUserContext.get().getUserId();
        // 更新文件记录表中supplierId
        ServerResponseEntity<Void> attachRes = attachFileFeignClient.updateShopIdByUid(supplierDetail.getSupplierId());
        if (!attachRes.isSuccess()) {
            throw new LuckException(attachRes.getMsg());
        }
        // 保存supplierId到供应商用户表
        if (supplierUserMapper.updateSupplierIdBySupplierUserId(supplierDetail.getSupplierId(), supplierUserId) != 1) {
            throw new LuckException("保存供应商信息错误");
        }
        // 保存supplierId到账号表
        UidInfoBO userInfoInTokenBO = AuthUserContext.get();
        userInfoInTokenBO.setTenantId(supplierDetail.getSupplierId());
        userInfoInTokenBO.setUserId(supplierUserId);
        userInfoInTokenBO.setSysType(SysTypeEnum.SUPPLIER.value());
        ServerResponseEntity<Void> updateTenantIdRes = accountFeignClient.updateNoAuditUidInfo(userInfoInTokenBO);
        if (!updateTenantIdRes.isSuccess()) {
            throw new LuckException(updateTenantIdRes.getMsg());
        }
    }

    @Override
    public List<SupplierApiDetailVO> getSupplierDetailBySupplierIdAndSupplierName(List<Long> supplierIds, String supplierName) {
        return supplierDetailMapper.getSupplierDetailBySupplierIdAndSupplierName(supplierIds, supplierName);
    }

    @Override
    public SupplierApiDetailVO getShoExtensionsBySupplierId(Long supplierId) {
        SupplierApiDetailVO extension = supplierDetailMapper.getShoExtensionsBySupplierId(supplierId);
        // 通联是上线待审核的话供应商状态也做对应展示
        setAllinpaySupplierStatus(extension);
        return extension;
    }

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierApiDetailVO.supplierId")
    @GlobalTransactional(rollbackFor = Exception.class)
    public void offline(SupplierApiDetailVO supplierApiDetailVO, String offlineReason, Long sysUserId) {
        Integer sysType = SysTypeEnum.SUPPLIER.value();
        // 添加下线处理记录
        OfflineHandleEventDTO offlineHandleEventDTO = new OfflineHandleEventDTO();
        offlineHandleEventDTO.setHandleId(supplierApiDetailVO.getSupplierId());
        offlineHandleEventDTO.setHandleType(OfflineHandleEventType.SHOP.getValue());
        offlineHandleEventDTO.setOfflineReason(offlineReason);
        offlineHandleEventDTO.setHandlerId(sysUserId);
        offlineHandleEventDTO.setSysType(sysType);
        offlineHandleEventDTO.setStatus(supplierAllinpayService.getIsAllinpay() ? OfflineHandleEventStatus.APPLY_BY_SHOP.getValue() : OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        offlineHandleEventDTO.setShopId(supplierApiDetailVO.getSupplierId());
        ServerResponseEntity<OfflineHandleEventVO> processingEventByHandleTypeAndHandleId = offlineHandleEventFeignClient.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.SHOP.getValue(), supplierApiDetailVO.getSupplierId(), sysType);
        if (processingEventByHandleTypeAndHandleId.isSuccess() && Objects.nonNull(processingEventByHandleTypeAndHandleId.getData())) {
            offlineHandleEventFeignClient.update(offlineHandleEventDTO);
        } else {
            offlineHandleEventFeignClient.save(offlineHandleEventDTO);
        }
        // 更新供应商状态为下线
        supplierDetailMapper.changeSupplierStatus(supplierApiDetailVO.getSupplierId(), SupplierStatus.OFFLINE.value());

        // 将供应商所有商品下线
        ServerResponseEntity<Void> spuResponseEntity = spuFeignClient.offlineSpuBySupplierId(supplierApiDetailVO.getSupplierId());
        if (!spuResponseEntity.isSuccess()) {
            throw new LuckException(spuResponseEntity);
        }
    }

    @Override
    public Long countBySupplierStatus(Long supplierStatus) {
        return supplierDetailMapper.countBySupplierStatus(supplierStatus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void platformCreateSupplier(SupplierCreateInfoDTO supplierCreateInfoDTO) {
        boolean isAllinpay = supplierAllinpayService.getIsAllinpay();
        SupplierUserRegisterDTO supplierUserRegisterInfo = supplierCreateInfoDTO.getSupplierUserRegisterInfo();
        // 1、校验验证码信息
        ServerResponseEntity<Boolean> sendNotifyResponse = notifyFeignClient.checkValidCode(supplierUserRegisterInfo.getMobile(), supplierUserRegisterInfo.getValidCode(), SendTypeEnum.VALID);
        Boolean data = sendNotifyResponse.getData();
        if (Objects.equals(sendNotifyResponse.getCode(), ResponseEnum.OK.value()) && Objects.nonNull(data) && !data) {
            throw new LuckException("供应商验证码有误或已过期");
        }
        // 2、保存供应商基本信息
        Date now = new Date();
        SupplierDetailDTO supplierDetailDTO = supplierCreateInfoDTO.getSupplierDetail();
        this.checkSupplierInfo(supplierDetailDTO, true);
        SupplierDetail supplierDetail = saveAndGetSupplierDetail(isAllinpay, now, supplierDetailDTO);
        // 通联创建企业会员
        supplierAllinpayService.createAllinpayCompanyMember(supplierDetail.getSupplierId());
        Long supplierId = supplierDetail.getSupplierId();
        // 3、保存供应商账号信息
        SupplierUser supplierUser = new SupplierUser();
        supplierUser.setNickName(supplierUserRegisterInfo.getUsername());
        supplierUser.setPhoneNum(supplierUserRegisterInfo.getMobile());
        supplierUser.setHasAccount(1);
        supplierUser.setSupplierId(supplierId);
        supplierUserService.save(supplierUser, null);
        // 4、初始化供应商数据
        addSupplierInfo(supplierId);
        // 5、初始化供应商审核信息，平台端创建供应商默认为审核成功
        SupplierAuditing supplierAuditing = new SupplierAuditing();
        supplierAuditing.setSupplierId(supplierId);
        supplierAuditing.setUserId(supplierUser.getSupplierUserId());
        supplierAuditing.setAuditorId(AuthUserContext.get().getUserId());
        supplierAuditing.setStatus(isAllinpay ? AuditStatus.WAITAUDIT.value() : AuditStatus.SUCCESSAUDIT.value());
        supplierAuditingService.save(supplierAuditing);
        // 6、保存供应商工商信息
        SupplierCompanyDTO supplierCompanyDTO = supplierCreateInfoDTO.getSupplierCompany();
        supplierCompanyDTO.setSupplierId(supplierDetail.getSupplierId());
        SupplierCompany supplierCompany = BeanUtil.map(supplierCompanyDTO, SupplierCompany.class);
        supplierCompany.setStatus(isAllinpay ? AuditStatus.WAITAUDIT.value() : AuditStatus.SUCCESSAUDIT.value());
        supplierCompanyService.save(supplierCompany, true);
        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setPhone(supplierUserRegisterInfo.getMobile());
        authAccountDTO.setIsAdmin(UserAdminType.ADMIN.value());
        authAccountDTO.setUsername(supplierUserRegisterInfo.getUsername());
        authAccountDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        authAccountDTO.setStatus(StatusEnum.ENABLE.value());
        authAccountDTO.setTenantId(supplierId);
        authAccountDTO.setUserId(supplierUser.getSupplierUserId());
        authAccountDTO.setPassword(supplierUserRegisterInfo.getPassword());
        authAccountDTO.setCreateIp(IpHelper.getIpAddr());
        authAccountDTO.setIsPassShop(isAllinpay ? IsPassShopEnum.NO.value() : IsPassShopEnum.YES.value());
        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(supplierCreateInfoDTO.getCategorySigningList(), supplierId, SysTypeEnum.SUPPLIER.value());
        if (!categoryRes.isSuccess()) {
            throw new LuckException(categoryRes.getMsg());
        }
        // 9、保存品牌签约信息
        ServerResponseEntity<Void> brandRes = brandSupplierFeignClient.insertBatchByShopId(supplierCreateInfoDTO.getBrandSigningList(), supplierId, SysTypeEnum.SUPPLIER.value());
        if (!brandRes.isSuccess()) {
            throw new LuckException(brandRes.getMsg());
        }
        // 7、保存供应商银行卡信息
        saveSupplierBankCard(supplierCreateInfoDTO, isAllinpay, supplierId, supplierCompany);

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

    private void saveSupplierBankCard(SupplierCreateInfoDTO supplierCreateInfoDTO, boolean isAllinpay, Long supplierId, SupplierCompany supplierCompany) {
        if (isAllinpay) {
            AllinpaySupplierBankCardDTO allinpaySupplierBankCardDTO = supplierCreateInfoDTO.getAllinpaySupplierBankCardDTO();
            if (Objects.isNull(allinpaySupplierBankCardDTO)) {
                throw new LuckException("至少绑定一个对公户账户");
            }
            // 保存数据到数据库
            supplierBankCardService.insertAndSetCompanyInfo(allinpaySupplierBankCardDTO, supplierId, BeanUtil.map(supplierCompany, SupplierCompanyVO.class));
        } else {
            supplierBankCardService.insertBatch(supplierCreateInfoDTO.getSupplierBankCardList(), supplierId);
        }
    }

    private SupplierDetail saveAndGetSupplierDetail(boolean isAllinpay, Date now, SupplierDetailDTO supplierDetailDTO) {
        SupplierDetail supplierDetail = BeanUtil.map(supplierDetailDTO, SupplierDetail.class);
        if (!isAllinpay) {
            if (Objects.isNull(supplierDetail.getContractStartTime())) {
                throw new LuckException("供应商签约时间不能为空");
            }
            handleContract(supplierDetail, supplierDetail.getContractStartTime(), supplierDetail.getContractEndTime(), now);
        } else {
            supplierDetail.setSupplierStatus(SupplierStatus.OPEN.value());
        }
        supplierDetail.setIsPreferred(IsPassShopEnum.NO.value());
        supplierDetail.setType(SupplierType.SELF_SHOP.value());
        supplierDetailMapper.save(supplierDetail);
        return supplierDetail;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void changeSupplierStatusByContractTime(Date now) {
        // 获取状态需要改变为停业状态的供应商id列表
        List<Long> supplierIdsToStop = supplierDetailMapper.listSupplierIdsOfStatusChangeToStopByContractTime(now);
        // 获取状态需要改变为营业状态的供应商id列表
        List<Long> supplierIdsToOpen = supplierDetailMapper.listSupplierIdsOfStatusChangeToOpenByContractTime(now);
        if (CollUtil.isEmpty(supplierIdsToStop) && CollUtil.isEmpty(supplierIdsToOpen)) {
            // 没有供应商状态需要改变
            return;
        }
        // 根据签约时间修改供应商状态
        supplierDetailMapper.changeSupplierStatusByContractTime(now);
        if (CollUtil.isNotEmpty(supplierIdsToStop)) {
            // 失效商品活动信息，不需要下架商品
            spuFeignClient.offlineSpuActivityByShopIds(supplierIdsToStop);
            //供应商为停业状态，下架供应商商品
            spuFeignClient.batchChangeSpuStatusToDisableBySupplierIds(supplierIdsToStop);
        }
        // 状态发生变化的供应商id列表
        List<Long> changeSupplierIds = CollUtil.unionAll(supplierIdsToStop, supplierIdsToOpen);
        // 清除状态发生变化的供应商缓存信息
        List<String> keyList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        changeSupplierIds.forEach(supplierId -> keyList.add(CacheNames.SUPPLIER_DETAIL_ID_KEY + CacheNames.UNION + supplierId));
        if (CollUtil.isNotEmpty(keyList)) {
            RedisUtil.deleteBatch(keyList);
        }
        // 更新供应商下的商品更新时间（用于刷新商品在es的appDisplay）
        ServerResponseEntity<Void> spuRes = spuFeignClient.updateSpuUpdateTimeByShopIds(changeSupplierIds, SysTypeEnum.SUPPLIER.value());
        if (!spuRes.isSuccess()) {
            throw new LuckException(spuRes.getMsg());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierSigningInfoDTO.supplierId")
    public void updateSigningInfo(SupplierSigningInfoDTO supplierSigningInfoDTO) {
        SupplierApiDetailVO oldSupplierDetail = supplierDetailMapper.getBySupplierId(supplierSigningInfoDTO.getSupplierId());
        SupplierDetail newSupplierDetail = BeanUtil.map(oldSupplierDetail, SupplierDetail.class);
        // 赋值
        newSupplierDetail.setType(supplierSigningInfoDTO.getType());
        newSupplierDetail.setContractStartTime(DateUtil.beginOfDay(supplierSigningInfoDTO.getContractStartTime()));
        newSupplierDetail.setContractEndTime(Objects.isNull(supplierSigningInfoDTO.getContractEndTime()) ? null : getSaveEndOfDay(supplierSigningInfoDTO.getContractEndTime()));
        // 当供应商状态处于营业中或者停业中时，供应商状态会受签约时间改变
        if (Objects.equals(newSupplierDetail.getSupplierStatus(), SupplierStatus.OPEN.value()) || Objects.equals(newSupplierDetail.getSupplierStatus(), SupplierStatus.STOP.value())) {
            Date now = new Date();
            // 记录供应商状态是否发生改变
            boolean isChangeStatus = false;
            boolean isContain = now.compareTo(newSupplierDetail.getContractStartTime()) >= 0 && (Objects.isNull(newSupplierDetail.getContractEndTime()) || now.compareTo(newSupplierDetail.getContractEndTime()) < 0);
            if (isContain || supplierAllinpayService.getIsAllinpay()) {
                // 如果供应商的签约时间包含当前时间，则把供应商状态置为营业中
                isChangeStatus = Objects.equals(oldSupplierDetail.getSupplierStatus(), SupplierStatus.STOP.value());
                newSupplierDetail.setSupplierStatus(SupplierStatus.OPEN.value());
                supplierDetailMapper.update(newSupplierDetail);
                ServerResponseEntity<Void> spuRes = spuFeignClient.updateSpuUpdateTimeByShopIds(Collections.singletonList(supplierSigningInfoDTO.getSupplierId()), SysTypeEnum.SUPPLIER.value());
                if (!spuRes.isSuccess()) {
                    throw new LuckException(spuRes.getMsg());
                }
            } else if (now.compareTo(newSupplierDetail.getContractStartTime()) < 0 || now.compareTo(newSupplierDetail.getContractEndTime()) >= 0) {
                // 如果供应商的签约时间不包含当前时间，则把供应商状态置为停业中
                isChangeStatus = Objects.equals(oldSupplierDetail.getSupplierStatus(), SupplierStatus.OPEN.value());
                newSupplierDetail.setSupplierStatus(SupplierStatus.STOP.value());
                supplierDetailMapper.update(newSupplierDetail);
            }
            //  供应商商品不能参加活动，不需要进行以下处理

//            // 如果供应商状态发生变化
            if (isChangeStatus) {
                // 更新购物车项供应商是否停业状态
                if (Objects.equals(oldSupplierDetail.getSupplierStatus(), SupplierStatus.OPEN.value())) {
                    // 供应商营业状态变为停业，需要下架供应商商品
                    ServerResponseEntity<Void> toDisableRes = spuFeignClient.batchChangeSpuStatusToDisableBySupplierIds(Collections.singletonList(newSupplierDetail.getSupplierId()));
                    if (!toDisableRes.isSuccess()) {
                        throw new LuckException(toDisableRes.getMsg());
                    }
                }
            }
        }
        //解绑平台轮播图商品
//        offlineIndexImg(newSupplierDetail.getSupplierId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#offlineHandleEventDTO.handleId")
    public void auditApply(OfflineHandleEventDTO offlineHandleEventDTO) {
        SupplierApiDetailVO supplierApiDetailVO = getBySupplierId(offlineHandleEventDTO.getHandleId());
        if (Objects.isNull(supplierApiDetailVO)) {
            throw new LuckException("供应商不存在");
        }
        if (!Objects.equals(supplierApiDetailVO.getSupplierStatus(), SupplierStatus.OFFLINE.value())) {
            throw new LuckException("供应商状态已发生变化，请刷新后重试");
        }
        // 更新事件状态
        ServerResponseEntity<Void> offlineRes = offlineHandleEventFeignClient.updateToApply(offlineHandleEventDTO);
        if (!offlineRes.isSuccess()) {
            throw new LuckException(offlineRes.getMsg());
        }
        // 更改供应商状态为上线申请待审核
        supplierDetailMapper.changeSupplierStatus(offlineHandleEventDTO.getHandleId(), SupplierStatus.OFFLINE_AWAIT_AUDIT.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#offlineHandleEventDTO.handleId")
    public void onlineAudit(OfflineHandleEventDTO offlineHandleEventDTO) {
        SupplierApiDetailVO supplierDetail = getBySupplierId(offlineHandleEventDTO.getHandleId());
        if (Objects.isNull(supplierDetail)) {
            throw new LuckException("供应商不存在");
        }
        if (!Objects.equals(supplierDetail.getSupplierStatus(), SupplierStatus.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());
        }
        Date now = new Date();
        Long supplierId = offlineHandleEventDTO.getHandleId();
        // 审核通过
        if (Objects.equals(offlineHandleEventDTO.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            auditSuccess(supplierDetail, now, supplierId);
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventDTO.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            supplierDetailMapper.changeSupplierStatus(supplierId, SupplierStatus.OFFLINE.value());
        }
    }

    private void auditSuccess(SupplierApiDetailVO supplierDetail, Date now, Long supplierId) {
        if (supplierAllinpayService.getIsAllinpay()) {
            supplierDetailMapper.changeSupplierStatus(supplierId, SupplierStatus.OPEN.value());
            spuFeignClient.updateSpuUpdateTimeByShopIds(Collections.singletonList(supplierId), SysTypeEnum.SUPPLIER.value());
            return;
        }
        if (now.compareTo(supplierDetail.getContractStartTime()) >= 0 && (Objects.isNull(supplierDetail.getContractEndTime()) || now.compareTo(supplierDetail.getContractEndTime()) < 0)) {
            // 如果供应商的签约时间包含当前时间，则把供应商状态置为营业中
            supplierDetailMapper.changeSupplierStatus(supplierId, SupplierStatus.OPEN.value());
        } else {
            // 如果供应商的签约时间不包含当前时间，则把供应商状态置为停业中
            supplierDetailMapper.changeSupplierStatus(supplierId, SupplierStatus.STOP.value());
        }
        spuFeignClient.updateSpuUpdateTimeByShopIds(Collections.singletonList(supplierId), SysTypeEnum.SUPPLIER.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#offlineHandleEventDTO.handleId")
    public void onlineOpenSupplier(OfflineHandleEventDTO offlineHandleEventDTO) {
        if (!supplierAllinpayService.getIsAllinpay()) {
            throw new LuckException("开通通联支付后才可以直接上线供应商");
        }
        SupplierDetailService supplierDetailService = (SupplierDetailService) AopContext.currentProxy();
        SupplierApiDetailVO supplierDetail = supplierDetailService.getBySupplierId(offlineHandleEventDTO.getHandleId());
        if (Objects.isNull(supplierDetail)) {
            throw new LuckException("供应商不存在");
        }
        if (!Objects.equals(supplierDetail.getSupplierStatus(), ShopStatus.OFFLINE_AWAIT_AUDIT.value()) && !Objects.equals(supplierDetail.getSupplierStatus(), ShopStatus.OFFLINE.value())) {
            throw new LuckException("供应商状态已发生变化，请刷新后重试");
        }
        // 审核
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.auditOfflineEvent(offlineHandleEventDTO);
        if (!responseEntity.isSuccess()) {
            throw new LuckException(responseEntity.getMsg());
        }
        // 审核通过
        auditSuccess(supplierDetail, new Date(), offlineHandleEventDTO.getHandleId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createAllinpayMemberBySupplierId(Long supplierId) {
        // 该方法通联独有
        if (!supplierAllinpayService.getIsAllinpay()) {
            return;
        }
        // 确保供应商还没有创建
        SupplierApiDetailVO supplierDetail = supplierDetailMapper.getSupplierBySupplierId(supplierId);
        if (Objects.equals(supplierDetail.getIsCreateMember(), 1)) {
            return;
        }
        supplierDetailMapper.updateSupplierIsCreate(Collections.singletonList(supplierId));
        Integer supplierStatus = supplierDetail.getSupplierStatus();
        if (Objects.equals(supplierStatus, ShopStatus.OPEN.value())
                || Objects.equals(supplierStatus, ShopStatus.STOP.value())
                || Objects.equals(supplierStatus, ShopStatus.OFFLINE.value())
                || Objects.equals(supplierStatus, ShopStatus.OFFLINE_AWAIT_AUDIT.value())) {
            // 已经开店的
            // 更新供应商信息并且将对应供应商的通联商家改完平台下线，等绑定了手机，设置了企业信息，影印件审核通过后，通联审核通过即可恢复原状态
            supplierDetailMapper.updateSupplierToStop(Collections.singletonList(supplierId));
        } else if (Objects.equals(supplierStatus, ShopStatus.OPEN_AWAIT_AUDIT.value())) {
            // 提交开店申请的
            // 找出已经提交申请的供应商的审核信息给予驳回，然后更改状态为申请中
            supplierDetailMapper.updateSupplierToApplying(Collections.singletonList(supplierId));
            supplierAuditingService.updateToFail(Collections.singletonList(supplierId));
        }
        SupplierCompanyAuditingVO companyAuditingVO = supplierCompanyAuditingMapper.getLatestAuditingBySupplierId(supplierId);
        if (Objects.nonNull(companyAuditingVO)) {
            if (Objects.equals(companyAuditingVO.getStatus(), AuditStatus.WAITAUDIT.value())) {
                // 修改工商信息的
                // 给予驳回，更改最后成功的工商信息为待审核
                companyAuditingVO.setRemarks("通联信息待完善");
                companyAuditingVO.setStatus(AuditStatus.FAILAUDIT.value());
                supplierCompanyAuditingMapper.update(BeanUtil.map(companyAuditingVO, SupplierCompanyAuditing.class));
                // 把对应的工商信息设置为审核未通过状态
                SupplierCompany supplierCompany = new SupplierCompany();
                supplierCompany.setStatus(AuditStatus.FAILAUDIT.value());
                supplierCompany.setSupplierCompanyId(companyAuditingVO.getSupplierCompanyId());
                supplierCompanyService.updateById(supplierCompany);
            }
        }
        // 修改供应商成功的工商信息为待审核
        supplierCompanyService.batchUpdateStatus(supplierId, AuditStatus.WAITAUDIT.value(), AuditStatus.SUCCESSAUDIT.value());

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

    @Override
    public List<SupplierSimpleBO> listSimple(SupplierSimpleBO supplierSimpleBO) {
        return supplierDetailMapper.listSimple(supplierSimpleBO);
    }

    @Override
    public Boolean checkSupplierName(String supplierName) {
        return supplierDetailMapper.countSupplierName(supplierName, null) > 0;
    }

    @Override
    public List<Long> getSupplierIdBySupplierStatus(Integer supplierStatus) {
        return supplierDetailMapper.getSupplierIdsBySupplierStatus(supplierStatus);
    }

    @Override
    public PageVO<SupplierDetailVO> pageSupplier(PageDTO pageDTO, SupplierDetailDTO supplierDetailDTO, Long shopId) {
        supplierDetailDTO.setPaySysType(supplierAllinpayService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value());
        //商家端 只显示有相同分类的供应商
        if (Objects.equals(supplierDetailDTO.getSysType(), SysTypeEnum.MULTISHOP.value())) {
            ServerResponseEntity<List<Long>> idsResp = categoryShopFeignClient.getSupplierIdsByShopId(shopId);
            if (!idsResp.isSuccess()) {
                throw new LuckException(idsResp);
            }
            if (CollectionUtil.isEmpty(idsResp.getData())) {
                PageVO<SupplierDetailVO> pageVO = new PageVO<>();
                pageVO.setList(new ArrayList<>(Constant.INITIAL_CAPACITY));
                pageVO.setTotal(0L);
                pageVO.setPages(0);
                return pageVO;
            }
            return PageUtil.doPage(pageDTO, () -> supplierDetailMapper.listSupplierDetail(supplierDetailDTO, idsResp.getData()));
        }
        //平台端 显示全部供应商
        return PageUtil.doPage(pageDTO, () -> supplierDetailMapper.listSupplierDetail(supplierDetailDTO, null));

    }

    @Override
    public List<SupplierDetailVO> listSupplierByShopId(SupplierDetailDTO supplierDetailDTO, Long shopId) {
        //商家端 只显示有相同分类的供应商
        ServerResponseEntity<List<Long>> supplierIdsResp = categoryShopFeignClient.getSupplierIdsByShopId(shopId);
        if (!supplierIdsResp.isSuccess()) {
            throw new LuckException(supplierIdsResp);
        }
        if (CollUtil.isEmpty(supplierIdsResp.getData())) {
            return new ArrayList<>(0);
        }
        return supplierDetailMapper.listSupplierDetail(supplierDetailDTO, supplierIdsResp.getData());

    }

    @Override
    public List<SupplierApiDetailVO> listSupplierDetailBySupplierIds(List<Long> supplierIds) {
        if (CollUtil.isEmpty(supplierIds)) {
            return new ArrayList<>(0);
        }
        return supplierDetailMapper.listSupplierDetailBySupplierIds(supplierIds);
    }

    @Override
    public void createAllinpayMember() {
        List<Long> supplierIds = supplierDetailMapper.listUnCreateMemberSupplierIds();
        if (CollUtil.isEmpty(supplierIds)) {
            return;
        }

        supplierDetailMapper.updateSupplierIsCreate(supplierIds);
        // 已经开店的
        // 更新供应商信息并且将对应供应商的通联商家改完平台下线，等绑定了手机，设置了企业信息，影印件审核通过后，通联审核通过即可恢复原状态
        supplierDetailMapper.updateSupplierToStop(supplierIds);
        // 提交开店申请的
        // 找出已经提交申请的商家的审核信息给予驳回，然后更改状态为申请中
        supplierDetailMapper.updateSupplierToApplying(supplierIds);
        supplierAuditingService.updateToFail(supplierIds);

        // 修改工商信息的
        // 给予驳回，更改最后成功的工商信息为待审核
        List<SupplierCompanyAuditingVO> needAuditList = supplierCompanyAuditingMapper.getNeedAuditList();
        if (CollUtil.isNotEmpty(needAuditList)) {
            for (SupplierCompanyAuditingVO companyAuditing : needAuditList) {
                companyAuditing.setStatus(AuditStatus.FAILAUDIT.value());
                companyAuditing.setRemarks("通联信息待完善");
                supplierCompanyAuditingMapper.update(BeanUtil.map(companyAuditing, SupplierCompanyAuditing.class));
                // 把对应的工商信息设置为审核未通过状态
                SupplierCompany shopCompany = new SupplierCompany();
                shopCompany.setSupplierCompanyId(companyAuditing.getSupplierCompanyId());
                shopCompany.setStatus(AuditStatus.FAILAUDIT.value());
                supplierCompanyService.updateById(shopCompany);
            }
        }
        supplierCompanyService.updateStatusToWaitAudit();
        // 给所有商家都新增一个通联的钱包
        List<String> keys = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (Long supplierId : supplierIds) {
            saveSupplierWallet(supplierId, true);
            // 删除商家的银行卡，需要重新绑定
            supplierBankCardService.deleteBySupplierId(supplierId);
            // 将该供应商所有的商品下线
            ServerResponseEntity<Void> spuResponse = spuFeignClient.offlineSpuByShopId(supplierId);
            if (!Objects.equals(spuResponse.getCode(), ResponseEnum.OK.value())) {
                throw new LuckException(spuResponse.getMsg());
            }
            keys.add(CacheNames.SUPPLIER_DETAIL_ID_KEY + CacheNames.UNION + supplierId);
        }
        RedisUtil.del(keys);

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAllinpayIdCardStatus(String bizUserId, Integer status) {
        Long supplierId = Long.valueOf(bizUserId.substring(AllinpayConstant.SUPPLIER_LENGTH));
        log.info("供应商{}影印件更新，影印件状态为{}", supplierId, Objects.requireNonNull(IdCardCollectProcessStatus.instance(status)).str());
        supplierBankCardService.updateSupplierAllinpayStatusToSuccess(supplierId);
        supplierDetailMapper.updateAllinpayIdCardStatus(supplierId, status);
        // 如果审核都通过，将对应供应商上线
        if (!Objects.equals(status, IdCardCollectProcessStatus.ALL.value())) {
            log.info("供应商{}影印件更新，影印件状态为{}，未全部通过审核", supplierId, Objects.requireNonNull(IdCardCollectProcessStatus.instance(status)).str());
            return;
        }
        supplierDetailMapper.updateSupplierToOpen(supplierId);
        SupplierAuditingVO supplierAuditing = supplierAuditingService.getBySupplierId(supplierId);
        if (!Objects.equals(supplierAuditing.getStatus(), AuditStatus.SUCCESSAUDIT.value())) {
            log.info("供应商{}影印件更新,全部通过审核,进行开店回调，自动审核供应商", supplierId);
            // 审核还没成功代表这是开店的回调
            SupplierAuditingDTO supplierAuditingDTO = BeanUtil.map(supplierAuditing, SupplierAuditingDTO.class);
            supplierAuditingDTO.setStatus(AuditStatus.SUCCESSAUDIT.value());
            // 自动审核供应商
            audit(supplierAuditingDTO);
        } else {
            log.info("供应商{}影印件更新,全部通过审核,进行修改工商信息回调，自动审核工商信息", supplierId);
            // 修改工商信息回调
            SupplierCompanyAuditingVO companyAuditing = supplierCompanyAuditingMapper.getLatestAuditingBySupplierId(supplierId);
            if (Objects.isNull(companyAuditing)) {
                log.error("影印件回调，工商审核信息不存在{}", bizUserId);
                return;
            }
            if (Objects.equals(companyAuditing.getStatus(), AuditStatus.WAITAUDIT.value())) {
                log.info("供应商{}影印件更新,全部通过审核,进行修改工商信息回调，工商信息为待审核状态", supplierId);
                companyAuditing.setStatus(AuditStatus.SUCCESSAUDIT.value());
                supplierCompanyAuditingMapper.update(BeanUtil.map(companyAuditing, SupplierCompanyAuditing.class));

                supplierCompanyService.batchUpdateStatus(companyAuditing.getSupplierId(), AuditStatus.FAILAUDIT.value(), null);
                // 把对应的工商信息设置为启用状态
                SupplierCompany shopCompany = new SupplierCompany();
                shopCompany.setSupplierCompanyId(companyAuditing.getSupplierCompanyId());
                shopCompany.setStatus(AuditStatus.SUCCESSAUDIT.value());
                supplierCompanyService.updateById(shopCompany);
            } else if (Objects.equals(companyAuditing.getStatus(), AuditStatus.FAILAUDIT.value())) {
                log.info("供应商{}影印件更新,全部通过审核,进行修改工商信息回调，工商信息为失败状态", supplierId);
                // 审核不通过的工商信息删了
                supplierCompanyService.deleteBySupplierIdAndStatus(supplierId, AuditStatus.FAILAUDIT.value());
            }
        }
    }

    @Override
    public List<SupplierApiDetailVO> listSupplierIds() {
        return supplierDetailMapper.listSupplierIds();
    }

    private void saveSupplierWallet(Long supplierId, boolean isAllinpay) {
        SupplierWallet supplierWallet = new SupplierWallet();
        supplierWallet.setVersion(0L);
        supplierWallet.setUnsettledAmount(0L);
        supplierWallet.setSettledAmount(0L);
        supplierWallet.setFreezeAmount(0L);
        supplierWallet.setTotalSettledAmount(0L);
        supplierWallet.setSupplierId(supplierId);
        supplierWallet.setPaySysType(isAllinpay ? 1 : 0);
        supplierWalletMapper.save(supplierWallet);
    }

    /**
     * 添加供应商钱包
     * @param supplierId
     * @return
     */
    public void addSupplierInfo(Long supplierId) {
        SupplierExtension supplierExtension = new SupplierExtension();
        supplierExtension.setSupplierId(supplierId);
        supplierExtensionService.save(supplierExtension);

        saveSupplierWallet(supplierId, supplierAllinpayService.getIsAllinpay());
    }

    /**
     * 检验供应商信息是否正确
     * @param supplierDetailDTO 供应商基本信息
     * @param isCreate true: 创建时校验， false: 更新时校验
     */
    private void checkSupplierInfo(SupplierDetailDTO supplierDetailDTO, Boolean isCreate) {
        if (!isCreate) {
            SupplierAuditingVO supplierAuditingVO = supplierAuditingService.getBySupplierId(supplierDetailDTO.getSupplierId());
            if (Objects.nonNull(supplierAuditingVO) && Objects.equals(supplierAuditingVO.getStatus(), AuditStatus.WAITAUDIT.value())) {
                throw new LuckException("供应商处于待审核状态无法修改信息");
            }
        }
        // 供应商供应商名称
        if (StrUtil.isNotBlank(supplierDetailDTO.getSupplierName())) {
            supplierDetailDTO.setSupplierName(supplierDetailDTO.getSupplierName().trim());
        }
        if (supplierDetailMapper.countSupplierName(supplierDetailDTO.getSupplierName(), supplierDetailDTO.getSupplierId()) > 0) {
            throw new LuckException("供应商名称已存在");
        }
        if (!isCreate) {
            // 更新供应商基本信息不用校验用户信息
            return;
        }
        if (StrUtil.isNotBlank(supplierDetailDTO.getContactPhone())) {
            supplierDetailDTO.setPhone(supplierDetailDTO.getContactPhone().trim());
        }
    }

    /**
     * 创建供应商初始账号
     * @param supplierDetailDTO
     * @param statusEnum
     */
    public void createSupplierAccount(SupplierDetailDTO supplierDetailDTO, StatusEnum statusEnum) {
        SupplierUser supplierUser = new SupplierUser();
        supplierUser.setSupplierId(supplierDetailDTO.getSupplierId());
        supplierUser.setHasAccount(1);
        supplierUser.setNickName(supplierDetailDTO.getUsername());
        supplierUserService.save(supplierUser, null);

        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setPhone(supplierDetailDTO.getPhone());
        authAccountDTO.setUsername(supplierDetailDTO.getUsername());
        authAccountDTO.setPassword(supplierDetailDTO.getPassword().trim());
        authAccountDTO.setStatus(statusEnum.value());
        authAccountDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        authAccountDTO.setCreateIp(IpHelper.getIpAddr());
        authAccountDTO.setTenantId(supplierDetailDTO.getSupplierId());
        authAccountDTO.setUserId(supplierUser.getSupplierUserId());
        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();
    }
}
