package org.dromara.zjk.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.zjk.domain.ZjkExpert;
import org.dromara.zjk.domain.ZjkExpertMoneyConfig;
import org.dromara.zjk.domain.ZjkExpertMoneyInfo;
import org.dromara.zjk.domain.ZjkProduct;
import org.dromara.zjk.domain.bo.ZjkExpertMoneyInfoBo;
import org.dromara.zjk.domain.vo.ZjkExpertMoneyInfoVO;
import org.dromara.zjk.domain.vo.ZjkExpertVo;
import org.dromara.zjk.enums.MoneyFlagStatusEnum;
import org.dromara.zjk.enums.MoneySettlementStatusEnum;
import org.dromara.zjk.mapper.ZjkExpertMapper;
import org.dromara.zjk.mapper.ZjkExpertMoneyConfigMapper;
import org.dromara.zjk.mapper.ZjkExpertMoneyInfoMapper;
import org.dromara.zjk.mapper.ZjkProductMapper;
import org.dromara.zjk.service.ZjkExpertMoneyInfoService;
import org.dromara.zjk.utils.NumberGenerator;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * @author EDY
 * @description 针对表【zjk_expert_money_info(专家费用管理表)】的数据库操作Service实现
 * @createDate 2024-11-28 18:36:35
 */
