package com.yunzhupaas.flowable.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.yunzhupaas.base.UserInfo;
import com.yunzhupaas.base.model.systemconfig.SysConfigModel;
import com.yunzhupaas.base.service.SuperServiceImpl;
import com.yunzhupaas.flowable.entity.DelegateEntity;
import com.yunzhupaas.flowable.entity.DelegateInfoEntity;
import com.yunzhupaas.flowable.mapper.DelegateInfoMapper;
import com.yunzhupaas.flowable.model.delegate.*;
import com.yunzhupaas.flowable.model.message.DelegateModel;
import com.yunzhupaas.flowable.service.DelegateInfoService;
import com.yunzhupaas.flowable.util.MsgUtil;
import com.yunzhupaas.flowable.util.ServiceUtil;
import com.yunzhupaas.permission.entity.UserEntity;
import com.yunzhupaas.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 类的描述
 *
 * @author YUNZHUPAASYUNZHUPAAS开发组
 * @version 5.0.x
 * @since 2024/9/2 13:41
 */
@Service
public class DelegateInfoServiceImpl extends SuperServiceImpl<DelegateInfoMapper, DelegateInfoEntity>
        implements DelegateInfoService {
    @Autowired
    private ServiceUtil serviceUtil;
    @Autowired
    private MsgUtil msgUtil;

    @Override
    public List<DelegateListVO> getList(DelegatePagination pagination) {
        Integer type = ObjectUtil.equals(pagination.getType(), 2) ? 0 : 1;
        String userId = UserProvider.getLoginUserId();
        MPJLambdaWrapper<DelegateInfoEntity> wrapper = JoinWrappers.lambda(DelegateInfoEntity.class)
                .leftJoin(DelegateEntity.class, DelegateEntity::getId, DelegateInfoEntity::getDelegateId)
                .selectAs(DelegateInfoEntity::getId, DelegateInfoModel::getId)
                .selectAs(DelegateInfoEntity::getDelegateId, DelegateInfoModel::getDelegateId)
                .selectAs(DelegateInfoEntity::getToUserName, DelegateInfoModel::getToUserName)
                .selectAs(DelegateInfoEntity::getStatus, DelegateInfoModel::getConfirmStatus)
                .selectAs(DelegateEntity::getFlowName, DelegateInfoModel::getFlowName)
                .selectAs(DelegateEntity::getUserName, DelegateInfoModel::getUserName)
                .selectAs(DelegateEntity::getStartTime, DelegateInfoModel::getStartTime)
                .selectAs(DelegateEntity::getEndTime, DelegateInfoModel::getEndTime)
                .selectAs(DelegateEntity::getType, DelegateInfoModel::getType)
                .selectAs(DelegateEntity::getDescription, DelegateInfoModel::getDescription)
                .eq(DelegateInfoEntity::getToUserId, userId)
                .eq(DelegateEntity::getType, type);

        String keyword = pagination.getKeyword();
        if (StringUtil.isNotBlank(keyword)) {
            wrapper.and(
                    t -> t.like(DelegateEntity::getUserName, keyword).or().like(DelegateEntity::getFlowName, keyword));
        }

        wrapper.orderByDesc(DelegateInfoEntity::getCreatorTime);
        Page<DelegateInfoModel> page = new Page<>(pagination.getCurrentPage(), pagination.getPageSize());
        Page<DelegateInfoModel> data = this.selectJoinListPage(page, DelegateInfoModel.class, wrapper);
        List<DelegateInfoModel> dataList = pagination.setData(data.getRecords(), page.getTotal());

        List<DelegateListVO> voList = new ArrayList<>();
        long time = new Date().getTime();
        List<String> delegateIds = dataList.stream().map(DelegateInfoModel::getDelegateId).distinct()
                .collect(Collectors.toList());
        List<DelegateInfoEntity> list = this.getList(delegateIds);
        for (DelegateInfoModel model : dataList) {
            DelegateListVO vo = JsonUtil.getJsonToBean(model, DelegateListVO.class);
            List<DelegateInfoEntity> infoList = list.stream()
                    .filter(e -> ObjectUtil.equals(e.getDelegateId(), model.getDelegateId()))
                    .collect(Collectors.toList());
            long rejectCount = infoList.stream().filter(e -> ObjectUtil.equals(e.getStatus(), 2)).count();
            long acceptCount = infoList.stream().filter(e -> ObjectUtil.equals(e.getStatus(), 1)).count();
            if (time >= vo.getEndTime() || rejectCount == infoList.size()) {// 已失效，1、所有人都拒绝；2、到达结束时间或终止委托
                vo.setStatus(2);
            } else if (time >= vo.getStartTime() && acceptCount > 0) {// 生效中，对方接受且到达开始时间的状态
                vo.setStatus(1);
            } else {// 未生效，两种场景1：对方已接受但未达到开始时间状态为未生效，2、对方未接受状态为未生效
                vo.setStatus(0);
            }
            voList.add(vo);
        }
        return voList;
    }

    @Override
    public List<DelegateInfoEntity> getList(List<String> delegateIds) {
        if (CollectionUtil.isEmpty(delegateIds)) {
            return new ArrayList<>();
        }
        QueryWrapper<DelegateInfoEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(DelegateInfoEntity::getDelegateId, delegateIds);
        return this.list(queryWrapper);
    }

    @Override
    public List<DelegateInfoEntity> getList(String delegateId) {
        QueryWrapper<DelegateInfoEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(DelegateInfoEntity::getDelegateId, delegateId);
        return this.list(queryWrapper);
    }

    @Override
    public List<DelegateInfoEntity> getByToUserId(String toUserId) {
        QueryWrapper<DelegateInfoEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(DelegateInfoEntity::getToUserId, toUserId);
        return this.list(queryWrapper);
    }

    @Override
    public List<DelegateInfoEntity> getByToUserIds(List<String> userIds) {
        List<DelegateInfoEntity> resList = new ArrayList<>();
        if (CollectionUtil.isEmpty(userIds)) {
            return resList;
        }
        QueryWrapper<DelegateInfoEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(DelegateInfoEntity::getToUserId, userIds);
        resList = this.list(queryWrapper);
        return resList;
    }

    @Override
    public void create(DelegateCrForm fo, DelegateEntity delegateEntity) {
        this.save(fo.getToUserId(), delegateEntity);
    }

    public void save(List<String> toUserIdList, DelegateEntity delegateEntity) {
        if (CollectionUtil.isNotEmpty(toUserIdList)) {
            Integer type = delegateEntity.getType();
            // 获取全局配置，是否确认
            SysConfigModel sysConfig = serviceUtil.getSysConfig();
            Integer ack = ObjectUtil.equals(type, 0) ? sysConfig.getDelegateAck() : sysConfig.getProxyAck();
            List<UserEntity> userList = serviceUtil.getUserName(toUserIdList);
            List<DelegateInfoEntity> list = new ArrayList<>();
            for (String toUserId : toUserIdList) {
                DelegateInfoEntity entity = new DelegateInfoEntity();
                entity.setId(RandomUtil.uuId());
                entity.setStatus(0);
                if (ObjectUtil.equals(ack, 0)) {
                    entity.setStatus(1);
                }
                entity.setDelegateId(delegateEntity.getId());
                entity.setToUserId(toUserId);
                UserEntity user = userList.stream().filter(e -> ObjectUtil.equals(e.getId(), toUserId)).findFirst()
                        .orElse(null);
                if (null != user) {
                    entity.setToUserName(user.getRealName() + "/" + user.getAccount());
                }
                list.add(entity);
            }
            this.saveBatch(list);

            // 委托消息
            UserInfo userInfo = UserProvider.getUser();
            DelegateModel model = new DelegateModel();
            model.setToUserIds(toUserIdList);
            model.setType(type);
            model.setUserInfo(userInfo);
            model.setDelegate(ObjectUtil.equals(type, 0));
            msgUtil.delegateMsg(model);
        }
    }

    @Override
    public void update(DelegateUpForm fo, DelegateEntity delegateEntity) {
        String delegateId = delegateEntity.getId();
        List<String> toUserIdList = fo.getToUserId();
        if (CollectionUtil.isNotEmpty(toUserIdList)) {
            List<String> createList = new ArrayList<>();
            List<String> deleteList = new ArrayList<>();
            List<DelegateInfoEntity> list = this.getList(delegateId);

            for (String userId : toUserIdList) {
                DelegateInfoEntity infoEntity = list.stream()
                        .filter(e -> ObjectUtil.equals(e.getToUserId(), userId)).findFirst().orElse(null);
                if (null == infoEntity) {
                    createList.add(userId);
                }
            }
            for (DelegateInfoEntity entity : list) {
                String userId = toUserIdList.stream()
                        .filter(e -> ObjectUtil.equals(entity.getToUserId(), e)).findFirst().orElse(null);
                if (StringUtil.isEmpty(userId)) {
                    deleteList.add(entity.getToUserId());
                }
            }
            if (CollectionUtil.isNotEmpty(deleteList)) {
                QueryWrapper<DelegateInfoEntity> wrapper = new QueryWrapper<>();
                wrapper.lambda().eq(DelegateInfoEntity::getDelegateId, delegateId)
                        .in(DelegateInfoEntity::getToUserId, deleteList);
                this.remove(wrapper);
            }
            if (CollectionUtil.isNotEmpty(createList)) {
                this.save(createList, delegateEntity);
            }
        }
    }

    @Override
    public void delete(String delegateId) {
        QueryWrapper<DelegateInfoEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(DelegateInfoEntity::getDelegateId, delegateId);
        this.remove(wrapper);
    }

}
