package com.njcn.csdevice.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.csdevice.mapper.CsLinePOMapper;
import com.njcn.csdevice.mapper.PqsDeviceUnitMapper;
import com.njcn.csdevice.pojo.dto.DevDetailDTO;
import com.njcn.csdevice.pojo.po.CsDeviceUserPO;
import com.njcn.csdevice.pojo.po.CsEquipmentDeliveryPO;
import com.njcn.csdevice.pojo.po.CsLedger;
import com.njcn.csdevice.pojo.po.CsLinePO;
import com.njcn.csdevice.pojo.vo.CsMarketDataVO;
import com.njcn.csdevice.pojo.vo.CsTouristDataParmVO;
import com.njcn.csdevice.service.*;
import com.njcn.csharmonic.api.PqGovernPlanFeignClient;
import com.njcn.csharmonic.pojo.po.PqGovernPlan;
import com.njcn.device.biz.pojo.po.PqsDeviceUnit;
import com.njcn.user.api.UserFeignClient;
import com.njcn.user.enums.AppRoleEnum;
import com.njcn.user.pojo.constant.UserType;
import com.njcn.user.pojo.vo.UserVO;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: cdf
 * @CreateTime: 2025-12-23
 * @Description:
 */
@Service
@RequiredArgsConstructor
public class CsCommTerminalServiceImpl implements CsCommTerminalService {

    private final PqsDeviceUnitMapper pqsDeviceUnitMapper;
    private final CsDeviceUserPOService csDeviceUserPOService;
    private final CsLinePOMapper csLinePOMapper;
    private final UserFeignClient userFeignClient;
    private final CsEquipmentDeliveryService csEquipmentDeliveryService;
    private final CsMarketDataService csMarketDataService;
    private final ICsLedgerService csLedgerService;
    private final CsTouristDataPOService csTouristDataPOService;
    private final PqGovernPlanFeignClient pqGovernPlanFeignClient;


    @Override
    public List<String> getLineIdsByUser(String userId) {
        List<String> result = new ArrayList<>();
        List<String> devIds = commGetDevIds(userId);
        if (CollUtil.isEmpty(devIds)) {
            return result;
        }

        LambdaQueryWrapper<CsLinePO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(CsLinePO::getLineId).in(CsLinePO::getDeviceId, devIds)
                .eq(CsLinePO::getStatus, DataStateEnum.ENABLE.getCode());
        List<CsLinePO> poList = csLinePOMapper.selectList(lambdaQueryWrapper);
        if (CollUtil.isNotEmpty(poList)) {
            result = poList.stream().map(CsLinePO::getLineId).distinct().collect(Collectors.toList());
        }
        return result;
    }

    @Override
    public List<String> getPqUserIdsByUser(String userId) {
        List<String> result = new ArrayList<>();
        List<String> lineIds = getLineIdsByUser(userId);
        if (CollUtil.isEmpty(lineIds)) {
            return result;
        }
        List<PqGovernPlan> governPlans = pqGovernPlanFeignClient.getListByMonitorPoint(lineIds).getData();
        if (CollUtil.isEmpty(governPlans)) {
            return result;
        }
        return governPlans.stream().map(PqGovernPlan::getPid).distinct().collect(Collectors.toList());
    }

    @Override
    public PqsDeviceUnit lineUnitDetail(String lineId) {
        PqsDeviceUnit pqsDeviceUnit = pqsDeviceUnitMapper.selectById(lineId);
        if(Objects.isNull(pqsDeviceUnit)){
            pqsDeviceUnit = new PqsDeviceUnit();
        }
        return pqsDeviceUnit;
    }


    @Override
    public List<String> commGetDevIds(String userId) {
        UserVO userVO = userFeignClient.getUserById(userId).getData();
        List<String> devIds = new ArrayList<>();
        if (userVO.getType().equals(UserType.SUPER_ADMINISTRATOR) || userVO.getType().equals(UserType.ADMINISTRATOR)) {
            devIds = csEquipmentDeliveryService.getAll().stream().map(CsEquipmentDeliveryPO::getId).collect(Collectors.toList());
        } else {
            //note 黄是在cs_market_data写入数据，是用户和工程的关系；
            // 但是权限根据用户和设备来判断会有问题，还需要用户和工程的关系(针对营销 工程用户)，所以这边还要添加用户和工程的关系。
            // 如果是营销 工程用户 没有配置相关工程，直接返回空的设备列表；如果有数据，也要判断下当前关注的工程里面是否包含主用户的设备，可能出现没有关注该工程，但是因为是设备的主用户导致数据统计错误
            String roleString = RequestUtil.getUserRole();
            if (roleString.contains(AppRoleEnum.MARKET_USER.getCode()) || roleString.contains(AppRoleEnum.ENGINEERING_USER.getCode())) {
                List<CsMarketDataVO> list = csMarketDataService.queryByUseId(userId);
                if (CollUtil.isNotEmpty(list)) {
                    List<String> engineerIds = list.stream().map(CsMarketDataVO::getEngineerId).distinct().collect(Collectors.toList());
                    List<DevDetailDTO> devs = csLedgerService.getDevInfoByEngineerIds(engineerIds);
                    devIds = devs.stream().map(DevDetailDTO::getEquipmentId).distinct().collect(Collectors.toList());
                }
            }
            //note 如果是游客，则还需要加入系统配置的设备
            else if (roleString.contains(AppRoleEnum.TOURIST.getCode())) {
                devIds.addAll(csTouristDataPOService.queryAll().stream().map(CsTouristDataParmVO::getDeviceId).distinct().collect(Collectors.toList()));
            }
            //note 如果是普通用户，则需要根据用户权限来获取设备列表
            else {
                List<CsDeviceUserPO> devList = csDeviceUserPOService.lambdaQuery().select(CsDeviceUserPO::getDeviceId)
                        .and(w -> w.eq(CsDeviceUserPO::getPrimaryUserId, userId).or().eq(CsDeviceUserPO::getSubUserId, userId))
                        .eq(CsDeviceUserPO::getStatus, DataStateEnum.ENABLE.getCode()).list();
                devIds = devList.stream().map(CsDeviceUserPO::getDeviceId).distinct().collect(Collectors.toList());
            }
        }
        if (!CollUtil.isEmpty(devIds)) {
            devIds = devIds.stream().distinct().collect(Collectors.toList());
        }
        return devIds;
    }

