package org.dromara.zjk.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.domain.R;
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.zjk.domain.ZjkCreditUser;
import org.dromara.zjk.domain.ZjkExpert;
import org.dromara.zjk.domain.ZjkPointUser;
import org.dromara.zjk.domain.dto.CreditReqDto;
import org.dromara.zjk.domain.vo.*;
import org.dromara.zjk.mapper.ZjkCreditRewardMapper;
import org.dromara.zjk.mapper.ZjkCreditUserMapper;
import org.dromara.zjk.mapper.ZjkExpertMapper;
import org.dromara.zjk.service.IZjkCreditRewardService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.dromara.zjk.domain.bo.ZjkCreditBo;
import org.dromara.zjk.domain.ZjkCredit;
import org.dromara.zjk.mapper.ZjkCreditMapper;
import org.dromara.zjk.service.IZjkCreditService;

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

/**
 * 信用记录Service业务层处理
 *
 * @author ygh
 * @date 2024-11-11
 */
@RequiredArgsConstructor
@Service
public class ZjkCreditServiceImpl implements IZjkCreditService {

    private final ZjkCreditMapper baseMapper;

    private final ZjkCreditUserMapper zjkCreditUserMapper;

    private final ZjkExpertMapper zjkExpertMapper;

    private final IZjkCreditRewardService zjkCreditRewardService;

    /**
     * 查询信用记录
     *
     * @param ID 主键
     * @return 信用记录
     */
    @Override
    public ZjkCreditVo queryById(Long ID){
        return baseMapper.selectVoById(ID);
    }

