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

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.PlatformCompanyLiftRelevance;
import cn.com.ty.lift.business.library.dao.entity.model.request.LiftRequest;
import cn.com.ty.lift.business.library.dao.mapper.PlatformCompanyLiftRelevanceMapper;
import cn.com.ty.lift.business.maintenance.service.MaintenancePlanService;
import cn.com.ty.lift.business.maintenance.service.MaintenanceService;
import cn.com.ty.lift.business.project.dao.entity.Project;
import cn.com.ty.lift.business.project.dao.entity.ProjectLiftRelevance;
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.service.ProjectAppService;
import cn.com.ty.lift.business.project.service.ProjectLiftRelevanceService;
import cn.com.ty.lift.business.project.service.ProjectService;
import cn.com.ty.lift.business.push.service.PushUserService;
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 com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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 PlatformCompanyLiftRelevanceService extends ServiceImpl<PlatformCompanyLiftRelevanceMapper, PlatformCompanyLiftRelevance> {

    @Resource
    private LiftService liftService;

    @Resource
    private MaintenancePlanService maintenancePlanService;

    @Resource
    private MaintenanceService maintenanceService;

    @Resource
    private ProjectLiftRelevanceService projectLiftRelevanceService;

    @Resource
    private ProjectService projectService;

    @Resource
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Resource
    private PushUserService pushUserService;

    @Resource
    private ProjectAppService projectAppService;


    /**
     * @param id          电梯id
     * @param mtCompanyId 公司id
     * @return PlatformCompanyLiftRelevance
     * @description 新增平台电梯、企业电梯关联表数据
     * @date 2019/12/5 2:38 PM
     */
    public PlatformCompanyLiftRelevance save(Long id, Long mtCompanyId) {
        //建立企业电梯关联关系
        PlatformCompanyLiftRelevance companyLiftEntry = new PlatformCompanyLiftRelevance();
        companyLiftEntry.setLiftId(id);
        companyLiftEntry.setMtCompanyId(mtCompanyId);
        return save(companyLiftEntry) ? companyLiftEntry : null;
    }

    /**
     * @param mtCompanyId 公司id
     * @return 数量集合
     * @description 根据公司id查询服务中电梯和维修中的电梯数量
     * @date 2020/1/19 2:34 下午
     */
    public Map<String, Object> countAll(Long mtCompanyId) {
        LambdaQueryWrapper<PlatformCompanyLiftRelevance> lambdaQueryWrapper = new QueryWrapper<PlatformCompanyLiftRelevance>().lambda();
        lambdaQueryWrapper.eq(PlatformCompanyLiftRelevance::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.ne(PlatformCompanyLiftRelevance::getLiftCompanyStatus, CommonEnum.LiftStatus.STOP_INSURANCE.getCode());
        int inService = count(lambdaQueryWrapper);
        lambdaQueryWrapper.eq(PlatformCompanyLiftRelevance::getLiftCompanyStatus, CommonEnum.LiftStatus.EMERGENCY_REPAIR.getCode());
        int emergency = count(lambdaQueryWrapper);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("inService", inService);
        resultMap.put("emergency", emergency);
        return resultMap;
    }

    /**
     * @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 projectStatus 项目状态
     * @return 条数
     * @description 根据公司id和项目状态查询停保电梯
     * @date 2020/4/24 9:50 上午
     */
    public int countCapital(Long mtCompanyId, String projectStatus) {
        return baseMapper.countCapital(mtCompanyId, projectStatus);
    }

    /**
     * @param id 主键id
     * @return 是否成功
     * @description 删除电梯
     * @date 2020/2/25 4:08 下午
     */
    public boolean remove(Long id){
        return removeById(id);
    }

    /**
     * @param paramMap 电梯id，公司id
     * @return 是否存在
     * @description 根据电梯id和公司id查询该公司是否关联过此电梯
     * @date 2019/12/20 11:39 AM
     */
    public boolean findCompanyLiftExist(Map<String, Object> paramMap) {
        QueryWrapper<PlatformCompanyLiftRelevance> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<PlatformCompanyLiftRelevance> lambdaQueryWrapper = queryWrapper.lambda();
        lambdaQueryWrapper.eq(PlatformCompanyLiftRelevance::getMtCompanyId, paramMap.get("mtCompanyId"));
        lambdaQueryWrapper.eq(PlatformCompanyLiftRelevance::getLiftId, paramMap.get("liftId"));
        return count(lambdaQueryWrapper) > 0;
    }

    /**
     * @param mtCompanyId 公司ID
     * @return 当前电梯台量
     * @description 查询维保公司下的实际电梯台量
     * @date 2019/12/12 5:16 PM
     */
    public int countLiftNum(Long mtCompanyId) {
        QueryWrapper<PlatformCompanyLiftRelevance> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<PlatformCompanyLiftRelevance> lambdaQueryWrapper = queryWrapper.lambda();
        lambdaQueryWrapper.eq(PlatformCompanyLiftRelevance::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.ne(PlatformCompanyLiftRelevance::getLiftCompanyStatus, CommonEnum.LiftStatus.STOP_INSURANCE.getCode());
        lambdaQueryWrapper.eq(PlatformCompanyLiftRelevance::getDeleteFlag, '0');
        return count(lambdaQueryWrapper);
    }

    /**
     * @param mtCompanyId 公司id
     * @param projectId 项目id
     * @return List<PlatformCompanyLiftRelevance> 公司电梯关联列表
     * @description 获取公司电梯关联列表
     * @date 2020/1/11 3:06 下午
     */
    public List<PlatformCompanyLiftRelevance> getCompanyLiftList(Long mtCompanyId, Long projectId){
        //根据项目id和公司id查询电梯列表
        List<ProjectLiftRelevance> liftList = projectLiftRelevanceService.findLiftList(mtCompanyId, projectId);
        Collection<Long> list = liftList.stream().map(ProjectLiftRelevance::getRelevanceId).collect(Collectors.toList());
        if (CollUtil.isEmpty(list)) return new ArrayList<>();
        return baseMapper.selectBatchIds(list);
    }

    /**
     * @param projectId 项目ID
     * @param mtCompanyId 公司ID
     * @return
     * @description 停止服务消息推送
     * @date 2020/5/5 9:26 下午
     */
    public void sendStopMessage(Long projectId, Long mtCompanyId) {
        //消息推送
        List<Long> userIds = new ArrayList<>();
        Region region = pushUserService.findRegionByProject(projectId, mtCompanyId);
        if (Objects.nonNull(region)) {
            userIds.addAll(region.members());
        }
        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);
            PushMessage pushMessage = PushMessage.workProjectStopService(detail.getAreaName(), detail.getProjectName(), detail.getNum());
            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 projectId 项目ID
     * @param mtCompanyId 公司ID
     * @return
     * @description 恢复服务消息推送
     * @date 2020/5/5 9:26 下午
     */
    public void sendRecoverMessage(Long projectId, Long mtCompanyId) {
        //消息推送
        List<Long> userIds = new ArrayList<>();
        Region region = pushUserService.findRegionByProject(projectId, mtCompanyId);
        if (Objects.nonNull(region)) {
            userIds.addAll(region.members());
        }
        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);
            PushMessage pushMessage = PushMessage.workProjectRecoverService(detail.getAreaName(), detail.getProjectName());
            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 liftIdList 电梯id列表
     * @return 1.成功, 0.失败, 消息描述
     * @description 服务操作
     * @date 2019/12/10 5:42 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse serviceOperate(ProjectRequest request) {
        Integer operate = request.getOperate();
        Long projectId = request.getProjectId();
        Long mtCompanyId = request.getMtCompanyId();
        Project project = new Project();
        project.setId(projectId);
        List<PlatformCompanyLiftRelevance> resultList = getCompanyLiftList(mtCompanyId,projectId);
        switch (operate) {
            //恢复服务
            case 1:
                //判断当前公司台量是否大于企业设置的台量
                boolean judgeResult = maintenanceService.judge(mtCompanyId);
                if (!judgeResult) {
                    return RestResponse.fail(MessageUtils.get("msg.limit.num"));
                }
                project.setStartDate(request.getStartDate());
                project.setEndDate(request.getEndDate());
                project.setProjectStatus(CommonEnum.ProjectStatus.IN_SERVICE.getCode());
                boolean result = projectService.updateById(project);
                if (!result)
                    return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
                if (CollUtil.isNotEmpty(resultList)) {
                    //电梯状态设置为正常
                    resultList.forEach(entry -> entry.setLiftCompanyStatus(CommonEnum.LiftStatus.NORMAL.getCode()));
                    boolean ret = updateBatchById(resultList);
                    if (!ret) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return RestResponse.fail(MessageUtils.get("msg.modify.batch.fail"));
                    }
                }
                //恢复服务发送消息
                sendRecoverMessage(projectId, mtCompanyId);
                break;
            //停止服务
            case 2:
                //修改项目状态为停止
                project.setProjectStatus(CommonEnum.ProjectStatus.STOP_SERVICE.getCode());
                //设置停止时间及描述
                project.setEndRemarks(request.getEndRemarks());
                project.setStopTime(request.getStopTime());
                boolean projectResult = projectService.updateById(project);
                if (!projectResult)
                    return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
                //停止服务发送消息
                sendStopMessage(projectId, mtCompanyId);
                if (CollUtil.isNotEmpty(resultList)) {
                    //批量停保项目下的电梯
                    resultList.forEach(entry -> entry.setLiftCompanyStatus(CommonEnum.LiftStatus.STOP_INSURANCE.getCode()));
                    boolean batchResult = updateBatchById(resultList);
                    if (!batchResult) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return RestResponse.fail(MessageUtils.get("msg.modify.batch.fail"));
                    }
                    //根据项目id和公司id查询电梯列表
                    List<ProjectLiftRelevance> liftList = projectLiftRelevanceService.findLiftList(mtCompanyId, projectId);
                    Collection<Long> list = liftList.stream().map(ProjectLiftRelevance::getLiftId).collect(Collectors.toList());
                    //批量清除维保计划
                    boolean planResult = maintenancePlanService.removeMaintenancePlan(mtCompanyId, list);
                    if (!planResult) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return RestResponse.fail(MessageUtils.get("msg.modify.batch.fail"));
                    }
                }
                break;
            //继续服务
            case 3:
                project.setEndDate(request.getEndDate());
                project.setProjectStatus(CommonEnum.ProjectStatus.IN_SERVICE.getCode());
                boolean ret = projectService.updateById(project);
                if (!ret) return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
                break;
            default:
                break;
        }
        return RestResponse.success(null, MessageUtils.get("msg.project.operate.success"));
    }

    /**
     * @param request relevanceId 公司电梯关联表主键id
     * @param request mtCompanyId 公司id
     * @param request liftId 电梯id
     * @return 1.成功, 0.失败, 消息描述
     * @description 更新电梯状态为停保或恢复为正常, 并清除维保计划
     * @date 2019/12/5 5:24 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse stopOrRecover(LiftRequest request) {
        PlatformCompanyLiftRelevance entry = new PlatformCompanyLiftRelevance();
        entry.setId(request.getRelevanceId());
        //恢复电梯为正常状态
        if (Objects.equals(0, request.getOperate())) {
            Optional<Lift> lift = liftService.getOne(null, request.getLiftId());
            Integer liftStatus = lift.map(Lift::getLiftStatus).orElse(null);
            // 1：弃用 2：正常
            if (Objects.equals(1, liftStatus)) return RestResponse.fail(MessageUtils.get("msg.error.lift.status"));
            entry.setLiftCompanyStatus(CommonEnum.LiftStatus.NORMAL.getCode());
            updateById(entry);
        } else {
            entry.setLiftCompanyStatus(CommonEnum.LiftStatus.STOP_INSURANCE.getCode());
            updateById(entry);
            //清除维保计划
            maintenancePlanService.cleanPlan(request.getMtCompanyId(), request.getLiftId());
        }
        return RestResponse.success(null, MessageUtils.get("msg.modify.success"));
    }

    /**
     * @param request companyIdList 公司电梯关联表主键id列表
     * @param request companyId 公司id
     * @param request idList 电梯id列表
     * @return 1.成功, 0.失败, 消息描述
     * @description 批量更新电梯状态为停保, 并清除维保计划
     * @date 2019/12/31 9:54 AM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse batchStopInsurance(LiftRequest request) {
        //公司电梯关联表主键id列表
        List<Long> companyIdList = request.getRelevanceIdList();
        //批量查询公司下电梯数据
        List<PlatformCompanyLiftRelevance> list = baseMapper.selectBatchIds(companyIdList);
        if (CollUtil.isEmpty(list)) {
            return RestResponse.success();
        }
        list.forEach(entry -> entry.setLiftCompanyStatus(CommonEnum.LiftStatus.STOP_INSURANCE.getCode()));
        //批量更新公司下电梯信息为停保
        boolean result = updateBatchById(list);
        if (!result) {
            return RestResponse.fail(MessageUtils.get("msg.modify.batch.fail"));
        }
        //批量清除维保计划
        maintenancePlanService.removeMaintenancePlan(request.getMtCompanyId(), request.getLiftList());
        return RestResponse.success(null, MessageUtils.get("msg.modify.batch.success"));
    }

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

    /**
     * 根据维保公司id和电梯id查找关联记录
     * @author wcz
     * @param mtCompanyId 维保公司id
     * @param liftId 电梯id
     * @return PlatformCompanyLiftRelevance
     */
    public PlatformCompanyLiftRelevance findByMtCompanyAndLift(Long mtCompanyId, Long liftId) {
        QueryWrapper<PlatformCompanyLiftRelevance> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<PlatformCompanyLiftRelevance> lambdaQueryWrapper = queryWrapper.lambda();
        lambdaQueryWrapper.eq(PlatformCompanyLiftRelevance::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.eq(PlatformCompanyLiftRelevance::getLiftId, liftId);
        //只查询一条
        lambdaQueryWrapper.last("LIMIT 1");
        return getOne(lambdaQueryWrapper);
    }
}
