package org.dromara.payment.operator.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.update.LambdaUpdateWrapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.enums.BusRole;
import org.dromara.common.core.enums.SmsType;
import org.dromara.common.core.exception.ServiceException;
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.sys.domain.SysSyd;
import org.dromara.payment.sys.domain.SysUnit;
import org.dromara.payment.sys.mapper.SysUnitMapper;
import org.dromara.resource.api.RemoteSmsService;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.bo.RemoteUserBo;
import org.springframework.stereotype.Service;
import org.dromara.payment.operator.domain.bo.BusOperatorBo;
import org.dromara.payment.operator.domain.vo.BusOperatorVo;
import org.dromara.payment.operator.domain.BusOperator;
import org.dromara.payment.operator.mapper.BusOperatorMapper;
import org.dromara.payment.operator.service.IBusOperatorService;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 运营商Service业务层处理
 *
 * @author LionLi
 * @date 2024-03-28
 */
@RequiredArgsConstructor
@Service
public class BusOperatorServiceImpl implements IBusOperatorService {

    private final BusOperatorMapper baseMapper;

    private final SysUnitMapper sysUnitMapper;

    @DubboReference
    private RemoteUserService remoteUserService;


    @DubboReference
    private RemoteSmsService remoteSmsService;

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

    /**
     * 查询运营商列表
     */
    @Override
    public TableDataInfo<BusOperatorVo> queryPageList(BusOperatorBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<BusOperator> lqw = buildQueryWrapper(bo);
        Page<BusOperatorVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询运营商列表
     */
    @Override
    public List<BusOperatorVo> queryList(BusOperatorBo bo) {
        LambdaQueryWrapper<BusOperator> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<BusOperator> buildQueryWrapper(BusOperatorBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<BusOperator> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getNo()), BusOperator::getNo, bo.getNo());
        lqw.eq(bo.getDwType() != null, BusOperator::getDwType, bo.getDwType());
        lqw.like(StringUtils.isNotBlank(bo.getName()), BusOperator::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getNsrSbh()), BusOperator::getNsrSbh, bo.getNsrSbh());
        lqw.eq(StringUtils.isNotBlank(bo.getFr()), BusOperator::getFr, bo.getFr());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSfz()), BusOperator::getFrSfz, bo.getFrSfz());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSjh()), BusOperator::getFrSjh, bo.getFrSjh());
        lqw.eq(StringUtils.isNotBlank(bo.getWtr()), BusOperator::getWtr, bo.getWtr());
        lqw.eq(StringUtils.isNotBlank(bo.getWtrSjh()), BusOperator::getWtrSjh, bo.getWtrSjh());
        lqw.eq(StringUtils.isNotBlank(bo.getWtrSfz()), BusOperator::getWtrSfz, bo.getWtrSfz());
        lqw.eq(StringUtils.isNotBlank(bo.getWtrEmail()), BusOperator::getWtrEmail, bo.getWtrEmail());
        lqw.eq(StringUtils.isNotBlank(bo.getUnitArea()), BusOperator::getUnitArea, bo.getUnitArea());
        lqw.like(StringUtils.isNotBlank(bo.getUnitAreaName()), BusOperator::getUnitAreaName, bo.getUnitAreaName());
        lqw.eq(StringUtils.isNotBlank(bo.getAddress()), BusOperator::getAddress, bo.getAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getKhm()), BusOperator::getKhm, bo.getKhm());
        lqw.eq(StringUtils.isNotBlank(bo.getBankCard()), BusOperator::getBankCard, bo.getBankCard());
        lqw.eq(StringUtils.isNotBlank(bo.getKhd()), BusOperator::getKhd, bo.getKhd());
        lqw.eq(StringUtils.isNotBlank(bo.getKhh()), BusOperator::getKhh, bo.getKhh());
        lqw.eq(StringUtils.isNotBlank(bo.getKhhNo()), BusOperator::getKhhNo, bo.getKhhNo());
        lqw.eq(StringUtils.isNotBlank(bo.getAlipayLogonId()), BusOperator::getAlipayLogonId, bo.getAlipayLogonId());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSfzzm()), BusOperator::getFrSfzzm, bo.getFrSfzzm());
        lqw.eq(StringUtils.isNotBlank(bo.getFrSfzfm()), BusOperator::getFrSfzfm, bo.getFrSfzfm());
        lqw.eq(StringUtils.isNotBlank(bo.getBankZm()), BusOperator::getBankZm, bo.getBankZm());
        lqw.eq(StringUtils.isNotBlank(bo.getPayPassword()), BusOperator::getPayPassword, bo.getPayPassword());
        lqw.eq(bo.getPassErrorNum() != null, BusOperator::getPassErrorNum, bo.getPassErrorNum());
        lqw.eq(bo.getPassFrozenTime() != null, BusOperator::getPassFrozenTime, bo.getPassFrozenTime());
        lqw.eq(bo.getStatus() != null, BusOperator::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoceHeader()), BusOperator::getInvoceHeader, bo.getInvoceHeader());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoceCreditCode()), BusOperator::getInvoceCreditCode, bo.getInvoceCreditCode());
        lqw.like(StringUtils.isNotBlank(bo.getInvoceBankName()), BusOperator::getInvoceBankName, bo.getInvoceBankName());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoceBankCard()), BusOperator::getInvoceBankCard, bo.getInvoceBankCard());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoceAddress()), BusOperator::getInvoceAddress, bo.getInvoceAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getInvoceDwdh()), BusOperator::getInvoceDwdh, bo.getInvoceDwdh());
        lqw.orderByDesc(BusOperator::getCreateTime);
        return lqw;
    }

    /**
     * 新增运营商
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(BusOperatorBo bo) {
        BusOperator add = MapstructUtils.convert(bo, BusOperator.class);
        validEntityBeforeSave(add);
        String no = genNo(0,10);
        SysUnit sysUnit = new SysUnit();
        sysUnit.setId(IdUtil.getSnowflakeNextId());
        sysUnit.setNo(no);
        sysUnit.setUnitType(BusRole.OPERATOR.getId());
        sysUnit.setName(add.getName());
        sysUnit.setCustNo(no.substring(1));
        sysUnitMapper.insert(sysUnit);
        add.setId(sysUnit.getId());
        add.setNo(no);
        add.setCreateBy(bo.getCreateBy());
        add.setCreateTime(new Date());
        add.setUpdateBy(bo.getCreateBy());
        add.setUpdateTime(bo.getCreateTime());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }

        RemoteUserBo remoteUserBo = new RemoteUserBo();
        remoteUserBo.setBusId(bo.getId());
        remoteUserBo.setBusNo(add.getNo());
        remoteUserBo.setRoleId(BusRole.OPERATOR.getId());
        remoteUserBo.setRoleName(BusRole.OPERATOR.getName());
        remoteUserBo.setRoleDataRange(1);
        remoteUserBo.setNickName(bo.getName());
        remoteUserBo.setCreateTime(new Date());
        remoteUserBo.setPhonenumber(bo.getWtrSjh());
        remoteUserBo.setCreateBy(LoginHelper.getUserId());
        remoteUserBo.setUserName("A"+StringUtils.randmNumber(5));
        String pwd = StringUtils.randmNumber(6);
        remoteUserBo.setPassword(BCrypt.hashpw(pwd));
        this.addUser(remoteUserBo);



        LinkedHashMap smsMap = new LinkedHashMap();
        smsMap.put("type",BusRole.OPERATOR.getName());
        smsMap.put("name",remoteUserBo.getUserName());
        smsMap.put("pwd",pwd);
        this.remoteSmsService.send(bo.getDomain(),remoteUserBo.getPhonenumber(), SmsType.UNIT_OPEN,smsMap);
        return flag;
    }

    private void addUser(RemoteUserBo remoteUserBo) {

        int result = this.remoteUserService.insertBusUser(remoteUserBo);
        if(result  == -1){
            remoteUserBo.setUserName("A"+StringUtils.randmNumber(5));
            this.addUser(remoteUserBo);
        }
    }

    /**
     * 生成运营商编号
     * @param retry 当前重试次数
     * @param maxRetry 最大重试次数
     * @return
     */
    public String genNo(int retry,int maxRetry){
        String no = "A"+ RandomUtil.randomNumbers(5);
        LambdaQueryWrapper<BusOperator> lqw = Wrappers.lambdaQuery();
        lqw.eq(BusOperator::getNo,no);
        BusOperator exists = baseMapper.selectOne(lqw);
        if(exists != null){
            if(retry > maxRetry){
                throw new ServiceException("运营商编号生成出错");
            }else {
                no = genNo(retry + 1,maxRetry);
            }
        }
        return no;
    }

    /**
     * 修改运营商
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(BusOperatorBo bo) {
        BusOperator update = MapstructUtils.convert(bo, BusOperator.class);
        validEntityBeforeSave(update);
        update.setUpdateBy(bo.getUpdateBy());
        update.setUpdateTime(new Date());
        sysUnitMapper.update(new LambdaUpdateWrapper<SysUnit>()
            .set(SysUnit::getName, update.getName())
            .eq(SysUnit::getId, update.getId()));
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(BusOperator entity){
        //TODO 做一些数据校验,如唯一约束
        LambdaQueryWrapper<BusOperator> lqw = Wrappers.lambdaQuery();
        lqw.eq(BusOperator::getName,entity.getName());
        BusOperator exists = baseMapper.selectOne(lqw);
        if(exists != null && (entity.getId() == null || entity.getId() != exists.getId())){
            throw new ServiceException("运营商已存在");
        }
    }

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