package org.dromara.payment.merchant.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.enums.BusRole;
import org.dromara.common.core.enums.SmsType;
import org.dromara.common.core.service.BaseService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.payment.channel.domain.BusChannel;
import org.dromara.payment.channel.domain.vo.BusChannelVo;
import org.dromara.payment.invoice.domain.MerInvoiceAddress;
import org.dromara.payment.invoice.mapper.MerInvoiceAddressMapper;
import org.dromara.payment.merchant.domain.BusMerchantConfig;
import org.dromara.payment.merchant.mapper.BusMerchantConfigMapper;
import org.dromara.payment.sys.domain.bo.SysUnitBo;
import org.dromara.payment.sys.service.ISysUnitService;
import org.dromara.resource.api.RemoteSmsService;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.bo.RemoteUserBo;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.dromara.payment.merchant.domain.bo.BusMerchantBo;
import org.dromara.payment.merchant.domain.vo.BusMerchantVo;
import org.dromara.payment.merchant.domain.BusMerchant;
import org.dromara.payment.merchant.mapper.BusMerchantMapper;
import org.dromara.payment.merchant.service.IBusMerchantService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * 商户Service业务层处理
 *
 * @author LionLi
 * @date 2024-04-03
 */
@RequiredArgsConstructor
@Service
public class BusMerchantServiceImpl extends BaseService implements IBusMerchantService {

    private final BusMerchantMapper baseMapper;

    private final BusMerchantConfigMapper merchantConfigMapper;

    private final MerInvoiceAddressMapper merInvoiceAddressMapper;

    @Resource
    private ISysUnitService  sysUnitService;


    @DubboReference
    private RemoteUserService remoteUserService;

    @DubboReference
    private RemoteSmsService remoteSmsService;


