package cn.com.ty.lift.business.project.service;

import cn.com.ty.lift.business.capital.dao.mapper.CommonMapper;
import cn.com.ty.lift.business.framework.util.MessageUtils;
import cn.com.ty.lift.business.library.dao.entity.Lift;
import cn.com.ty.lift.business.library.dao.entity.model.request.LiftRequest;
import cn.com.ty.lift.business.library.service.LiftService;
import cn.com.ty.lift.business.library.service.PlatformCompanyLiftRelevanceService;
import cn.com.ty.lift.business.maintenance.dao.entity.MaintenancePlan;
import cn.com.ty.lift.business.maintenance.service.MaintenancePlanService;
import cn.com.ty.lift.business.project.dao.entity.ProjectLiftRelevance;
import cn.com.ty.lift.business.project.dao.entity.ProjectUser;
import cn.com.ty.lift.business.project.dao.entity.Region;
import cn.com.ty.lift.business.project.dao.entity.model.request.ProjectRequest;
import cn.com.ty.lift.business.project.dao.entity.model.response.ProjectDetailResponse;
import cn.com.ty.lift.business.project.dao.entity.model.response.ProjectRelevanceResponse;
import cn.com.ty.lift.business.project.dao.entity.model.response.ProjectUserResponse;
import cn.com.ty.lift.business.project.dao.mapper.ProjectLiftRelevanceMapper;
import cn.com.ty.lift.business.push.service.PushUserService;
import cn.com.ty.lift.common.constants.ApiConstants;
import cn.com.ty.lift.common.constants.CommonEnum;
import cn.com.ty.lift.common.constants.WebSocketConstants;
import cn.com.ty.lift.common.model.PushMessage;
import cn.com.ty.lift.common.model.PushUserInfo;
import cn.com.ty.lift.common.utils.SendMessageUtil;
import cn.com.xwy.boot.web.dto.RestResponse;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author bieao
 * @date 2019/12/5
 * @description 项目电梯关联业务层
 */
@Service
public class ProjectLiftRelevanceService extends ServiceImpl<ProjectLiftRelevanceMapper, ProjectLiftRelevance> {

    @Resource
    private ProjectUserService projectUserService;

    @Resource
    private PlatformCompanyLiftRelevanceService platformService;

    @Resource
    private ProjectAppService projectAppService;

    @Resource
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Resource
    private PushUserService pushUserService;

    @Resource
    private LiftService liftService;

    @Resource
    private CommonMapper commonMapper;

    @Resource
    private MaintenancePlanService maintenancePlanService;

    /**
     * @param request 项目关联数据
     * @return RestResponse 状态码和返回消息
     * @description 删除电梯
     * @date 2019/12/5 2:16 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse delete(LiftRequest request) {
        //项目电梯关联主键id
        Long id = request.getId();
        ProjectLiftRelevance relevance = getById(id);
        boolean result = remove(id);
        if (!result)
            return RestResponse.fail(MessageUtils.get("msg.delete.fail"));
        //清除电梯维保计划
        boolean cleanPlan = maintenancePlanService.cleanPlan(request.getMtCompanyId(), relevance.getLiftId());
        if (!cleanPlan) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(MessageUtils.get("msg.delete.fail"));
        }
        return RestResponse.success(null, MessageUtils.get("msg.delete.success"));
    }

    /**
     * @param mtCompanyId   公司id
     * @param projectStatus 项目状态
     * @return 条数
     * @description 根据公司id和项目状态查询电梯
     * @date 2020/1/19 2:15 下午
     */
    public int count(Long mtCompanyId, Integer projectStatus) {
        return baseMapper.count(mtCompanyId, projectStatus);
    }

    /**
     * @param mtCompanyId 公司id
     * @param projectId   项目id
     * @return 计算结果
     * @description 计算公司某项目下的电梯台量
     * @date 2020/5/20 9:54 上午
     */
    public int countLiftNum(Long mtCompanyId, Long projectId) {
        return baseMapper.countLiftNum(mtCompanyId, projectId);
    }

    /**
     * @param liftId      电梯id
     * @param projectId   项目id
     * @param id          平台企业电梯主键id
     * @param workerId    维保工id
     * @param mtCompanyId 公司id
     * @return projectLiftEntry
     * @description 新增项目电梯关联数据
     * @date 2019/12/5 2:39 PM
     */
    public ProjectLiftRelevance save(Long liftId, Long projectId, Long id, Long workerId, Long mtCompanyId) {
        //新增项目电梯关联表
        ProjectLiftRelevance projectLiftEntry = new ProjectLiftRelevance();
        projectLiftEntry.setProjectId(projectId);
        projectLiftEntry.setLiftId(liftId);
        projectLiftEntry.setRelevanceId(id);
        projectLiftEntry.setWorkerId(workerId);
        projectLiftEntry.setMtCompanyId(mtCompanyId);
        return save(projectLiftEntry) ? projectLiftEntry : null;
    }

