package com.njcn.csdevice.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.csdevice.enums.AlgorithmResponseEnum;
import com.njcn.csdevice.mapper.CsDeviceUserPOMapper;
import com.njcn.csdevice.mapper.CsEquipmentDeliveryMapper;
import com.njcn.csdevice.mapper.CsMarketDataMapper;
import com.njcn.csdevice.pojo.param.UserDevParam;
import com.njcn.csdevice.pojo.po.*;
import com.njcn.csdevice.pojo.vo.CsLedgerVO;
import com.njcn.csdevice.pojo.vo.DevCountVO;
import com.njcn.csdevice.pojo.vo.DevUserVO;
import com.njcn.csdevice.service.*;
import com.njcn.csharmonic.api.EventUserFeignClient;
import com.njcn.csharmonic.param.CsEventUserQueryParam;
import com.njcn.csharmonic.pojo.vo.EventDetailVO;
import com.njcn.cssystem.api.FeedBackFeignClient;
import com.njcn.cssystem.pojo.param.CsFeedbackQueryParm;
import com.njcn.cssystem.pojo.vo.CsFeedbackVO;
import com.njcn.user.api.UserFeignClient;
import com.njcn.user.enums.AppRoleEnum;
import com.njcn.user.pojo.po.User;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static java.util.Objects.isNull;

/**
 * 
 * Description:
 * Date: 2023/6/27  9:40【需求编号】
 *
 * @author clam
 * @version V1.0.0
 */
@Service
@RequiredArgsConstructor
public class CsDeviceUserPOServiceImpl extends ServiceImpl<CsDeviceUserPOMapper, CsDeviceUserPO> implements CsDeviceUserPOService{