    /**
     * 分页查询信用记录列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 信用记录分页列表
     */
    @Override
    public TableDataInfo<ZjkCreditVo> queryPageList(ZjkCreditBo bo, PageQuery pageQuery) {
        //获取入库时间在这个范围之内的专家id
        List<Long> collect = new ArrayList<>();
        int count = 0;
        LambdaQueryWrapper<ZjkExpert> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(bo.getStartTime()!=null&&bo.getEndTime()!=null){
            lambdaQueryWrapper.ge(ZjkExpert::getApprovalTime,bo.getStartTime());
            lambdaQueryWrapper.le(ZjkExpert::getApprovalTime,bo.getEndTime());
            count++;
        }
        if(bo.getExpertName()!=null){
            lambdaQueryWrapper.like(ZjkExpert::getExpertName,bo.getExpertName());
            count++;
        }
        if(bo.getWorkUnit()!=null){
            lambdaQueryWrapper.like(ZjkExpert::getWorkUnit,bo.getWorkUnit());
            count++;
        }
        if(count!=0){
            List<ZjkExpertVo> vos = zjkExpertMapper.selectVoList(lambdaQueryWrapper);
            collect = vos.stream().map(ZjkExpertVo::getExpertId).collect(Collectors.toList());
        }
        LambdaQueryWrapper<ZjkCredit> lqw = buildQueryWrapper(bo);
        if(collect!=null&&collect.size()>0){
            lqw.in(ZjkCredit::getCreditId,collect);
        }
        Page<ZjkCreditVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的信用记录列表
     *
     * @param bo 查询条件
     * @return 信用记录列表
     */
    @Override
    public List<ZjkCreditVo> queryList(ZjkCreditBo bo) {
        LambdaQueryWrapper<ZjkCredit> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ZjkCredit> buildQueryWrapper(ZjkCreditBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ZjkCredit> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getCreditId() != null, ZjkCredit::getCreditId, bo.getCredit());
        lqw.eq(bo.getCredit() != null, ZjkCredit::getCredit, bo.getCredit());
        lqw.eq(bo.getRuleId() != null, ZjkCredit::getRuleId, bo.getRuleId());
        lqw.eq(bo.getCreateBy() != null, ZjkCredit::getCreateBy, bo.getCreateBy());
        lqw.eq(bo.getCreateTime() != null, ZjkCredit::getCreateTime, bo.getCreateTime());
        lqw.eq(bo.getUpdateBy() != null, ZjkCredit::getUpdateBy, bo.getUpdateBy());
        lqw.eq(bo.getUpdateTime() != null, ZjkCredit::getUpdateTime, bo.getUpdateTime());
        lqw.eq(bo.getExpertId() != null, ZjkCredit::getExpertId, bo.getExpertId());
        lqw.eq(bo.getUserId() != null, ZjkCredit::getUserId, bo.getUserId());
        return lqw;
    }

    /**
     * 新增信用记录
     *
     * @param bo 信用记录
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(ZjkCreditBo bo) {
        ZjkCredit add = MapstructUtils.convert(bo, ZjkCredit.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setCreditId(add.getCreditId());
        }
        return flag;
    }

    /**
     * 修改信用记录
     *
     * @param bo 信用记录
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(ZjkCreditBo bo) {
        ZjkCredit update = MapstructUtils.convert(bo, ZjkCredit.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ZjkCredit 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 R<PointExpertRankVO> expertPointRankUser() {
        //获取所有专家信息
        LambdaQueryWrapper<ZjkExpert> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ZjkExpert::getStatus,2);
        List<ZjkExpertVo> vos = zjkExpertMapper.selectVoList(lambdaQueryWrapper);
        List<ZjkCreditUser> list = new ArrayList<>();
        for (ZjkExpertVo vo : vos) {
            ZjkCreditUser zjkCreditUser = new ZjkCreditUser();
            zjkCreditUser.setExpertId(vo.getExpertId());
            zjkCreditUser.setUserId(vo.getUserId());
            list.add(zjkCreditUser);
        }
        zjkCreditUserMapper.insertBatch(list);
        return null;
    }

    @Override
    public TableDataInfo<CreditShowVO> queryPointList(CreditReqDto bo, PageQuery pageQuery) {
        //获取入库时间在这个范围之内的专家id

        IPage<CreditShowVO> page = baseMapper.queryPointList(pageQuery.build(), bo);
        List<CreditShowVO> records = page.getRecords();
        for (CreditShowVO record : records) {
            if(record.getCreditCount()>100){
                record.setCreditCount(100L);
            }
        }
        return TableDataInfo.build(page);
    }

    @Override
    public R<ChartBaseCreditVO> getPointBase() {
        LambdaQueryWrapper<ZjkExpert> wq = new LambdaQueryWrapper<ZjkExpert>()
            .eq(ZjkExpert::getUserId, LoginHelper.getUserId())
            .eq(ZjkExpert::getDeleteFlag, UserConstants.DEL_FLAG_NORMAL)
            .eq(ZjkExpert::getStatus, 2);
        ZjkExpert zjkExpert = zjkExpertMapper.selectOne(wq);
        if (zjkExpert != null) {
            ChartBaseCreditVO result = new ChartBaseCreditVO();
            BeanUtil.copyProperties(zjkExpert, result);
            //积分title设置
            QueryWrapper<ZjkPointUser> zj = new QueryWrapper<>();
            zj.lambda().eq(ZjkPointUser::getUserId, LoginHelper.getUserId());
            CreditShowVO rdata = zjkCreditUserMapper.getRankAndPoint(LoginHelper.getUserId());
            if(rdata!=null){
                result.setCreditCount(rdata.getCreditCount());
                result.setRank(rdata.getRank());
                result.setRewardTitle(zjkCreditRewardService.getRewardTitle(rdata.getExpertId(), rdata.getCreditCount()));
            }
            return R.ok(result);
        }

        return R.fail("当前用户还未入专家库");
    }

    @Override
    public R<ChartBaseCreditVO> synchronization() {
        List<ZjkCreditUser> list = zjkCreditUserMapper.selectList();
        for (ZjkCreditUser zjkCreditUser : list) {
            ZjkCredit zjkCredit = new ZjkCredit();
            zjkCredit.setExpertId(zjkCreditUser.getExpertId());
            zjkCredit.setUserId(zjkCreditUser.getUserId());
            zjkCredit.setCreditCount(zjkCreditUser.getCreditCount());
            baseMapper.insert(zjkCredit);
        }
        return R.ok();
    }

    //定时跟新专家的信用分，每日凌晨5点跟新昨天的数据
    @Scheduled(cron = "0 0 5 * * ?")
    public void scheduled(){
        //获取昨日凌晨5点开始之后的数据
        // 设置日期格式
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        Date now = new Date();
//        long oneDay = 24 * 60 * 60 * 1000L;
//        Date yesterday = new Date(now.getTime() - oneDay);
//        // 格式化日期
//        String yesterdayStr = sdf.format(yesterday);
//        String todayStr = sdf.format(now);
        //完成项目评审后增加信用分

        //项目请假成功扣减相信用分

        //项目评审缺席扣减信用分

        //增加信用记录

        //修改用户总信用分

    }


}