    @Override
    public List<DevDetailDTO> getLedgerByLineId(List<String> id) {
        List<DevDetailDTO> result = new ArrayList<>();
        List<CsLedger> lineLedgers = csLedgerService.listByIds(id);
        Set<String> equipmentIds = new HashSet<>();
        Set<String> projectIds = new HashSet<>();
        Set<String> engineeringIds = new HashSet<>();

        if (CollUtil.isEmpty(lineLedgers)) {
            return result;
        }
        for (CsLedger item : lineLedgers) {
            String pids = item.getPids();
            if (pids == null) {
                continue;
            }
            String[] pidArr = pids.split(",");
            if (pidArr.length < 4) {
                continue;
            }
            engineeringIds.add(pidArr[1]);
            projectIds.add(pidArr[2]);
            equipmentIds.add(pidArr[3]);
        }

        Map<String, CsLinePO> csLinePoMap = csLinePOMapper.selectBatchIds(id)
                .stream().collect(Collectors.toMap(CsLinePO::getLineId, item -> item));
        Map<String, CsLedger> equipmentLedgerMap = csLedgerService.listByIds(equipmentIds)
                .stream().collect(Collectors.toMap(CsLedger::getId, item -> item));
        Map<String, CsEquipmentDeliveryPO> equipmentDeliveryMap = csEquipmentDeliveryService.listByIds(equipmentIds)
                .stream().collect(Collectors.toMap(CsEquipmentDeliveryPO::getId, item -> item));
        Map<String, CsLedger> projectLedgerMap = csLedgerService.listByIds(projectIds)
                .stream().collect(Collectors.toMap(CsLedger::getId, item -> item));
        Map<String, CsLedger> engineeringLedgerMap = csLedgerService.listByIds(engineeringIds)
                .stream().collect(Collectors.toMap(CsLedger::getId, item -> item));

        for (CsLedger item : lineLedgers) {
            String pids = item.getPids();
            if (pids == null) {
                continue;
            }
            String[] pidArr = pids.split(",");
            if (pidArr.length < 4) {
                continue;
            }

            String engineeringId = pidArr[1];
            String projectId = pidArr[2];
            String equipmentId = pidArr[3];

            CsLedger engineeringLedger = engineeringLedgerMap.get(engineeringId);
            CsLedger projectLedger = projectLedgerMap.get(projectId);
            CsLedger equipmentLedger = equipmentLedgerMap.get(equipmentId);
            if (engineeringLedger == null || projectLedger == null || equipmentLedger == null) {
                continue;
            }
            DevDetailDTO dto = new DevDetailDTO();
            dto.setEngineeringid(engineeringId);
            dto.setEngineeringName(engineeringLedger.getName());
            dto.setProjectId(projectId);
            dto.setProjectName(projectLedger.getName());
            dto.setEquipmentId(equipmentId);
            dto.setEquipmentName(equipmentLedger.getName());
            dto.setLineId(item.getId());
            dto.setLineName(item.getName());
            dto.setObjType(csLinePoMap.get(item.getId()).getMonitorObj());

            if (Objects.isNull(csLinePoMap.get(item.getId()).getRunStatus())) {
                CsEquipmentDeliveryPO delivery = equipmentDeliveryMap.get(equipmentId);
                if (delivery != null) {
                    Integer runStatus = delivery.getRunStatus();
                    if (runStatus == 1) {
                        dto.setRunStatus(2);
                    } else if (runStatus == 2) {
                        dto.setRunStatus(0);
                    }
                }
            } else {
                dto.setRunStatus(csLinePoMap.get(item.getId()).getRunStatus());
            }
            result.add(dto);
        }
        return result;
    }

}