    private final CsDevModelRelationService csDevModelRelationService;
    private final ICsLedgerService iCsLedgerService;
    private final CsEquipmentDeliveryMapper csEquipmentDeliveryMapper;
    private final RoleEngineerDevService roleEngineerDevService;
    private final AppLineTopologyDiagramService appLineTopologyDiagramService;
    private final CsTouristDataPOService csTouristDataPOService;
    private final CsLinePOService csLinePOService;
    private final CsMarketDataMapper csMarketDataMapper;
    private final EventUserFeignClient eventUserFeignClient;
    private final UserFeignClient userFeignClient;
    private final FeedBackFeignClient feedBackFeignClient;
    private final IMqttUserService mqttUserService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(String id) {
        CsDeviceUserPO one = this.lambdaQuery().eq(CsDeviceUserPO::getDeviceId, id).one();
        if(!isNull(one)){
            throw new BusinessException(AlgorithmResponseEnum.LOSE_EFFICACY);
        }
        String userIndex = RequestUtil.getUserIndex();
        CsDeviceUserPO csDevice = new CsDeviceUserPO();
        //设备PrimaryUserId与SubUserId相同就是主用户
        csDevice.setDeviceId(id);
        csDevice.setPrimaryUserId(userIndex);
        csDevice.setSubUserId(userIndex);
        csDevice.setStatus("1");
        boolean save = this.save(csDevice);
        return save;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean share(List<String> ids) {
        ids.stream().forEach(id->{
            List<CsDeviceUserPO> list = this.lambdaQuery().eq(CsDeviceUserPO::getDeviceId, id).eq(CsDeviceUserPO::getStatus,"1" ).list();

            if(CollectionUtils.isEmpty(list)){
                throw new BusinessException(AlgorithmResponseEnum.DATA_LOSE);

            }
            String userIndex = RequestUtil.getUserIndex();
            String userRole = RequestUtil.getUserRole();
            List<String> strings = JSONArray.parseArray(userRole, String.class);
            if(CollectionUtils.isEmpty(strings)){
                throw new BusinessException(AlgorithmResponseEnum.UNKNOW_ROLE);

            }
            userRole=strings.get(0);
            //分享只能给vip用户分享
            if(
                    !Objects.equals(userRole, AppRoleEnum.APP_VIP_USER.getCode())
            ){
                throw new BusinessException(AlgorithmResponseEnum.UNKNOW_ROLE);

            }
            CsDeviceUserPO one = this.lambdaQuery().eq(CsDeviceUserPO::getDeviceId, id).eq(CsDeviceUserPO::getStatus,"1" ).eq(CsDeviceUserPO::getSubUserId,userIndex).one();
            if(!isNull(one)){
                return;
            }
            CsDeviceUserPO csDeviceUserPO = list.get(0);
            csDeviceUserPO.setSubUserId(userIndex);
            boolean save = this.save(csDeviceUserPO);
        });


        return true;
    }

    @Override
    public DevCountVO devCount(String id) {
        QueryWrapper<CsEquipmentDeliveryPO> queryWrapper = new QueryWrapper<>();

        DevCountVO devCountVO = new DevCountVO();

        String userRole = RequestUtil.getUserRole();
        List<String> strings = JSONArray.parseArray(userRole, String.class);
        if(CollectionUtils.isEmpty(strings)){
            throw new BusinessException(AlgorithmResponseEnum.UNKNOW_ROLE);

        }
        userRole=strings.get(0);

        List<String> device = roleEngineerDevService.getDevice();
        if(CollectionUtils.isEmpty(device)){
            devCountVO.setOnLineDevCount(0);
            devCountVO.setOnLineDevs(new ArrayList<>());
            devCountVO.setOffLineDevCount(0);
            devCountVO.setOffLineDevs(new ArrayList<>());
        }else {
            queryWrapper.clear();
            queryWrapper.in("id",device);

            List<CsEquipmentDeliveryPO> csEquipmentDeliveryPOS = csEquipmentDeliveryMapper.selectList(queryWrapper);
            List<CsEquipmentDeliveryPO> collect = csEquipmentDeliveryPOS.stream().filter(temp -> temp.getRunStatus() == 1).collect(Collectors.toList());
            List<CsEquipmentDeliveryPO> collect2= csEquipmentDeliveryPOS.stream().filter(temp -> temp.getRunStatus() == 2).collect(Collectors.toList());
            devCountVO.setOnLineDevCount(collect2.size());
            devCountVO.setOnLineDevs(collect2);
            devCountVO.setOffLineDevCount(collect.size());
            devCountVO.setOffLineDevs(collect);
            List<String> roleengineer = roleEngineerDevService.getRoleengineer();
            devCountVO.setEningerCount(roleengineer.size());
        }

        List<CsLedgerVO> deviceTree = iCsLedgerService.getDeviceTree();
        //由于多加了一程便携式设备
        List<String> collect1 = deviceTree.stream()
                .map(CsLedgerVO::getChildren).flatMap(Collection::stream)
                .filter(temp -> temp.getId().equals(id))
                .map(CsLedgerVO::getChildren).flatMap(Collection::stream)
                .map(CsLedgerVO::getChildren).flatMap(Collection::stream)
                .map(CsLedgerVO::getId).collect(Collectors.toList());
        //求交集
        device.retainAll(collect1);
        if(CollectionUtils.isEmpty(device)){
            devCountVO.setCurrentOnLineDevCount(0);
            devCountVO.setCurrentOnLineDevs(new ArrayList<>());
            devCountVO.setCurrentOffLineDevCount(0);
            devCountVO.setCurrentOffLineDevs(new ArrayList<>());
            devCountVO.setCurrentProjectCount(0);

        }else {
            queryWrapper.clear();
            queryWrapper.in("id",device);

            List<CsEquipmentDeliveryPO> csEquipmentDeliveryPOS = csEquipmentDeliveryMapper.selectList(queryWrapper);
            List<CsEquipmentDeliveryPO> collect = csEquipmentDeliveryPOS.stream().filter(temp -> temp.getRunStatus() == 1).collect(Collectors.toList());
            List<CsEquipmentDeliveryPO> collect2= csEquipmentDeliveryPOS.stream().filter(temp -> temp.getRunStatus() == 2).collect(Collectors.toList());
            devCountVO.setCurrentOnLineDevCount(collect2.size());
            devCountVO.setCurrentOnLineDevs(collect2);
            devCountVO.setCurrentOffLineDevCount(collect.size());
            devCountVO.setCurrentOffLineDevs(collect);
            List<CsLedger> list = iCsLedgerService.lambdaQuery().eq(CsLedger::getPid, id).eq(CsLedger::getState, 1).list();
            devCountVO.setCurrentProjectCount(list.size());
        }
        CsEventUserQueryParam csEventUserQueryParam = new CsEventUserQueryParam();
        csEventUserQueryParam.setStatus("0");
        List<EventDetailVO> data = eventUserFeignClient.queryEventList(csEventUserQueryParam).getData();
        List<EventDetailVO> event = data.stream().filter(temp -> temp.getType() == 0).collect(Collectors.toList());
        List<EventDetailVO> harmonic = data.stream().filter(temp -> temp.getType() == 1).collect(Collectors.toList());
        List<EventDetailVO> alarm = data.stream().filter(temp -> temp.getType() == 3).collect(Collectors.toList());

        if(Objects.equals(userRole, AppRoleEnum.APP_VIP_USER.getCode())){
            alarm = alarm.stream().filter(temp -> Objects.equals("3", temp.getLevel())).collect(Collectors.toList());
        }
        List<EventDetailVO> run = data.stream().filter(temp -> temp.getType() == 2).collect(Collectors.toList());
        if(Objects.equals(userRole,AppRoleEnum.APP_VIP_USER.getCode())||Objects.equals(userRole,AppRoleEnum.TOURIST.getCode())
        ||Objects.equals(userRole,AppRoleEnum.MARKET_USER.getCode())){
            devCountVO.setFeedBackCount(0);

        }else {
            CsFeedbackQueryParm csFeedbackQueryParm = new CsFeedbackQueryParm();
            csFeedbackQueryParm.setPageNum(1);
            csFeedbackQueryParm.setPageSize(100000);
            csFeedbackQueryParm.setStatus("1");
            Page<CsFeedbackVO> data1 = feedBackFeignClient.queryFeedBackPage(csFeedbackQueryParm).getData();
            List<CsFeedbackVO> collect = data1.getRecords().stream().filter(temp -> !Objects.equals(temp.getUserId(), RequestUtil.getUserIndex())).collect(Collectors.toList());
            devCountVO.setFeedBackCount(collect.size());
        }

        //todo 后续添加警告数,事件数
        devCountVO.setEventCount(event.size());
        devCountVO.setAlarmCount(alarm.size());
        devCountVO.setRunCount(run.size());
        devCountVO.setHarmonicCount(harmonic.size());
        List<EventDetailVO> curEvent = event.stream().filter(temp -> Objects.equals(temp.getEngineeringid(), id)).collect(Collectors.toList());
        List<EventDetailVO> curHarmonic = harmonic.stream().filter(temp -> Objects.equals(temp.getEngineeringid(), id)).collect(Collectors.toList());
        List<EventDetailVO> curAlarm = alarm.stream().filter(temp -> Objects.equals(temp.getEngineeringid(), id)).collect(Collectors.toList());
        List<EventDetailVO> curRun = run.stream().filter(temp -> Objects.equals(temp.getEngineeringid(), id)).collect(Collectors.toList());

        devCountVO.setCurrentEventCount(curEvent.size());
        devCountVO.setCurrentAlarmCount(curAlarm.size());
        devCountVO.setCurrentRunCount(curRun.size());
        devCountVO.setCurrentHarmonicCount(curHarmonic.size());


        return devCountVO;
    }
    /** 
    * @Description: 判断当前用户是否是主用户 0-否1-是
    * @Param:  
    * @return: java.lang.String 
    * @Author: clam
    * @Date: 2023/7/25 
    */ 
    @Override
    public String isPrimaryUser(String deviceId) {
        String userIndex = RequestUtil.getUserIndex();
        List<CsDeviceUserPO> list = this.lambdaQuery().eq(CsDeviceUserPO::getDeviceId, deviceId).eq(CsDeviceUserPO::getStatus, "1").eq(CsDeviceUserPO::getPrimaryUserId, userIndex).list();
        String number = CollectionUtils.isEmpty(list) ? "0" : "1";
        return number;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean transfer(List<String> ids,String useId) {
        String userIndex = useId;
        ids.forEach(eid->{
            List<CsDeviceUserPO> list = this.lambdaQuery().eq(CsDeviceUserPO::getDeviceId, eid).eq(CsDeviceUserPO::getStatus,"1" ).list();
            if(CollectionUtils.isEmpty(list)){
                throw new BusinessException(AlgorithmResponseEnum.DATA_LOSE);

            }
            this.lambdaUpdate().eq(CsDeviceUserPO::getDeviceId, eid).eq(CsDeviceUserPO::getStatus,"1" ).apply("primary_user_id=sub_user_id").set(CsDeviceUserPO::getPrimaryUserId,userIndex).set(CsDeviceUserPO::getSubUserId,userIndex).update();
            this.lambdaUpdate().eq(CsDeviceUserPO::getDeviceId, eid).eq(CsDeviceUserPO::getStatus,"1" ).apply("primary_user_id<>sub_user_id").set(CsDeviceUserPO::getPrimaryUserId,userIndex).update();

        });
        //工程人员接受到移交设备，默认把工程加入关注列表

        String role = RequestUtil.getUserRole();
        List<String> strings = JSONArray.parseArray(role, String.class);
        if(CollectionUtils.isEmpty(strings)){
            throw new BusinessException(AlgorithmResponseEnum.UNKNOW_ROLE);
        }
        List<CsLedger> list = iCsLedgerService.lambdaQuery().in(CsLedger::getId, ids).list();
        String[] split = list.get(0).getPids().split(",");
        role=strings.get(0);
        if(Objects.equals(role, AppRoleEnum.ENGINEERING_USER.getCode())){
            CsMarketData csMarketData = new CsMarketData();
            csMarketData.setEngineerId(split[1]);
            csMarketData.setUserId(RequestUtil.getUserIndex());
            QueryWrapper<CsMarketData> queryWrap = new QueryWrapper<>();
            queryWrap.setEntity(csMarketData);
            List<CsMarketData> csMarketData1 = csMarketDataMapper.selectList(queryWrap);
            if(CollectionUtils.isEmpty(csMarketData1)){
                csMarketDataMapper.insert(csMarketData);
            }

        }




        return true;
    }

    @Override
//    @Transactional(rollbackFor = {Exception.class})
    public Boolean delete(String eid) {
        String userIndex = RequestUtil.getUserIndex();
        List<CsDeviceUserPO> list = this.lambdaQuery().eq(CsDeviceUserPO::getDeviceId, eid).eq(CsDeviceUserPO::getStatus, "1").eq(CsDeviceUserPO::getPrimaryUserId, userIndex).list();
        if(CollectionUtils.isEmpty(list)){
            throw new BusinessException(AlgorithmResponseEnum.DATA_LOSE);

        }
        CsEquipmentDeliveryPO csEquipmentDeliveryPO =new CsEquipmentDeliveryPO();
        csEquipmentDeliveryPO.setId(eid);
        csEquipmentDeliveryPO.setRunStatus(0);

        csEquipmentDeliveryMapper.updateById(csEquipmentDeliveryPO);
        this.lambdaUpdate().eq(CsDeviceUserPO::getDeviceId, eid).set(CsDeviceUserPO::getStatus,"0").update();

        CsEquipmentDeliveryPO temp = csEquipmentDeliveryMapper.selectById(eid);
        mqttUserService.deleteUser(temp.getNdid());
        List<CsLedger> list1 = iCsLedgerService.lambdaQuery().eq(CsLedger::getPid, eid).list();
        if(!CollectionUtils.isEmpty(list1)){
            List<String> collect = list1.stream().map(CsLedger::getId).collect(Collectors.toList());
            LambdaQueryWrapper<CsLinePO> csLinePOLambdaQueryWrapper = new LambdaQueryWrapper<>();
            csLinePOLambdaQueryWrapper.in(CsLinePO::getLineId,collect);
            csLinePOService.remove(csLinePOLambdaQueryWrapper);
            QueryWrapper<AppLineTopologyDiagramPO> appLineTopologyDiagramPOQueryWrapper = new QueryWrapper<>();
            appLineTopologyDiagramPOQueryWrapper.clear();
            appLineTopologyDiagramPOQueryWrapper.in("line_id",collect);
            appLineTopologyDiagramService.remove(appLineTopologyDiagramPOQueryWrapper);
//            appLineTopologyDiagramService.lambdaUpdate().in(AppLineTopologyDiagramPO::getLineId,collect).set(AppLineTopologyDiagramPO::getStatus,0).update();
        }
        //删除监测点，设备
        LambdaQueryWrapper<CsLedger>  csLedgerLambdaQueryWrapper = new LambdaQueryWrapper<>();
        csLedgerLambdaQueryWrapper.clear();
        csLedgerLambdaQueryWrapper.eq(CsLedger::getId,eid);
        iCsLedgerService.remove(csLedgerLambdaQueryWrapper);
        csLedgerLambdaQueryWrapper.clear();
        csLedgerLambdaQueryWrapper.eq(CsLedger::getPid,eid);
        iCsLedgerService.remove(csLedgerLambdaQueryWrapper);
//        iCsLedgerService.lambdaUpdate().eq(CsLedger::getId,eid).set(CsLedger::getState,0).update();
//        iCsLedgerService.lambdaUpdate().eq(CsLedger::getPid,eid).set(CsLedger::getState,0).update();
        QueryWrapper<CsTouristDataPO> queryWrap = new QueryWrapper<>();
        queryWrap.eq("device_id",eid);
        csTouristDataPOService.getBaseMapper().delete(queryWrap);
        csDevModelRelationService.lambdaUpdate().eq(CsDevModelRelationPO::getDevId,eid).set(CsDevModelRelationPO::getStatus,0).update();

        return true;
    }
    /** 
    * @Description: 主用户发起取消分享，则可选择取消拥有该设备权限的子用户。子用户发起取消分享则只是移除自己拥有该设备权限
    * @Param:  
    * @return: java.lang.Boolean 
    * @Author: clam
    * @Date: 2023/7/25 
    */ 
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean cancelShare(String eid,String userId) {
        String userIndex = RequestUtil.getUserIndex();
//        //主用户
//        if(Objects.equals(isPrimaryUser(eid),"1")){
//           this.lambdaUpdate().eq(CsDeviceUserPO::getDeviceId, eid).ne(CsDeviceUserPO::getSubUserId,userIndex).set(CsDeviceUserPO::getStatus,"0").update();
//        }
//        //子用户
//        else if (Objects.equals(isPrimaryUser(eid),"0")) {
            this.lambdaUpdate().eq(CsDeviceUserPO::getDeviceId, eid).eq(CsDeviceUserPO::getSubUserId,userId).set(CsDeviceUserPO::getStatus,"0").update();

//        }

        return true;
    }

    @Override
    public Boolean recovery(String eid) {
        String userIndex = RequestUtil.getUserIndex();
        List<CsDeviceUserPO> list = this.lambdaQuery().eq(CsDeviceUserPO::getDeviceId, eid).eq(CsDeviceUserPO::getStatus, "0").eq(CsDeviceUserPO::getPrimaryUserId, userIndex).list();
        if(CollectionUtils.isEmpty(list)){
            throw new BusinessException(AlgorithmResponseEnum.DATA_LOSE);

        }
        CsEquipmentDeliveryPO csEquipmentDeliveryPO =new CsEquipmentDeliveryPO();
        csEquipmentDeliveryPO.setId(eid);
        csEquipmentDeliveryPO.setRunStatus(1);
        csEquipmentDeliveryMapper.updateById(csEquipmentDeliveryPO);
        this.lambdaUpdate().eq(CsDeviceUserPO::getDeviceId, eid).set(CsDeviceUserPO::getStatus,"1").update();
        return true;
    }

    @Override
    public DevUserVO queryUserById(String devId) {
        List<CsDeviceUserPO> list = this.lambdaQuery().eq(CsDeviceUserPO::getDeviceId, devId).eq(CsDeviceUserPO::getStatus, "1").list();
        if (CollectionUtils.isEmpty(list)) {
            throw new BusinessException(AlgorithmResponseEnum.DATA_ARRAY_MISSING);
        }
        List<String> collect = list.stream().map(CsDeviceUserPO::getSubUserId).distinct().collect(Collectors.toList());
        List<User> data = userFeignClient.appuserByIdList(collect).getData();
        String primaryUserId = list.get(0).getPrimaryUserId();
        List<User> subUser = data.stream().filter(temp -> !Objects.equals(temp.getId(), primaryUserId)).collect(Collectors.toList());
        List<User> primaryUser = data.stream().filter(temp -> Objects.equals(temp.getId(), primaryUserId)).collect(Collectors.toList());
        DevUserVO devUser = new DevUserVO();
        devUser.setDevId(devId);
        devUser.setSubUsers(subUser);
        devUser.setMasterUser(primaryUser.get(0));
        return devUser;
    }

    @Override
    public List<String> findUserById(String devId) {
        List<String> result = new ArrayList<>();
        List<CsDeviceUserPO> list = this.lambdaQuery().eq(CsDeviceUserPO::getDeviceId,devId).list();
        if (CollectionUtil.isNotEmpty(list)){
            result = list.stream().map(CsDeviceUserPO::getSubUserId).collect(Collectors.toList());
        }
        return result;
    }

    @Override
    public List<String> findDevByUserId(String userId) {
        List<String> result = new ArrayList<>();
        List<CsDeviceUserPO> list = this.lambdaQuery().eq(CsDeviceUserPO::getPrimaryUserId,userId).list();
        if (CollectionUtil.isNotEmpty(list)){
            result = list.stream().map(CsDeviceUserPO::getDeviceId).collect(Collectors.toList());
        }
        return result;
    }

    @Override
    public void channelDevByUserId(UserDevParam param) {
        LambdaQueryWrapper<CsDeviceUserPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CsDeviceUserPO::getPrimaryUserId,param.getUserId())
                .in(CsDeviceUserPO::getDeviceId,param.getList());
        this.remove(queryWrapper);
    }
}
