package org.dromara.zjk.learning_world.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
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.common.satoken.utils.LoginHelper;
import org.dromara.zjk.domain.vo.ZjkExpertVo;
import org.dromara.zjk.learning_world.domain.bo.ZjkProblemBo;
import org.dromara.zjk.learning_world.domain.entity.ZjkProblem;
import org.dromara.zjk.learning_world.domain.vo.ZjkProblemVo;
import org.dromara.zjk.learning_world.enums.problem.ProblemStatusEnum;
import org.dromara.zjk.learning_world.mapper.ZjkProblemMapper;
import org.dromara.zjk.learning_world.service.IZjkProblemService;
import org.dromara.zjk.mapper.ZjkExpertMapper;
import org.springframework.stereotype.Service;

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

/**
 * 问题管理Service业务层处理
 *
 * @author wt
 * @date 2024-11-20
 */
@RequiredArgsConstructor
@Service
public class ZjkProblemServiceImpl implements IZjkProblemService {

    private final ZjkProblemMapper baseMapper;

    private final ZjkExpertMapper expertMapper;

    /**
     * 查询问题管理
     *
     * @param id 主键
     * @return 问题管理
     */
    @Override
    public ZjkProblemVo queryById(Long id) {
        ZjkProblemVo zjkProblemVo = baseMapper.selectVoById(id);
        if (zjkProblemVo == null) {
            return new ZjkProblemVo();
        }
        List<ZjkExpertVo> zjkExpertVos = expertMapper.selectByUserIds(Arrays.asList(zjkProblemVo.getReplyId(), zjkProblemVo.getUserId()));
        if (CollectionUtil.isEmpty(zjkExpertVos)) {
            return new ZjkProblemVo();
        }
        Map<Long, ZjkExpertVo> expertVoMap = zjkExpertVos.stream().collect(Collectors.toMap(ZjkExpertVo::getUserId, v -> v));

        Long userId = zjkProblemVo.getUserId();
        Long replyId = zjkProblemVo.getReplyId();
        if (expertVoMap.containsKey(userId)) {
            ZjkExpertVo zjkExpertVo = expertVoMap.get(userId);
            zjkProblemVo.setUserPhotograph(zjkExpertVo.getPhotograph());
            zjkProblemVo.setDeptName(zjkExpertVo.getDeptName());
            zjkProblemVo.setUserName(zjkExpertVo.getExpertName());
        }
        if (expertVoMap.containsKey(replyId)) {
            ZjkExpertVo expertVo = expertVoMap.get(replyId);
            zjkProblemVo.setReplyName(expertVo.getUserName());
            zjkProblemVo.setReplyPhotograph(expertVo.getAvatar());
            zjkProblemVo.setReplyDeptName(expertVo.getDeptName());
        }

        return zjkProblemVo;
    }

    /**
     * 分页查询问题管理列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 问题管理分页列表
     */
    @Override
    public TableDataInfo<ZjkProblemVo> queryPageList(ZjkProblemBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ZjkProblem> lqw = buildQueryWrapper(bo);
        Page<ZjkProblemVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<ZjkProblemVo> records = result.getRecords();
        if (CollectionUtil.isEmpty(records)) {
            return TableDataInfo.build(result);
        }
        List<Long> userIds = new ArrayList<>();
        for (ZjkProblemVo record : records) {
            userIds.add(record.getUserId());
            userIds.add(record.getReplyId());
        }
        List<ZjkExpertVo> zjkExpertVos = expertMapper.selectByUserIds(userIds);
        if (CollectionUtil.isEmpty(zjkExpertVos)) {
            return TableDataInfo.build(result);
        }
        Map<Long, ZjkExpertVo> expertVoMap = zjkExpertVos.stream().collect(Collectors.toMap(ZjkExpertVo::getUserId, v -> v));
        for (ZjkProblemVo record : records) {
            Long userId = record.getUserId();
            Long replyId = record.getReplyId();
            if (!expertVoMap.containsKey(userId)) {
                continue;
            }
            ZjkExpertVo zjkExpertVo = expertVoMap.get(userId);
            record.setUserPhotograph(zjkExpertVo.getPhotograph());
            record.setDeptName(zjkExpertVo.getDeptName());
            record.setUserName(zjkExpertVo.getExpertName());
            if (!expertVoMap.containsKey(replyId)) {
                continue;
            }
            ZjkExpertVo expertVo = expertVoMap.get(replyId);
            record.setReplyName(expertVo.getUserName());
            record.setReplyPhotograph(expertVo.getAvatar());
            record.setReplyDeptName(expertVo.getDeptName());

        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的问题管理列表
     *
     * @param bo 查询条件
     * @return 问题管理列表
     */
    @Override
    public List<ZjkProblemVo> queryList(ZjkProblemBo bo) {
        LambdaQueryWrapper<ZjkProblem> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ZjkProblem> buildQueryWrapper(ZjkProblemBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ZjkProblem> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getProblemTitle()), ZjkProblem::getProblemTitle, bo.getProblemTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getProblem()), ZjkProblem::getProblem, bo.getProblem());
        lqw.eq(StringUtils.isNotBlank(bo.getReply()), ZjkProblem::getReply, bo.getReply());
        lqw.eq(bo.getUserId() != null, ZjkProblem::getUserId, bo.getUserId());
        lqw.eq(bo.getReplyId() != null, ZjkProblem::getReplyId, bo.getReplyId());
        lqw.eq(bo.getReplyTime() != null, ZjkProblem::getReplyTime, bo.getReplyTime());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), ZjkProblem::getStatus, bo.getStatus());
        lqw.ge(!Objects.isNull(bo.getStartTime()), ZjkProblem::getProblemTime, bo.getStartTime());
        lqw.le(!Objects.isNull(bo.getEndTime()), ZjkProblem::getProblemTime, bo.getEndTime());
        lqw.ge(!Objects.isNull(bo.getReplyStartTime()), ZjkProblem::getReplyTime, bo.getReplyStartTime());
        lqw.le(!Objects.isNull(bo.getReplyEndTime()), ZjkProblem::getReplyTime, bo.getReplyEndTime());
        return lqw;
    }

    /**
     * 新增问题管理
     *
     * @param bo 问题管理
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(ZjkProblemBo bo) {
        ZjkProblem add = MapstructUtils.convert(bo, ZjkProblem.class);
        validEntityBeforeSave(add);
        add.setUserId(LoginHelper.getUserId());
        add.setProblemTime(new Date());
        add.setStatus(ProblemStatusEnum.NO_REPLY.getCode());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改问题管理
     *
     * @param bo 问题管理
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(ZjkProblemBo bo) {
        ZjkProblem update = MapstructUtils.convert(bo, ZjkProblem.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ZjkProblem 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 int reply(ZjkProblemBo bo) {
        Long id = bo.getId();
        ZjkProblem zjkProblem = baseMapper.selectById(id);
        if (zjkProblem == null) {
            throw new ServiceException("无效id");
        }
        zjkProblem.setReplyTime(new Date());
        zjkProblem.setReplyId(LoginHelper.getUserId());
        zjkProblem.setReply(bo.getReply());
        zjkProblem.setStatus(ProblemStatusEnum.REPLY.getCode());
        return baseMapper.updateById(zjkProblem);
    }
}