    /**
     * @param list 项目电梯关联列表
     * @return 是否成功
     * @description 批量插入项目电梯关联表
     * @date 2020/1/2 2:55 下午
     */
    public boolean insertBatch(List<ProjectLiftRelevance> list) {
        return saveBatch(list, list.size());
    }

    /**
     * @param request 项目id，项目电梯关联id列表
     * @return 1.成功, 0.失败, 消息描述
     * @description 批量移动电梯
     * @date 2020/1/7 7:57 下午
     */
    public boolean move(LiftRequest request) {
        List<ProjectLiftRelevance> list = request.getList();
        list.forEach(entry -> entry.setProjectId(request.getProjectId()));
        return updateBatchById(list, list.size());
    }


    /**
     * @param mtCompanyId 公司id
     * @param idList      电梯id列表
     * @return 项目电梯关联列表
     * @description 根据公司id和电梯id列表查询项目电梯关联列表
     * @date 2019/12/28 1:55 PM
     */
    public List<ProjectLiftRelevance> list(Long mtCompanyId, List<Long> idList) {
        QueryWrapper<ProjectLiftRelevance> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<ProjectLiftRelevance> lambdaQueryWrapper = queryWrapper.lambda();
        lambdaQueryWrapper.eq(ProjectLiftRelevance::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.in(ProjectLiftRelevance::getLiftId, idList);
        return list(lambdaQueryWrapper);
    }

    /**
     * @param request 电梯id列表
     * @return RestResponse 状态码和返回消息
     * @description 电梯锁定、解锁
     * @date 2019/12/5 11:00 AM
     */
    public RestResponse liftLockOrUnLock(LiftRequest request) {
        List<ProjectLiftRelevance> projectLiftList = list(request.getMtCompanyId(), request.getLiftList());
        if (ObjectUtil.isEmpty(projectLiftList)) {
            return RestResponse.success(null, MessageUtils.get("msg.company.lift.empty"));
        }
        projectLiftList.forEach(entry -> entry.setLiftLocked(request.getLock()));
        boolean result = updateBatchById(projectLiftList);
        if (!result) {
            return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
        }
        return RestResponse.success(null, MessageUtils.get("msg.modify.success"));
    }

    /**
     * @param mtCompanyId 公司id
     * @param projectId   项目id
     * @return List<ProjectLiftRelevance> 项目下电梯列表
     * @description 根据项目id和公司id查询项目下电梯
     * @date 2020/1/7 3:35 下午
     */
    public List<ProjectLiftRelevance> findLiftList(Long mtCompanyId, Long projectId) {
        QueryWrapper<ProjectLiftRelevance> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<ProjectLiftRelevance> lambdaQueryWrapper = queryWrapper.lambda();
        lambdaQueryWrapper.eq(ProjectLiftRelevance::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.eq(ProjectLiftRelevance::getProjectId, projectId);
        return list(lambdaQueryWrapper);
    }

    /**
     * @param mtCompanyId 公司id
     * @param liftId      电梯id
     * @return ProjectLiftRelevance 项目电梯记录
     * @description 根据公司id和电梯id查询项目电梯记录
     * @date 2020/1/8 9:59 上午
     */
    public ProjectLiftRelevance getOne(Long mtCompanyId, Long liftId) {
        QueryWrapper<ProjectLiftRelevance> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<ProjectLiftRelevance> lambdaQueryWrapper = queryWrapper.lambda();
        lambdaQueryWrapper.eq(ProjectLiftRelevance::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.eq(ProjectLiftRelevance::getLiftId, liftId);
        ProjectLiftRelevance entry = getOne(lambdaQueryWrapper);
        return ObjectUtil.isNotEmpty(entry) ? entry : null;
    }

    /**
     * @param entry 项目电梯关联实体
     * @description 修改项目电梯关联信息
     * @date 2020/1/8 9:59 上午
     */
    public boolean modify(ProjectLiftRelevance entry) {
        return updateById(entry);
    }

    /**
     * @param projectId   项目ID
     * @param mtCompanyId 公司ID
     * @param liftId      电梯ID
     * @param workerId    原有维保负责人
     * @param newWorkerId 新维保负责人
     * @return
     * @description 电梯更换主要负责人消息推送
     * @date 2020/5/8 6:35 下午
     */
    public void sendMessage(Long projectId, Long mtCompanyId, Long liftId, Long workerId, Long newWorkerId) {
        //消息推送
        List<Long> userIds = new ArrayList<>();
        Region region = pushUserService.findRegionByProject(projectId, mtCompanyId);
        if (Objects.nonNull(region)) {
            userIds.addAll(region.members());
        }
        userIds.add(workerId);
        userIds.add(newWorkerId);
        List<PushUserInfo> director = pushUserService.listEnterpriseAdmin(mtCompanyId);
        List<PushUserInfo> pushUserInfos = new ArrayList<>(director);
        if (!userIds.isEmpty()) {
            List<PushUserInfo> userInfos = pushUserService.listByUserIds(mtCompanyId, userIds);
            pushUserInfos.addAll(userInfos);
        }
        if (!pushUserInfos.isEmpty()) {
            ProjectDetailResponse detail = projectAppService.detail(projectId);
            Optional<Lift> lift = liftService.getOne(null, liftId);
            lift.ifPresent(l -> {
                String workerName = commonMapper.queryUserNameById(workerId);
                String newworkerName = commonMapper.queryUserNameById(newWorkerId);
                PushMessage pushMessage = PushMessage.workReplaceLiftCharger(detail.getAreaName(), detail.getProjectName(),
                        l.getDevicePosition(), l.getRegistrationCode(), workerName, newworkerName);
                pushMessage.sendTokenOnPlatform(jmsMessagingTemplate, pushUserInfos);
                List<Long> sendToUserIdList = pushUserInfos.stream().map(PushUserInfo::getUserId).collect(Collectors.toList());
                //推送pc端
                SendMessageUtil.sendMessageToPC(jmsMessagingTemplate, sendToUserIdList, pushMessage.getContent(),
                        WebSocketConstants.MessageType.WORK_MSG);
            });
        }
    }

    /**
     * @param request 项目电梯id列表
     * @return 是否成功
     * @description 批量更新电梯维保负责人，并修改未完成的维保计划为新的维保负责人
     * @date 2020/5/8 4:15 下午
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse batchModify(ProjectRequest request) {
        Long newWorkerId = request.getWorkerId();
        List<ProjectLiftRelevance> list = request.getList();
        list.forEach(entry -> entry.setWorkerId(request.getWorkerId()));
        boolean result = updateBatchById(list);
        if (!result) return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
        for (ProjectLiftRelevance entry : list) {
            sendMessage(entry.getProjectId(), entry.getMtCompanyId(), entry.getLiftId(), entry.getWorkerId(), newWorkerId);
        }
        //查询未完成的维保任务
        List<Long> liftIdList = list.stream().map(ProjectLiftRelevance::getLiftId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(liftIdList)) {
            List<MaintenancePlan> planList = maintenancePlanService.getPlanList(request.getMtCompanyId(), liftIdList);
            //修改未完成的维保计划为新的维保负责人
            planList.forEach(entry -> entry.setWorkerId(newWorkerId));
            boolean planResult = maintenancePlanService.updateBatchById(planList);
            if (!planResult) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
            }
        }
        return RestResponse.success(null, MessageUtils.get("msg.modify.success"));
    }

    /**
     * @param id 项目关联主键id
     * @return 是否成功
     * @description 删除项目关联数据
     * @date 2020/2/12 5:10 下午
     */
    public boolean remove(Long id) {
        return removeById(id);
    }

    /**
     * @param id          项目id
     * @param mtCompanyId 公司id
     * @return 是否成功
     * @description 批量删除项目关联数据
     * @date 2020/5/26 5:33 下午
     */
    public boolean removeByMap(Long id, Long mtCompanyId) {
        Map<String, Object> columnMap = new HashMap<>(2);
        columnMap.put("mt_company_id", mtCompanyId);
        columnMap.put("project_id", id);
        return removeByMap(columnMap);
    }

    /**
     * @param projectId 项目ID
     * @return List<ProjectUser> userList项目组维保工列表
     * @description 查询项目组维保工
     * @date 2020/2/12 5:01 下午
     */
    public List<ProjectUserResponse> userList(Long projectId) {
        List<ProjectUserResponse> userList = projectUserService.getUserList(projectId, null);
        return userList.stream().filter(user -> (
                CommonEnum.DefaultRole.MTWORK.getCode().equals(user.getUserRole())
        )).collect(Collectors.toList());
    }

    /**
     * @param request 用户id
     * @return 1.成功, 0.失败, 消息描述
     * @description 查询用户下的关联项目和电梯信息
     * @date 2019/12/26 4:27 PM
     */
    public IPage<ProjectRelevanceResponse> relevanceList(ProjectRequest request) {
        return baseMapper.selectListByUserIdAndProjectId(request.getPage(), request);
    }


    public List<ProjectLiftRelevance> listByMtCompany(Long mtCompanyId) {
        QueryWrapper<ProjectLiftRelevance> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<ProjectLiftRelevance> lambdaQueryWrapper = queryWrapper.lambda();
        lambdaQueryWrapper.eq(ProjectLiftRelevance::getMtCompanyId, mtCompanyId);
        return list(lambdaQueryWrapper);
    }

    /**
     * @param
     * @return
     * @description 取消关联
     * @date 2020/5/26 4:40 下午
     */
    public RestResponse cancelRelevance(ProjectRequest request) {
        long relevanceLiftNum = commonMapper.getRelevanceLiftNum(request.getWorkerId(), request.getProjectId());
        if (relevanceLiftNum > 0) {
            return RestResponse.fail("用户存在关联电梯，无法取消");
        }
        boolean removeFlag = projectUserService.remove(new QueryWrapper<ProjectUser>()
              .eq("project_id", request.getProjectId())
              .eq("user_id", request.getWorkerId())
        );
        if(!removeFlag) {
            return RestResponse.fail("取消关联失败");
        }
        return RestResponse.success(ApiConstants.RESULT_SUCCESS, "操作成功");
    }
}
