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

import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
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.bo.BusChannelAccountBo;
import org.dromara.payment.channel.domain.vo.BaseCompInfo;
import org.dromara.payment.channel.service.IBusChannelAccountService;
import org.dromara.payment.merchant.domain.BusMerchant;
import org.dromara.payment.merchant.domain.bo.BusMerchantBo;
import org.dromara.payment.merchant.domain.vo.BusMerchantVo;
import org.dromara.payment.merchant.mapper.BusMerchantMapper;
import org.dromara.payment.operator.domain.BusOperator;
import org.dromara.payment.operator.domain.bo.BusOperatorBo;
import org.dromara.payment.operator.domain.vo.BusOperatorVo;
import org.dromara.payment.operator.mapper.BusOperatorMapper;
import org.dromara.payment.sys.domain.bo.SysUnitBo;
import org.dromara.payment.sys.domain.vo.SysSydVo;
import org.dromara.payment.sys.mapper.SysSydMapper;
import org.dromara.payment.sys.service.ISysUnitService;
import org.dromara.resource.api.RemoteSmsService;
import org.dromara.system.api.RemoteDictService;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.bo.RemoteUserBo;
import org.dromara.system.api.domain.vo.RemoteDictDataVo;
import org.dromara.system.api.model.LoginUser;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.dromara.payment.channel.domain.bo.BusChannelBo;
import org.dromara.payment.channel.domain.vo.BusChannelVo;
import org.dromara.payment.channel.domain.BusChannel;
import org.dromara.payment.channel.mapper.BusChannelMapper;
import org.dromara.payment.channel.service.IBusChannelService;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 代理商Service业务层处理
 *
 * @author LionLi
 * @date 2024-04-10
 */
@RequiredArgsConstructor
@Service
public class BusChannelServiceImpl extends BaseService implements IBusChannelService {

    private final BusChannelMapper baseMapper;

    private final BusMerchantMapper busMerchantMapper;

    private final BusOperatorMapper busOperatorMapper;

    private final SysSydMapper sysSydMapper;

    private final IBusChannelAccountService busChannelAccountService;
    @Resource
    private ISysUnitService sysUnitService;

    @DubboReference
    private RemoteUserService remoteUserService;

    @DubboReference
    private RemoteSmsService  remoteSmsService;


    @DubboReference
    private RemoteDictService remoteDictService;

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



    public List<RemoteDictDataVo>   getDwLevel(){
        List<RemoteDictDataVo>  dictList = this.remoteDictService.selectDictDataByType("agent_level");
        int busRole = LoginHelper.getBusRole();
        if(busRole == BusRole.PLATFORM.getId()){
            return dictList;
        }else if(busRole == BusRole.OPERATOR.getId()){
            return dictList;
        }else if(busRole == BusRole.AGENT.getId()){
            Long channelId = LoginHelper.getBusId();
            BusChannelVo bco = this.baseMapper.selectVoById(channelId);
            List resultList = new ArrayList<>();
            dictList.forEach(item->{
                if(Integer.valueOf(item.getDictValue()) > bco.getDwLevel()){
                    resultList.add(item);
                }
            });
            return resultList;
        }else{
            return new ArrayList<>();
        }

    }


