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

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.enums.BusRole;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.BaseService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StreamUtils;
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.payment.channel.domain.BusChannelProduct;
import org.dromara.payment.channel.mapper.BusChannelProductMapper;
import org.dromara.payment.merchant.domain.BusMerchantProduct;
import org.dromara.payment.merchant.mapper.BusMerchantProductMapper;
import org.dromara.payment.operator.domain.BusOperator;
import org.dromara.payment.operator.domain.BusOperatorProduct;
import org.dromara.payment.operator.domain.ReProductInvoice;
import org.dromara.payment.operator.domain.bo.ReProductInvoiceBo;
import org.dromara.payment.operator.mapper.BusOperatorProductMapper;
import org.dromara.payment.operator.mapper.ReProductInvoiceMapper;
import org.dromara.payment.sys.domain.SysSydProduct;
import org.dromara.payment.sys.domain.vo.SysSydProductVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.dromara.payment.sys.domain.bo.SysSydProductBo;
import org.dromara.payment.sys.mapper.SysSydProductMapper;
import org.dromara.payment.sys.service.ISysSydProductService;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 服务商产品Service业务层处理
 *
 * @author LionLi
 * @date 2024-03-26
 */
@RequiredArgsConstructor
@Service
public class SysSydProductServiceImpl  extends BaseService implements ISysSydProductService {

    private final SysSydProductMapper baseMapper;

    private final ReProductInvoiceMapper reProductInvoiceMapper;

    @Autowired
    private BusOperatorProductMapper busOperatorProductMapper;

    @Autowired
    private BusChannelProductMapper busChannelProductMapper;

    @Autowired
    private BusMerchantProductMapper busMerchantProductMapper;

    /**
     * 查询服务商产品
     */
    @Override
    public SysSydProductVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询服务商产品列表
     */
    @Override
    public TableDataInfo<SysSydProductVo> queryPageList(SysSydProductBo bo, PageQuery pageQuery) {
        Page<SysSydProductVo> result = baseMapper.queryPageList(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    /**
     * 查询服务商产品列表
     */
    @Override
    public List<SysSydProductVo> queryList(SysSydProductBo bo) {
        return baseMapper.queryList(bo);
    }

    /**
     * 新增服务商产品
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(SysSydProductBo bo) {
        SysSydProduct add = MapstructUtils.convert(bo, SysSydProduct.class);
        validEntityBeforeSave(add);
        add.setNo(genNo(0,10));
        if(bo.getInvoiceItemList() != null){
            bo.setInvoiceItems(StreamUtils.join(bo.getInvoiceItemList(),ReProductInvoiceBo::getInvoiceTypeName));
        }
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            if(bo.getInvoiceItemList() != null && bo.getInvoiceItemList().size() > 0){
                List<ReProductInvoice> invoiceItems = new ArrayList<>();
                for (ReProductInvoiceBo ibo:bo.getInvoiceItemList()) {
                    ReProductInvoice obj = MapstructUtils.convert(ibo,ReProductInvoice.class);
                    obj.setProType(bo.getBusType());
                    obj.setProNo(bo.getNo());
                    obj.setProId(add.getId());
                    obj.setBusId(bo.getSydId());
                    obj.setBusType(BusRole.SERVICE.getId());
                    invoiceItems.add(obj);
                }
                reProductInvoiceMapper.insertBatch(invoiceItems);
            }
        }
        return flag;
    }

    /**
     * 生成产品编号
     * @param retry 当前重试次数
     * @param maxRetry 最大重试次数
     * @return
     */
    public String genNo(int retry,int maxRetry){
        String no = "P"+ RandomUtil.randomNumbers(10);
        QueryWrapper<SysSydProduct> lqw = Wrappers.query();
        lqw.eq("no",no);
        SysSydProduct 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(SysSydProductBo bo) {
        SysSydProduct update = MapstructUtils.convert(bo, SysSydProduct.class);
        validEntityBeforeSave(update);
        SysSydProductVo selObj = this.baseMapper.selectVoById(bo.getId());
        if(selObj == null){
            this.invalidationParamsException("参数无效，无此产品");
        }

        BigDecimal minBigDecimal = this.baseMapper.selMinServiceChargeByproId(bo.getId());
        if(minBigDecimal != null ){

            if(minBigDecimal.compareTo(bo.getSetingServiceCharge()) < 0){
                this.invalidationParamsException("产品费率不能大于"+minBigDecimal);
            }
        }

        reProductInvoiceMapper.delete(new LambdaQueryWrapper<ReProductInvoice>().eq(ReProductInvoice::getBusId,bo.getSydId()).eq(ReProductInvoice::getBusType,BusRole.SERVICE.getId()));
        if(bo.getInvoiceItemList() != null && bo.getInvoiceItemList().size() > 0){
            bo.setInvoiceItems(StreamUtils.join(bo.getInvoiceItemList(),ReProductInvoiceBo::getInvoiceTypeName));
            List<ReProductInvoice> invoiceItems = new ArrayList<>();
            for (ReProductInvoiceBo ibo:bo.getInvoiceItemList()) {
                ReProductInvoice obj = MapstructUtils.convert(ibo,ReProductInvoice.class);
                obj.setProType(bo.getBusType());
                obj.setProNo(bo.getNo());
                obj.setProId(bo.getId());
                obj.setBusId(bo.getSydId());
                obj.setBusType(BusRole.SERVICE.getId());
                invoiceItems.add(obj);
            }
            reProductInvoiceMapper.insertBatch(invoiceItems);
        }else{
            bo.setInvoiceItems("");
        }

        if(selObj.getInvoiceItems() == null || !selObj.getInvoiceItems().equals(bo.getInvoiceItems())){

            this.busOperatorProductMapper.update(null,new LambdaUpdateWrapper<BusOperatorProduct>()
                .set(BusOperatorProduct::getInvoiceItems, bo.getInvoiceItems())
                .eq(BusOperatorProduct::getProId, bo.getId()));
            this.busChannelProductMapper.update(null,new LambdaUpdateWrapper<BusChannelProduct>()
                .set(BusChannelProduct::getInvoiceItems, bo.getInvoiceItems())
                .eq(BusChannelProduct::getProId, bo.getId()));
            this.busMerchantProductMapper.update(null,new LambdaUpdateWrapper<BusMerchantProduct>()
                .set(BusMerchantProduct::getInvoiceItems, bo.getInvoiceItems())
                .eq(BusMerchantProduct::getProId, bo.getId()));
        }

        return baseMapper.updateById(update) > 0;
    }

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

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

    @Override
    public String upDown(Long id, Integer status) {
        if(id == null || status == null){
            this.invalidationParamsException("参数无效");
        }
        this.baseMapper.update(null,new LambdaUpdateWrapper<SysSydProduct>().set(SysSydProduct::getProStatus,status).eq(SysSydProduct::getId,id));
        return "true";
    }
}
