package cn.stylefeng.workflow.instance.modular.tag.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.db.api.pojo.entity.BaseEntity;
import cn.stylefeng.workflow.instance.api.pojo.tag.SimpleRemarkVo;
import cn.stylefeng.workflow.instance.modular.tag.entity.RuntimeRemark;
import cn.stylefeng.workflow.instance.modular.tag.mapper.RuntimeRemarkMapper;
import cn.stylefeng.workflow.instance.modular.tag.pojo.request.RuntimeRemarkRequest;
import cn.stylefeng.workflow.instance.modular.tag.service.RuntimeRemarkService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class RuntimeRemarkServiceImpl extends ServiceImpl<RuntimeRemarkMapper, RuntimeRemark> implements RuntimeRemarkService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserRemark(RuntimeRemarkRequest runtimeRemarkRequest) {

        Long userId = LoginContext.me().getLoginUser().getUserId();

        this.removeUserRemarkList(userId, runtimeRemarkRequest.getInstanceId());

        List<RuntimeRemark> runtimeRemarkList = runtimeRemarkRequest.getUserRemarkList();
        List<RuntimeRemark> finalInsert = new ArrayList<>();
        for (RuntimeRemark runtimeRemark : runtimeRemarkList) {

            if (ObjectUtil.isEmpty(runtimeRemark.getRemarkContent())) {
                continue;
            }

            runtimeRemark.setUserId(userId);
            runtimeRemark.setInstanceId(runtimeRemarkRequest.getInstanceId());
            finalInsert.add(runtimeRemark);
        }

        this.saveBatch(finalInsert);
    }

    @Override
    public List<RuntimeRemark> findUserRemarkList(RuntimeRemarkRequest runtimeRemarkRequest) {
        LambdaQueryWrapper<RuntimeRemark> wrapper = this.createWrapper(runtimeRemarkRequest);
        return this.list(wrapper);
    }

    @Override
    public Map<Long, List<SimpleRemarkVo>> findUserRemarkListMap(List<Long> instanceIdList) {

        if (ObjectUtil.isEmpty(instanceIdList)) {
            return new HashMap<>();
        }

        Long userId = LoginContext.me().getLoginUser().getUserId();

        LambdaQueryWrapper<RuntimeRemark> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RuntimeRemark::getUserId, userId);
        queryWrapper.in(RuntimeRemark::getInstanceId, instanceIdList);
        queryWrapper.select(RuntimeRemark::getRemarkContent, RuntimeRemark::getUserId, RuntimeRemark::getInstanceId);
        List<RuntimeRemark> list = this.list(queryWrapper);
        if (ObjectUtil.isEmpty(list)) {
            return new HashMap<>();
        }

        Map<Long, List<RuntimeRemark>> runtimeRemarkMap = list.stream().collect(Collectors.groupingBy(RuntimeRemark::getInstanceId));

        Map<Long, List<SimpleRemarkVo>> simpleRemarkMap = new HashMap<>();
        for (Map.Entry<Long, List<RuntimeRemark>> entry : runtimeRemarkMap.entrySet()) {
            List<RuntimeRemark> value = entry.getValue();
            if (ObjectUtil.isEmpty(value)) {
                continue;
            }
            List<SimpleRemarkVo> simpleRemarkVos = BeanUtil.copyToList(value, SimpleRemarkVo.class);
            simpleRemarkMap.put(entry.getKey(), simpleRemarkVos);
        }
        return simpleRemarkMap;

    }

    private void removeUserRemarkList(Long userId, Long instanceId) {
        LambdaQueryWrapper<RuntimeRemark> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RuntimeRemark::getUserId, userId);
        wrapper.eq(RuntimeRemark::getInstanceId, instanceId);
        this.remove(wrapper);
    }

    private LambdaQueryWrapper<RuntimeRemark> createWrapper(RuntimeRemarkRequest runtimeRemarkRequest) {
        LambdaQueryWrapper<RuntimeRemark> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(RuntimeRemark::getUserId, LoginContext.me().getLoginUser().getUserId());
        queryWrapper.eq(RuntimeRemark::getInstanceId, runtimeRemarkRequest.getInstanceId());

        queryWrapper.select(RuntimeRemark::getRemarkContent);

        queryWrapper.orderByAsc(BaseEntity::getCreateTime);

        return queryWrapper;
    }

}