    /**
     * 查询代理商列表
     */
    @Override
    public TableDataInfo<BusChannelVo> queryPageList(BusChannelBo bo, PageQuery pageQuery) {
        QueryWrapper<BusChannel> lqw = Wrappers.query();
        if (!LoginHelper.isSuperAdmin()) {
            lqw.between(bo.getStartTime() != null, "t.create_time", bo.getStartTime(), bo.getEndTime());
            lqw.eq(bo.getDwType() != null, "t.dw_type", bo.getDwType());
            lqw.eq(bo.getDwLevel() != null, "t.dw_level", bo.getDwLevel());
            lqw.like(StringUtils.isNotEmpty(bo.getName()), "t.name", bo.getName());
            lqw.like(StringUtils.isNotEmpty(bo.getNo()), "t.no", bo.getNo());
            lqw.eq(bo.getVerifyStatus() != null, "t.verify_status", bo.getVerifyStatus());
            lqw.ne(StringUtils.isNotEmpty(LoginHelper.getNo()), "t.no", LoginHelper.getNo());
            if (bo.getIsProduct() != null && bo.getIsProduct() == 1) {
                lqw.eq("t.create_unit_id", LoginHelper.getBusId());
            }
        }

        lqw.orderByDesc("t.create_time");
        Page<BusChannelVo> result = baseMapper.selBusChannelLists(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }



    /**
     * 产品配置-查询代理商列表
     */
    @Override
    public TableDataInfo<BusChannelVo> queryPageListProConfig(BusChannelBo bo, PageQuery pageQuery) {
        QueryWrapper<BusChannel> lqw = Wrappers.query();
        lqw.between(bo.getStartTime() != null,"t.create_time",bo.getStartTime(),bo.getEndTime());
        lqw.eq(bo.getDwType() != null,"t.dw_type",bo.getDwType());
        lqw.eq(bo.getDwLevel() != null,"t.dw_level",bo.getDwLevel());
        lqw.like(StringUtils.isNotEmpty(bo.getName()),"t.name",bo.getName());
        lqw.like(StringUtils.isNotEmpty(bo.getNo()),"t.no",bo.getNo());
        lqw.ne(StringUtils.isNotEmpty(LoginHelper.getNo()),"t.no",LoginHelper.getNo() );
        int role = LoginHelper.getLoginUser().getBusRole();
        if(role == BusRole.AGENT.getId()){
            lqw.eq("t.p_id",LoginHelper.getBusId());
        }else if(role == BusRole.OPERATOR.getId()){
            lqw.isNull("t.p_id");
        }
        lqw.orderByDesc("t.create_time");
        Page<BusChannelVo> result = baseMapper.selBusChannelLists(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询代理商列表
     */
    @Override
    public List<BusChannelVo> queryList(BusChannelBo bo) {
        LambdaQueryWrapper<BusChannel> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<BusChannel> buildQueryWrapper(BusChannelBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BusChannel> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getNo()), BusChannel::getNo, bo.getNo());
        lqw.eq(bo.getDwType() != null, BusChannel::getDwType, bo.getDwType());
        lqw.like(StringUtils.isNotBlank(bo.getName()), BusChannel::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getNsrSbh()), BusChannel::getNsrSbh, bo.getNsrSbh());
        lqw.eq(StringUtils.isNotBlank(bo.getFr()), BusChannel::getFr, bo.getFr());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSfz()), BusChannel::getFrSfz, bo.getFrSfz());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSjh()), BusChannel::getFrSjh, bo.getFrSjh());
        lqw.eq(StringUtils.isNotBlank(bo.getWtr()), BusChannel::getWtr, bo.getWtr());
        lqw.eq(StringUtils.isNotBlank(bo.getWtrSjh()), BusChannel::getWtrSjh, bo.getWtrSjh());
        lqw.eq(StringUtils.isNotBlank(bo.getWtrSfz()), BusChannel::getWtrSfz, bo.getWtrSfz());
        lqw.eq(StringUtils.isNotBlank(bo.getWtrEmail()), BusChannel::getWtrEmail, bo.getWtrEmail());
        lqw.eq(StringUtils.isNotBlank(bo.getUnitArea()), BusChannel::getUnitArea, bo.getUnitArea());
        lqw.like(StringUtils.isNotBlank(bo.getUnitAreaName()), BusChannel::getUnitAreaName, bo.getUnitAreaName());
        lqw.eq(StringUtils.isNotBlank(bo.getAddress()), BusChannel::getAddress, bo.getAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getKhm()), BusChannel::getKhm, bo.getKhm());
        lqw.eq(StringUtils.isNotBlank(bo.getBankCard()), BusChannel::getBankCard, bo.getBankCard());
        lqw.eq(StringUtils.isNotBlank(bo.getKhd()), BusChannel::getKhd, bo.getKhd());
        lqw.eq(StringUtils.isNotBlank(bo.getKhh()), BusChannel::getKhh, bo.getKhh());
        lqw.eq(StringUtils.isNotBlank(bo.getKhhNo()), BusChannel::getKhhNo, bo.getKhhNo());
        lqw.eq(StringUtils.isNotBlank(bo.getAlipayLogonId()), BusChannel::getAlipayLogonId, bo.getAlipayLogonId());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSfzzm()), BusChannel::getFrSfzzm, bo.getFrSfzzm());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSfzfm()), BusChannel::getFrSfzfm, bo.getFrSfzfm());
        lqw.eq(StringUtils.isNotBlank(bo.getBankZm()), BusChannel::getBankZm, bo.getBankZm());
        lqw.eq(bo.getStatus() != null, BusChannel::getStatus, bo.getStatus());
        lqw.eq(bo.getPId() != null, BusChannel::getPId, bo.getPId());
        lqw.eq(StringUtils.isNotBlank(bo.getLevelCode()), BusChannel::getLevelCode, bo.getLevelCode());
        lqw.eq(bo.getVerifyStatus() != null, BusChannel::getVerifyStatus, bo.getVerifyStatus());
        lqw.eq(bo.getVerifyTime() != null, BusChannel::getVerifyTime, bo.getVerifyTime());
        lqw.eq(StringUtils.isNotBlank(bo.getVerifyBy()), BusChannel::getVerifyBy, bo.getVerifyBy());
        lqw.eq(StringUtils.isNotBlank(bo.getVerifyReason()), BusChannel::getVerifyReason, bo.getVerifyReason());
        lqw.between(bo.getStartTime() != null, BusChannel::getCreateTime, bo.getStartTime(), bo.getEndTime());
        return lqw;
    }

    public static void main(String[] args) {
        BusChannelBo bo = new BusChannelBo();

        bo.setName("代理商名称");
        bo.setDwType(1);
        bo.setDwLevel(1);
        bo.setNsrSbh("统一社会信用代码");
        bo.setFr("法人");
        bo.setFrSfz("法人身份证");
        bo.setFrSjh("法人手机号");
        bo.setWtr("经办人姓名");
        bo.setWtrSjh("经办人手机号");
        bo.setWtrEmail("经办人邮件");
        bo.setAddress("实际经营地址");
        bo.setUnitArea("区域code");
        bo.setUnitAreaName("区域名");
        bo.setKhm("开户名");
        bo.setKhh("开户行");
        bo.setKhd("开户支行");
        bo.setKhhNo("开户行行号/银联号");
        bo.setBankCard("开户账号");
        bo.setYyzz("营业执照");
        bo.setKhxkz("开户许可证");
        bo.setFrSfzzm("法人身份证正面");
        bo.setFrSfzfm("法人身份证反面");
        bo.setBankZm("银行卡正面");

        System.out.println(JSONUtil.toJsonStr(bo));

    }

    /**
     * 新增代理商
     */
    @Override
    @Transactional
    public Boolean insertByBo(BusChannelBo bo) {


        if(bo.getDwType().intValue() == 1){

            if(StringUtils.isEmpty(bo.getYyzz())){
                this.invalidationParamsException("营业执照不能为空");
            }

            if(StringUtils.isEmpty(bo.getKhxkz())){
                this.invalidationParamsException("开户许可证不能为空");
            }

        }else{
            if(StringUtils.isEmpty(bo.getBankZm())){
                this.invalidationParamsException("银行卡正面不能为空");
            }
        }


        if(StringUtils.isEmpty(bo.getNo())){
            bo.setNo(LoginHelper.getNo()+"-"+this.getAgentNo(bo));
        }


        long id = IdUtil.getSnowflakeNextId();

        BusChannel add = MapstructUtils.convert(bo, BusChannel.class);
        add.setId(id);
        add.setCreateTime(new Date());
        add.setCreateBy(LoginHelper.getUserId());
        int busRole = LoginHelper.getLoginUser().getBusRole();
        if(busRole ==  BusRole.AGENT.getId()){
            add.setPId(LoginHelper.getBusId());
        }
        if(StringUtils.isNotEmpty(LoginHelper.getNo())){
            String[] pCodes = LoginHelper.getNo().split("-");
            add.setOperatorNo(pCodes[0]);
        }
        add.setVerifyStatus(0L);
        add.setStatus(1L);
        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.getAgentNo(bo));
                return this.insertByBo(bo);
            }
        }

        if (flag) {
            bo.setId(add.getId());
        }

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

        return flag;
    }

    private String getAgentNo(BusChannelBo bo) {
        LoginUser user = LoginHelper.getLoginUser();
        int busRole = user.getBusRole().intValue();
        String rno = RandomUtil.randomString("0123456789",5);
        if(bo.getDwLevel() != null){
            int level = bo.getDwLevel();
            if(level == 1){
                return "B"+rno;
            }else if(level == 2){
                return "C"+rno;
            }else if(level == 3){
                return "D"+rno;
            }
        }
        return "CBD"+rno;

    }

    /**
     * 修改代理商
     */
    @Override
    public Boolean updateByBo(BusChannelBo bo) {

        BusChannelVo channelVo = this.queryById(bo.getId());

        if(channelVo == null){
            this.invalidationParamsException("代理商不存在!");
        }

        if(channelVo.getVerifyStatus() == null ||  channelVo.getVerifyStatus().equals(2L)){
            this.invalidationParamsException("代理商信息不能修改!");
        }
        bo.setVerifyStatus(0L);
        BusChannel update = MapstructUtils.convert(bo, BusChannel.class);
        validEntityBeforeSave(update);
        update.setUpdateBy(LoginHelper.getUserId());
        update.setUpdateTime(new Date());
        update.setNo(null);
        update.setOperatorNo(null);
        return baseMapper.updateById(update) > 0;
    }

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

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

    @Override
    public BaseCompInfo getAgentInfo() {
        LoginUser user = LoginHelper.getLoginUser();
        Integer busRole = user.getBusRole();

        BaseCompInfo info = new BaseCompInfo();
        if (busRole == BusRole.AGENT.getId()) {
            BusChannelBo bo = new BusChannelBo();
            bo.setNo(LoginHelper.getNo());
            BusChannelVo result =  this.baseMapper.selectVoOne(this.buildQueryWrapper(bo));
            if(result != null){
                info.setName(result.getName());
                info.setAddress(result.getAddress());
                info.setXyCode(result.getNsrSbh());
                info.setArea(result.getUnitAreaName());
            }
        }else if(busRole == BusRole.MERCHANT.getId()){
            BusMerchantBo bo = new BusMerchantBo();
            bo.setNo(LoginHelper.getNo());
            LambdaQueryWrapper<BusMerchant> lqw = Wrappers.lambdaQuery();
            lqw.eq(StringUtils.isNotBlank(bo.getNo()), BusMerchant::getNo, bo.getNo());
            BusMerchantVo result= this.busMerchantMapper.selectVoOne(lqw);
            if(result != null){
                info.setName(result.getName());
                info.setAddress(result.getAddress());
                info.setXyCode(result.getNsrSbh());
                info.setArea(result.getUnitAreaName());
            }
        }else if(busRole == BusRole.OPERATOR.getId()){
            BusOperatorBo bo = new BusOperatorBo();
            bo.setNo(LoginHelper.getNo());
            LambdaQueryWrapper<BusOperator> lqw = Wrappers.lambdaQuery();
            lqw.eq(StringUtils.isNotBlank(bo.getNo()), BusOperator::getNo, bo.getNo());
            BusOperatorVo result = this.busOperatorMapper.selectVoOne(lqw);
            if(result != null){
                info.setName(result.getName());
                info.setAddress(result.getAddress());
                info.setXyCode(result.getNsrSbh());
                info.setArea(result.getUnitAreaName());
            }
        }else if(busRole == BusRole.SERVICE.getId()){

            SysSydVo sysSysVO = this.sysSydMapper.selectVoById(LoginHelper.getBusId());
            if(sysSysVO != null){
                info.setName(sysSysVO.getGsmc());
                info.setAddress(sysSysVO.getAddress());
                info.setXyCode(sysSysVO.getNsrSbh());
                info.setArea(sysSysVO.getUnitAreaName());
            }
        }
        return info;
    }

    @Override
    public boolean checkChannel(Long chId, Long checkType, String reason,String domain) {

        if(chId == null){
            this.invalidationParamsException("代理商ID不能为空");
        }

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

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

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

        BusChannelVo  bcv = this.baseMapper.selectVoById(chId);

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

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

            BusChannelAccountBo bcab = new BusChannelAccountBo();
            bcab.setChannelId(chId);
            bcab.setIsDefault(1);
            bcab.setAddTime(new Date());
            bcab.setCreateTime(new Date());
            bcab.setAccId(0L);
            bcab.setSydId(0L);
            busChannelAccountService.insertByBo(bcab);
            RemoteUserBo  remoteUserBo = new RemoteUserBo();
            remoteUserBo.setBusId(chId);
            remoteUserBo.setBusNo(bcv.getNo());
            remoteUserBo.setRoleId(BusRole.AGENT.getId());
            remoteUserBo.setRoleName(BusRole.AGENT.getName());
            remoteUserBo.setRoleDataRange(1);
            remoteUserBo.setNickName(bcv.getName());
            remoteUserBo.setCreateTime(new Date());
            remoteUserBo.setPhonenumber(bcv.getWtrSjh());
            remoteUserBo.setCreateBy(LoginHelper.getUserId());
            remoteUserBo.setUserName("B"+StringUtils.randmNumber(5));
            String pwd = StringUtils.randmNumber(6);
            remoteUserBo.setPassword(BCrypt.hashpw(pwd));
            this.addBusUser(remoteUserBo);
            LinkedHashMap smsMap = new LinkedHashMap();
            smsMap.put("type",BusRole.AGENT.getName());
            smsMap.put("name",remoteUserBo.getUserName());
            smsMap.put("pwd",pwd);
            this.remoteSmsService.send(domain,remoteUserBo.getPhonenumber(),SmsType.UNIT_OPEN,smsMap);
        }

        BusChannel  busChannel =   new BusChannel();

        busChannel.setVerifyStatus(checkType);
        busChannel.setVerifyReason(reason);
        busChannel.setVerifyTime(new Date());
        busChannel.setVerifyBy(LoginHelper.getUserId()+"");
        busChannel.setId(chId);
        this.baseMapper.updateById(busChannel);

        return true;
    }

    private void addBusUser(RemoteUserBo remoteUserBo) {
        int result = this.remoteUserService.insertBusUser(remoteUserBo);
        if(result  == -1){
            remoteUserBo.setUserName("B"+StringUtils.randmNumber(5));
            this.addBusUser(remoteUserBo);
        }
    }

}