    /**
     * 查询商户
     */
    @Override
    public BusMerchantVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询商户列表
     */
    @Override
    public TableDataInfo<BusMerchantVo> queryPageList(BusMerchantBo bo, PageQuery pageQuery) {
        QueryWrapper<BusMerchant> lqw = Wrappers.query();
        if (!LoginHelper.isSuperAdmin()){
            lqw.between(bo.getStartTime() != null,"t.create_time",bo.getStartTime(),bo.getEndTime());
            lqw.like(StringUtils.isNotEmpty(bo.getName()),"t.name",bo.getName());
            lqw.like(StringUtils.isNotEmpty(bo.getNo()),"t.no",bo.getNo());
            lqw.like(StringUtils.isNotEmpty(bo.getScaleName()),"s.name",bo.getScaleName());
            if(bo.getIsProduct() != null && bo.getIsProduct() == 1){
                lqw.eq("t.create_unit_id",LoginHelper.getBusId());
            }
            int busRole = LoginHelper.getBusRole();
            if(busRole == BusRole.SERVICE.getId()){
                lqw.inSql("t.id","select  distinct mer_id from bus_merchant_product tt where tt.syd_id ="+LoginHelper.getBusId());
            }
        }

        lqw.orderByDesc("t.create_time");
        Page<BusMerchantVo> result = baseMapper.selectMerchantList(pageQuery.build(), lqw);

        result.getRecords().forEach(item->{
                item.setPayPassword(null);
                if(item.getCreateUnitId() != null && item.getCreateUnitId().equals(LoginHelper.getBusId())){
                    item.setIsCanSetScale(1);
                }
        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询商户列表
     */
    @Override
    public List<BusMerchantVo> queryList(BusMerchantBo bo) {
        LambdaQueryWrapper<BusMerchant> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<BusMerchant> buildQueryWrapper(BusMerchantBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BusMerchant> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getNo()), BusMerchant::getNo, bo.getNo());
        lqw.eq(StringUtils.isNotBlank(bo.getIndustry()), BusMerchant::getIndustry, bo.getIndustry());
        lqw.like(StringUtils.isNotBlank(bo.getName()), BusMerchant::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getNameNc()), BusMerchant::getNameNc, bo.getNameNc());
        lqw.eq(StringUtils.isNotBlank(bo.getNsrSbh()), BusMerchant::getNsrSbh, bo.getNsrSbh());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSjh()), BusMerchant::getFrSjh, bo.getFrSjh());
        lqw.eq(StringUtils.isNotBlank(bo.getWtrSjh()), BusMerchant::getWtrSjh, bo.getWtrSjh());
        lqw.eq(StringUtils.isNotBlank(bo.getWtr()), BusMerchant::getWtr, bo.getWtr());
        lqw.eq(StringUtils.isNotBlank(bo.getWtrSfz()), BusMerchant::getWtrSfz, bo.getWtrSfz());
        lqw.eq(StringUtils.isNotBlank(bo.getWtrEmail()), BusMerchant::getWtrEmail, bo.getWtrEmail());
        lqw.eq(StringUtils.isNotBlank(bo.getUnitArea()), BusMerchant::getUnitArea, bo.getUnitArea());
        lqw.like(StringUtils.isNotBlank(bo.getUnitAreaName()), BusMerchant::getUnitAreaName, bo.getUnitAreaName());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSfz()), BusMerchant::getFrSfz, bo.getFrSfz());
        lqw.eq(StringUtils.isNotBlank(bo.getFr()), BusMerchant::getFr, bo.getFr());
        lqw.eq(StringUtils.isNotBlank(bo.getBankCard()), BusMerchant::getBankCard, bo.getBankCard());
        lqw.eq(StringUtils.isNotBlank(bo.getAddress()), BusMerchant::getAddress, bo.getAddress());
        lqw.eq(bo.getYyzzBeginDate() != null, BusMerchant::getYyzzBeginDate, bo.getYyzzBeginDate());
        lqw.eq(bo.getYyzzEndDate() != null, BusMerchant::getYyzzEndDate, bo.getYyzzEndDate());
        lqw.eq(StringUtils.isNotBlank(bo.getYyzz()), BusMerchant::getYyzz, bo.getYyzz());
        lqw.eq(StringUtils.isNotBlank(bo.getPayPassword()), BusMerchant::getPayPassword, bo.getPayPassword());
        lqw.eq(bo.getPassErrorNum() != null, BusMerchant::getPassErrorNum, bo.getPassErrorNum());
        lqw.eq(bo.getPassFrozenTime() != null, BusMerchant::getPassFrozenTime, bo.getPassFrozenTime());
        lqw.eq(bo.getStatus() != null, BusMerchant::getStatus, bo.getStatus());
        lqw.eq(bo.getAddTime() != null, BusMerchant::getAddTime, bo.getAddTime());
        lqw.eq(StringUtils.isNotBlank(bo.getAddBy()), BusMerchant::getAddBy, bo.getAddBy());
        lqw.eq(StringUtils.isNotBlank(bo.getEditer()), BusMerchant::getEditer, bo.getEditer());
        lqw.eq(bo.getEditTime() != null, BusMerchant::getEditTime, bo.getEditTime());
        lqw.eq(StringUtils.isNotBlank(bo.getKhm()), BusMerchant::getKhm, bo.getKhm());
        lqw.eq(StringUtils.isNotBlank(bo.getKhd()), BusMerchant::getKhd, bo.getKhd());
        lqw.eq(StringUtils.isNotBlank(bo.getKhh()), BusMerchant::getKhh, bo.getKhh());
        lqw.eq(StringUtils.isNotBlank(bo.getKhhNo()), BusMerchant::getKhhNo, bo.getKhhNo());
        lqw.eq(StringUtils.isNotBlank(bo.getJbckzhbm()), BusMerchant::getJbckzhbm, bo.getJbckzhbm());
        lqw.eq(StringUtils.isNotBlank(bo.getPassage()), BusMerchant::getPassage, bo.getPassage());
        lqw.eq(bo.getFrCardidBeginDate() != null, BusMerchant::getFrCardidBeginDate, bo.getFrCardidBeginDate());
        lqw.eq(bo.getFrCardidEndDate() != null, BusMerchant::getFrCardidEndDate, bo.getFrCardidEndDate());
        lqw.eq(bo.getJbrCardidBeginDate() != null, BusMerchant::getJbrCardidBeginDate, bo.getJbrCardidBeginDate());
        lqw.eq(bo.getJbrCardidEndDate() != null, BusMerchant::getJbrCardidEndDate, bo.getJbrCardidEndDate());
        lqw.eq(bo.getYwyId() != null, BusMerchant::getYwyId, bo.getYwyId());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoceHeader()), BusMerchant::getInvoceHeader, bo.getInvoceHeader());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoceCreditCode()), BusMerchant::getInvoceCreditCode, bo.getInvoceCreditCode());
        lqw.like(StringUtils.isNotBlank(bo.getInvoceBankName()), BusMerchant::getInvoceBankName, bo.getInvoceBankName());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoceBankCard()), BusMerchant::getInvoceBankCard, bo.getInvoceBankCard());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoceAddress()), BusMerchant::getInvoceAddress, bo.getInvoceAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoceDwdh()), BusMerchant::getInvoceDwdh, bo.getInvoceDwdh());
        lqw.eq(StringUtils.isNotBlank(bo.getFhxkzPic()), BusMerchant::getFhxkzPic, bo.getFhxkzPic());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSfzzm()), BusMerchant::getFrSfzzm, bo.getFrSfzzm());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSfzfm()), BusMerchant::getFrSfzfm, bo.getFrSfzfm());
        lqw.eq(StringUtils.isNotBlank(bo.getJbrSfzzm()), BusMerchant::getJbrSfzzm, bo.getJbrSfzzm());
        lqw.eq(StringUtils.isNotBlank(bo.getJbrSfzfm()), BusMerchant::getJbrSfzfm, bo.getJbrSfzfm());
        lqw.eq(StringUtils.isNotBlank(bo.getMtqjzPic()), BusMerchant::getMtqjzPic, bo.getMtqjzPic());
        lqw.eq(StringUtils.isNotBlank(bo.getBgzp1Pic()), BusMerchant::getBgzp1Pic, bo.getBgzp1Pic());
        lqw.eq(StringUtils.isNotBlank(bo.getBgzp2Pic()), BusMerchant::getBgzp2Pic, bo.getBgzp2Pic());
        lqw.eq(StringUtils.isNotBlank(bo.getYwcjzsxcnh()), BusMerchant::getYwcjzsxcnh, bo.getYwcjzsxcnh());
        lqw.eq(StringUtils.isNotBlank(bo.getYwcjsm()), BusMerchant::getYwcjsm, bo.getYwcjsm());
        lqw.eq(StringUtils.isNotBlank(bo.getFddsqxy()), BusMerchant::getFddsqxy, bo.getFddsqxy());
        lqw.eq(StringUtils.isNotBlank(bo.getTshyxkz()), BusMerchant::getTshyxkz, bo.getTshyxkz());
        lqw.eq(bo.getVerifyStatus() != null, BusMerchant::getVerifyStatus, bo.getVerifyStatus());
        lqw.eq(bo.getVerifyTime() != null, BusMerchant::getVerifyTime, bo.getVerifyTime());
        lqw.eq(StringUtils.isNotBlank(bo.getVerifyBy()), BusMerchant::getVerifyBy, bo.getVerifyBy());
        lqw.eq(StringUtils.isNotBlank(bo.getVerifyReason()), BusMerchant::getVerifyReason, bo.getVerifyReason());
        lqw.eq(StringUtils.isNotBlank(bo.getScale()), BusMerchant::getScale, bo.getScale());
        lqw.eq(StringUtils.isNotBlank(bo.getLogo()), BusMerchant::getLogo, bo.getLogo());
        lqw.eq(StringUtils.isNotBlank(bo.getIntroduce()), BusMerchant::getIntroduce, bo.getIntroduce());
        lqw.eq(bo.getSalesmanId() != null, BusMerchant::getSalesmanId, bo.getSalesmanId());
        lqw.eq(bo.getIsValiAcc() != null, BusMerchant::getIsValiAcc, bo.getIsValiAcc());
        return lqw;
    }

    /**
     * 新增商户
     */
    @Override
    @Transactional
    public Boolean insertByBo(BusMerchantBo bo) {

        Long id = IdUtil.getSnowflakeNextId();

        bo.setId(id);
        bo.setCreateBy(LoginHelper.getUserId());
        bo.setCreateTime(new Date());
        bo.setSalesmanId(bo.getYwyId());
        bo.setVerifyStatus(0L);
        if(StringUtils.isEmpty(bo.getNo())){
            bo.setNo(LoginHelper.getNo()+"-"+this.getMerNo());
        }
        String pCode = LoginHelper.getNo();
        if(StringUtils.isNotEmpty(pCode)){
            String[] pcs = pCode.split("-");
            bo.setOperatorNo(pcs[0]);
            if(pcs.length >= 2){
                bo.setAgentNo(pCode);
            }
        }
        BusMerchant add = MapstructUtils.convert(bo, BusMerchant.class);
        validEntityBeforeSave(add);
        add.setCreateUnitId(LoginHelper.getBusId());
        add.setCreateUnitNo(LoginHelper.getNo());

        boolean flag = false;
        try{
                flag =  baseMapper.insert(add) > 0;
        }catch (Exception e){
            if( e instanceof DuplicateKeyException){
                bo.setNo(LoginHelper.getNo()+"-"+this.getMerNo());
                return this.insertByBo(bo);
            }
            throw e;
        }
        if (flag) {
            bo.setId(add.getId());
        }

        SysUnitBo  sysUnitBo = new SysUnitBo();
        sysUnitBo.setName(bo.getName());
        sysUnitBo.setId(id);
        sysUnitBo.setUnitType(BusRole.MERCHANT.getId());
        sysUnitBo.setNo(add.getNo());
        sysUnitBo.setCreateBy(add.getCreateBy());
        sysUnitBo.setCreateTime(add.getCreateTime());
        this.sysUnitService.insertByBo(sysUnitBo);


        BusMerchantConfig  busMerchantConfig = new BusMerchantConfig();
        busMerchantConfig.setMerId(add.getId());
        busMerchantConfig.setAutoApprove(1);
        busMerchantConfig.setValiWorker(1);
        busMerchantConfig.setCreateTime(new Date());

        this.merchantConfigMapper.insert(busMerchantConfig);



        return flag;
    }

    private String getMerNo() {
        return "M"+RandomUtil.randomString("0123456789",5);
    }

    /**
     * 修改商户
     */
    @Override
    public Boolean updateByBo(BusMerchantBo bo) {

        BusMerchantVo vo = this.baseMapper.selectVoById(bo.getId());
        if(vo == null){
            this.invalidationParamsException("无效主键!");
        }

        if(vo.getVerifyStatus() == null || vo.getVerifyStatus().equals(2L)){
            this.invalidationParamsException("此状态下不能修改企业信息");
        }
        BusMerchant update = MapstructUtils.convert(bo, BusMerchant.class);
        update.setNo(null);
        update.setVerifyStatus(0L);
        update.setAgentNo(null);
        update.setOperatorNo(null);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(BusMerchant entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除商户
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public int setYwy(Long id, Long ywyId) {

        if(id == null){
            this.invalidationParamsException("企业ID不能为空");
        }

        if(ywyId == null){
            this.invalidationParamsException("业务员ID不能为空");
        }
        BusMerchant bm = new BusMerchant();
        bm.setYwyId(ywyId);
        bm.setSalesmanId(bm.getYwyId());
        bm.setUpdateBy(LoginHelper.getUserId());
        bm.setUpdateTime(new Date());
        bm.setId(id);
        this.baseMapper.setAndUnbindYwy(bm);
        return 1;
    }

    @Override
    public Boolean checkMerChant(Long merId, Long checkType, String reason, String domain) {

        if(merId == null){
            this.invalidationParamsException("商户ID不能为空");
        }

        if(checkType == null){
            this.invalidationParamsException("审核类型不能为空");
        }

        if(checkType.intValue() == 1 && StringUtils.isEmpty(reason)){
            this.invalidationParamsException("驳回原因不能为空");
        }

        if(StringUtils.isEmpty(domain)){
            this.invalidationParamsException("域名不能为空");
        }

        BusMerchantVo bcv = this.baseMapper.selectVoById(merId);

        if(bcv == null){
            this.invalidationParamsException("商户ID无效");
        }

        if(checkType.intValue() == 2){

            MerInvoiceAddress invoiceAddress = new MerInvoiceAddress();
            invoiceAddress.setMerId(bcv.getId());
            invoiceAddress.setMerNo(bcv.getNo());
            invoiceAddress.setBankCard(bcv.getBankCard());
            invoiceAddress.setHeader(bcv.getName());
            invoiceAddress.setBankAddress(bcv.getKhd());
            invoiceAddress.setNsrSbh(bcv.getInvoceCreditCode());
            invoiceAddress.setUnitAddress(bcv.getInvoceAddress());
            invoiceAddress.setUnitPhone(bcv.getInvoceDwdh());
            this.merInvoiceAddressMapper.insert(invoiceAddress);


            RemoteUserBo remoteUserBo = new RemoteUserBo();
            remoteUserBo.setBusId(merId);
            remoteUserBo.setBusNo(bcv.getNo());
            remoteUserBo.setRoleId(BusRole.MERCHANT.getId());
            remoteUserBo.setRoleName(BusRole.MERCHANT.getName());
            remoteUserBo.setRoleDataRange(1);
            remoteUserBo.setNickName(bcv.getName());
            remoteUserBo.setCreateTime(new Date());
            remoteUserBo.setPhonenumber(bcv.getWtrSjh());
            remoteUserBo.setCreateBy(LoginHelper.getUserId());
            remoteUserBo.setUserName("M"+StringUtils.randmNumber(5));
            String pwd = StringUtils.randmNumber(6);
            remoteUserBo.setPassword(BCrypt.hashpw(pwd));
            this.addBusUser(remoteUserBo);
            LinkedHashMap smsMap = new LinkedHashMap();
            smsMap.put("type",BusRole.MERCHANT.getName());
            smsMap.put("name",remoteUserBo.getUserName());
            smsMap.put("pwd",pwd);
            this.remoteSmsService.send(domain,remoteUserBo.getPhonenumber(), SmsType.UNIT_OPEN,smsMap);
        }

        BusMerchant busMerchant =   new BusMerchant();
        busMerchant.setVerifyStatus(checkType);
        busMerchant.setVerifyReason(reason);
        busMerchant.setVerifyTime(new Date());
        busMerchant.setVerifyBy(LoginHelper.getUserId()+"");
        busMerchant.setId(merId);
        this.baseMapper.updateById(busMerchant);
        return true;
    }


    private void addBusUser(RemoteUserBo remoteUserBo) {
        int result = this.remoteUserService.insertBusUser(remoteUserBo);
        if(result  == -1){
            remoteUserBo.setUserName("M"+StringUtils.randmNumber(5));
            this.addBusUser(remoteUserBo);
        }
    }
    @Override
    public Integer unbindYwy(Long id, Long ywyId) {


        if(id == null){
            this.invalidationParamsException("主键ID不能为空");
        }


        BusMerchant bm = new BusMerchant();
        bm.setYwyId(null);
        bm.setSalesmanId(null);
        bm.setUpdateBy(LoginHelper.getUserId());
        bm.setUpdateTime(new Date());
        bm.setId(id);
        this.baseMapper.setAndUnbindYwy(bm);
        return 1;
    }
}