@Service
public class ZjkExpertMoneyInfoServiceImpl extends ServiceImpl<ZjkExpertMoneyInfoMapper, ZjkExpertMoneyInfo>
    implements ZjkExpertMoneyInfoService {

    @Resource
    private ZjkExpertMapper zjkExpertMapper;
    @Resource
    private ZjkProductMapper zjkProductMapper;

    @Resource
    private ZjkExpertMoneyConfigMapper zjkExpertMoneyConfigMapper;

    @Override
    public ZjkExpertMoneyInfo queryById(Long moneyId) {
        return baseMapper.selectById(moneyId);
    }

    @Override
    public TableDataInfo<ZjkExpertMoneyInfoVO> queryPageList(ZjkExpertMoneyInfoBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ZjkExpertMoneyInfo> wrapper = buildQueryWrapper(bo);
        Page<ZjkExpertMoneyInfoVO> result = baseMapper.selectMoneyInfoList(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    @Override
    public boolean updateMoneyInfo(ZjkExpertMoneyInfoBo bo) {
        List<ZjkExpertMoneyInfo> zjkExpertMoneyInfoList = baseMapper.selectBatchIds(bo.getIds());
        if (CollectionUtil.isEmpty(zjkExpertMoneyInfoList)) {
            throw new ServiceException("无效id");
        }
        for (ZjkExpertMoneyInfo zjkExpertMoneyInfo : zjkExpertMoneyInfoList) {
            zjkExpertMoneyInfo.setStatus(MoneySettlementStatusEnum.NO_SETTLEMENT.getCode());
            zjkExpertMoneyInfo.setSettlementDate(new Date());
            zjkExpertMoneyInfo.setSettlementSn(NumberGenerator.generateUniqueNumber("stn", 3));
        }
        return baseMapper.updateBatchById(zjkExpertMoneyInfoList);
    }

    @Override
    @Transactional
    public boolean updateMoneyInfoPay(ZjkExpertMoneyInfoBo bo) {
        Long moneyId = bo.getMoneyId();
        if (null == moneyId) {
            throw new ServiceException("id不能为空");
        }
        ZjkExpertMoneyInfo zjkExpertMoneyInfo = baseMapper.selectById(moneyId);
        if (null == zjkExpertMoneyInfo) {
            throw new ServiceException("无效id");
        }
        String status = zjkExpertMoneyInfo.getStatus();
        if (status.equals(MoneySettlementStatusEnum.SETTLEMENT.getCode())) {
            throw new ServiceException("未结算 无法支付");
        }
        BigDecimal expertNoPayMoney = BigDecimal.ZERO;
        String expertMoneyFlag = zjkExpertMoneyInfo.getExpertMoneyFlag();
        if (MoneyFlagStatusEnum.Paid.getCode().equals(expertMoneyFlag)) {
            throw new ServiceException("已支付 ，无效重复支付");
        }
        zjkExpertMoneyInfo.setExpertMoneyFlag(MoneyFlagStatusEnum.Paid.getCode());
        BigDecimal expertPayMoney = zjkExpertMoneyInfo.getExpertPayMoney();
        BigDecimal expertMoney = zjkExpertMoneyInfo.getExpertMoney();
        int compareTo = 0;
        if (MoneyFlagStatusEnum.PART_PAID.getCode().equals(expertMoneyFlag)) {
            BigDecimal add = expertPayMoney.add(bo.getMoney());
            compareTo = add.compareTo(expertMoney);
            expertNoPayMoney = expertMoney.subtract(add);
        } else {
            BigDecimal money = bo.getMoney();
            compareTo = money.compareTo(zjkExpertMoneyInfo.getExpertMoney());
            expertNoPayMoney = expertMoney.subtract(money);
        }
        if (compareTo > 0) {
            throw new ServiceException("支付金额大于专家费用");
        } else if (compareTo < 0) {
            zjkExpertMoneyInfo.setExpertMoneyFlag(MoneyFlagStatusEnum.PART_PAID.getCode());
        }
        zjkExpertMoneyInfo.setPaySn(NumberGenerator.generateUniqueNumber("pay", 3));
        zjkExpertMoneyInfo.setExpertMoneyFile(bo.getExpertMoneyFile());
        zjkExpertMoneyInfo.setExpertNoPayMoney(expertNoPayMoney);
        BigDecimal payMoney = expertMoney.subtract(expertNoPayMoney);
        zjkExpertMoneyInfo.setExpertPayMoney(payMoney);
        zjkExpertMoneyInfo.setPayMethod(bo.getPayMethod());
        return baseMapper.updateById(zjkExpertMoneyInfo) > 0;
    }


    /**
     * 查询符合条件的【请填写功能名称】列表
     *
     * @param bo 查询条件
     * @return 【请填写功能名称】列表
     */
    @Override
    public List<ZjkExpertMoneyInfoVO> queryList(ZjkExpertMoneyInfoBo bo) {
        LambdaQueryWrapper<ZjkExpertMoneyInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ZjkExpertMoneyInfo> buildQueryWrapper(ZjkExpertMoneyInfoBo bo) {
        LambdaQueryWrapper<ZjkExpertMoneyInfo> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getMoneyId() != null, ZjkExpertMoneyInfo::getMoneyId, bo.getMoneyId());
        lqw.eq(StringUtils.isNotBlank(bo.getExpertType()), ZjkExpertMoneyInfo::getExpertType, bo.getExpertType());
        lqw.eq(StringUtils.isNotBlank(bo.getExpertId()), ZjkExpertMoneyInfo::getExpertId, bo.getExpertId());
        lqw.eq(bo.getExpertMoney() != null, ZjkExpertMoneyInfo::getExpertMoney, bo.getExpertMoney());
        lqw.like(StringUtils.isNotBlank(bo.getExpertName()), ZjkExpertMoneyInfo::getExpertName, bo.getExpertName());
        lqw.eq(StringUtils.isNotBlank(bo.getExpertUnit()), ZjkExpertMoneyInfo::getExpertUnit, bo.getExpertUnit());
        lqw.eq(bo.getAssignId() != null, ZjkExpertMoneyInfo::getAssignId, bo.getAssignId());
        lqw.eq(StringUtils.isNotBlank(bo.getExpertMoneyFlag()), ZjkExpertMoneyInfo::getExpertMoneyFlag, bo.getExpertMoneyFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getExpertMoneyFile()), ZjkExpertMoneyInfo::getExpertMoneyFile, bo.getExpertMoneyFile());
        lqw.eq(StringUtils.isNotBlank(bo.getProductId()), ZjkExpertMoneyInfo::getProductId, bo.getProductId());
        lqw.eq(StringUtils.isNotBlank(bo.getProductType()), ZjkExpertMoneyInfo::getProductType, bo.getProductType());
        lqw.like(StringUtils.isNotBlank(bo.getProductName()), ZjkExpertMoneyInfo::getProductName, bo.getProductName());
        lqw.eq(bo.getExpertNoPayMoney() != null, ZjkExpertMoneyInfo::getExpertNoPayMoney, bo.getExpertNoPayMoney());
        lqw.eq(bo.getExpertPayMoney() != null, ZjkExpertMoneyInfo::getExpertPayMoney, bo.getExpertPayMoney());
        lqw.eq(bo.getReviewDate() != null, ZjkExpertMoneyInfo::getReviewDate, bo.getReviewDate());
        lqw.eq(bo.getSettlementDate() != null, ZjkExpertMoneyInfo::getSettlementDate, bo.getSettlementDate());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ZjkExpertMoneyInfo::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getSettlementSn()), ZjkExpertMoneyInfo::getSettlementSn, bo.getSettlementSn());
        lqw.eq(StringUtils.isNotBlank(bo.getPaySn()), ZjkExpertMoneyInfo::getPaySn, bo.getPaySn());
        lqw.eq(StringUtils.isNotBlank(bo.getExpertIdcard()), ZjkExpertMoneyInfo::getExpertIdcard, bo.getExpertIdcard());
        lqw.eq(StringUtils.isNotBlank(bo.getExpertContact()), ZjkExpertMoneyInfo::getExpertContact, bo.getExpertContact());
        lqw.eq(StringUtils.isNotBlank(bo.getReviewCount()), ZjkExpertMoneyInfo::getReviewCount, bo.getReviewCount());
        lqw.eq(StringUtils.isNotBlank(bo.getMoneyCycle()), ZjkExpertMoneyInfo::getMoneyCycle, bo.getMoneyCycle());
        lqw.eq(StringUtils.isNotBlank(bo.getPayMethod()), ZjkExpertMoneyInfo::getPayMethod, bo.getPayMethod());
        return lqw;
    }

    /**
     * 新增【请填写功能名称】
     *
     * @param bo 【请填写功能名称】
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(ZjkExpertMoneyInfoBo bo) {
        //校验是否已有同样的结算单已经录入了
        LambdaQueryWrapper<ZjkExpertMoneyInfo> wp = Wrappers.lambdaQuery();
        wp
            .eq(ZjkExpertMoneyInfo::getExpertId, bo.getExpertId())
            .eq(ZjkExpertMoneyInfo::getProductId, bo.getProductId())
            .eq(ZjkExpertMoneyInfo::getProductType, bo.getProductType());
        List<ZjkExpertMoneyInfo> zjkExpertMoneyInfos = baseMapper.selectList(wp);
        if(!CollectionUtil.isEmpty(zjkExpertMoneyInfos)){
            throw new ServiceException("该项目阶段下已经有专家录入了结算单不可重复录入！");
        }

        ZjkExpertMoneyInfo add = MapstructUtils.convert(bo, ZjkExpertMoneyInfo.class);
        add.setPaySn(NumberGenerator.generateUniqueNumber("fee", 8));

        assert add != null;
        if(add.getStatus().equals(MoneySettlementStatusEnum.NO_SETTLEMENT.getCode())){
            add.setSettlementSn(NumberGenerator.generateUniqueNumber("stn",8));
            add.setSettlementDate(new Date());
        }
        String expertType = bo.getExpertType();
        LambdaQueryWrapper<ZjkExpertMoneyConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ZjkExpertMoneyConfig::getMoneyType, expertType);
        wrapper.last("limit 1");
        ZjkExpertMoneyConfig zjkExpertMoneyConfig = zjkExpertMoneyConfigMapper.selectOne(wrapper);
        BigDecimal moneyNumber = zjkExpertMoneyConfig.getMoneyNumber();
        add.setExpertMoney(moneyNumber);
        add.setExpertTypeMoneyFee(moneyNumber);
        add.setExpertNoPayMoney(moneyNumber);
        add.setMoneyCycle(zjkExpertMoneyConfig.getMoneyCycle());
        add.setExpertPayMoney(BigDecimal.ZERO);
        add.setExpertMoneyFlag(MoneyFlagStatusEnum.NO_PAID.getCode());

        String expertId = bo.getExpertId();
        ZjkExpert zjkExpert = zjkExpertMapper.selectById(expertId);
        if (zjkExpert == null) {
            throw new ServiceException("无效专家id");
        }
        add.setExpertName(zjkExpert.getExpertName());
        add.setExpertContact(zjkExpert.getContact());
        add.setExpertIdcard(zjkExpert.getIdCard());
        add.setExpertUnit(zjkExpert.getWorkUnit());

        String productId = bo.getProductId();
        ZjkProduct zjkProduct = zjkProductMapper.selectById(productId);
        if (zjkProduct == null) {
            throw new ServiceException("无效项目id");
        }
        add.setProductName(zjkProduct.getProductName());

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setMoneyId(add.getMoneyId());
        }
        return flag;
    }

    /**
     * 修改【请填写功能名称】
     *
     * @param bo 【请填写功能名称】
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(ZjkExpertMoneyInfoBo bo) {

        ZjkExpertMoneyInfo update = MapstructUtils.convert(bo, ZjkExpertMoneyInfo.class);

        assert update != null;
        if(update.getStatus().equals(MoneySettlementStatusEnum.NO_SETTLEMENT.getCode())){
            update.setSettlementSn(NumberGenerator.generateUniqueNumber("stn",8));
            update.setSettlementDate(new Date());
        }
        String expertType = bo.getExpertType();
        LambdaQueryWrapper<ZjkExpertMoneyConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ZjkExpertMoneyConfig::getMoneyType, expertType);
        wrapper.last("limit 1");
        ZjkExpertMoneyConfig zjkExpertMoneyConfig = zjkExpertMoneyConfigMapper.selectOne(wrapper);
        BigDecimal moneyNumber = zjkExpertMoneyConfig.getMoneyNumber();
        update.setExpertMoney(moneyNumber);
        update.setExpertTypeMoneyFee(moneyNumber);
        update.setExpertNoPayMoney(moneyNumber);
        update.setMoneyCycle(zjkExpertMoneyConfig.getMoneyCycle());
        update.setExpertPayMoney(BigDecimal.ZERO);
        update.setExpertMoneyFlag(MoneyFlagStatusEnum.NO_PAID.getCode());

        String expertId = bo.getExpertId();
        ZjkExpert zjkExpert = zjkExpertMapper.selectById(expertId);
        if (zjkExpert == null) {
            throw new ServiceException("无效专家id");
        }
        update.setExpertName(zjkExpert.getExpertName());
        update.setExpertContact(zjkExpert.getContact());
        update.setExpertIdcard(zjkExpert.getIdCard());
        update.setExpertUnit(zjkExpert.getWorkUnit());

        String productId = bo.getProductId();
        ZjkProduct zjkProduct = zjkProductMapper.selectById(productId);
        if (zjkProduct == null) {
            throw new ServiceException("无效项目id");
        }
        update.setProductName(zjkProduct.getProductName());

        return baseMapper.updateById(update) > 0;
    }

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

    /**
     * 校验并批量删除【请填写功能名称】信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public List<ZjkExpertMoneyInfo> getJsList(Long productId, Integer reviewSn, String expertId) {
        QueryWrapper<ZjkExpertMoneyInfo> wq = new QueryWrapper<>();
        wq.lambda().eq(ZjkExpertMoneyInfo::getProductId, productId).eq(ZjkExpertMoneyInfo::getProductType, reviewSn)
            .eq(ZjkExpertMoneyInfo::getStatus, MoneySettlementStatusEnum.NO_SETTLEMENT.getCode()).eq(ZjkExpertMoneyInfo::getExpertId, expertId);
        List<ZjkExpertMoneyInfo> res = baseMapper.selectList(wq);
        return res;
    }

    @Override
    public List<ZjkExpertVo> getExpertList(Long productId, Integer reviewSn) {
        List<ZjkExpertVo>  res = baseMapper.getExpertList(productId, reviewSn);
        return res;
    }
}




