package cn.iocoder.yudao.module.pms.service.yanfan.sip.device.channel;

import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.enums.DeviceChannelStatus;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.enums.SessionType;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.redis.RedisCache;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.redis.RedisKeyBuilder;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.server.VideoSessionManager;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.sip.device.channel.vo.YfSipDeviceChannelPageReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.sip.device.channel.vo.YfSipDeviceChannelRespVO;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.sip.device.channel.vo.YfSipDeviceChannelSaveReqVO;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.sip.vo.VideoSessionInfo;
import cn.iocoder.yudao.module.pms.controller.admin.yanfan.utils.SipUtil;
import cn.iocoder.yudao.module.pms.dal.dataobject.yanfan.product.IotYfProductDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.yanfan.sip.device.YfSipDeviceDO;
import cn.iocoder.yudao.module.pms.dal.dataobject.yanfan.sip.device.channel.YfSipDeviceChannelDO;
import cn.iocoder.yudao.module.pms.dal.mysql.yanfan.sip.device.YfSipDeviceMapper;
import cn.iocoder.yudao.module.pms.dal.mysql.yanfan.sip.device.channel.YfSipDeviceChannelMapper;
import cn.iocoder.yudao.module.pms.service.yanfan.product.IotYfProductService;
import cn.iocoder.yudao.module.pms.service.yanfan.sip.model.BaseTree;
import liquibase.pro.packaged.Y;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;


import javax.annotation.Resource;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * yf监控设备通道信息 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
@Slf4j
public class YfSipDeviceChannelServiceImpl implements YfSipDeviceChannelService {

    @Resource
    private YfSipDeviceChannelMapper yfSipDeviceChannelMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private IotYfProductService iotYfProductService;
    @Autowired
    private VideoSessionManager streamSession;
    @Autowired
    private YfSipDeviceMapper yfSipDeviceMapper;

    /**
     * 新增监控设备通道信息
     *
     * @param sipDeviceChannel 监控设备通道信息
     * @return 结果
     */
    @Override
    public String insertSipDeviceChannelGen(Long createNum, YfSipDeviceChannelSaveReqVO sipDeviceChannel) {
        int ret = 0;
        int devuserid = 0;
        int channeluserid = 0;
        String tmpdev = sipDeviceChannel.getDeviceSipId();
        String tmpchannel = sipDeviceChannel.getChannelSipId();
        Object cacheObj = redisCache.getCacheObject(RedisKeyBuilder.buildSipDeviceidCacheKey(tmpdev));
        if (cacheObj != null) {
            devuserid = (int) cacheObj;
        }
        cacheObj = redisCache.getCacheObject(RedisKeyBuilder.buildSipDeviceidCacheKey(tmpchannel));
        if (cacheObj != null) {
            channeluserid = (int) cacheObj;
        }
        String devstr = String.format("%06d", devuserid + 1);
        sipDeviceChannel.setDeviceSipId(tmpdev + devstr);
        sipDeviceChannel.setStatus(DeviceChannelStatus.notused.getValue());
        //限制最大添加数量为10
        if (createNum > 10) {
            createNum = 10L;
        }
        for (int i = 1; i <= createNum; i++) {
            String channelstr = String.format("%06d", channeluserid + i);
            sipDeviceChannel.setChannelSipId(tmpchannel + channelstr);
            YfSipDeviceChannelDO deviceChannel = yfSipDeviceChannelMapper.selectSipDeviceChannelByChannelSipId(sipDeviceChannel.getChannelSipId());
            if (deviceChannel == null) {
                ret = insertSipDeviceChannel(sipDeviceChannel);
            }
        }
        redisCache.incr(RedisKeyBuilder.buildSipDeviceidCacheKey(tmpdev), 1);
        redisCache.incr(RedisKeyBuilder.buildSipDeviceidCacheKey(tmpchannel), createNum);
        if (ret > 0) {
            return tmpdev + devstr;
        } else {
            return "";
        }
    }

    @Override
    public int insertSipDeviceChannel(YfSipDeviceChannelSaveReqVO sipDeviceChannel) {
        IotYfProductDO product = iotYfProductService.getProductBySerialNumber(sipDeviceChannel.getDeviceSipId());
        if (product != null) {
            sipDeviceChannel.setProductId(product.getProductId());
            sipDeviceChannel.setProductName(product.getProductName());
        }
//        sipDeviceChannel.setCreateTime(DateUtils.getNowDate());
        YfSipDeviceChannelDO bean = BeanUtils.toBean(sipDeviceChannel, YfSipDeviceChannelDO.class);
        bean.setDeleted(false);
        bean.setTenantId("1");
        return yfSipDeviceChannelMapper.insert(bean);
    }

    @Override
    public Long createYfSipDeviceChannel(YfSipDeviceChannelSaveReqVO createReqVO) {
        // 插入
        YfSipDeviceChannelDO yfSipDeviceChannel = BeanUtils.toBean(createReqVO, YfSipDeviceChannelDO.class);
        yfSipDeviceChannel.setTenantId("1");
        yfSipDeviceChannelMapper.insert(yfSipDeviceChannel);
        // 返回
        return yfSipDeviceChannel.getId();
    }

    @Override
    public void updateYfSipDeviceChannel(YfSipDeviceChannelSaveReqVO updateReqVO) {
        // 校验存在
        validateYfSipDeviceChannelExists(updateReqVO.getId());
        // 更新
        YfSipDeviceChannelDO updateObj = BeanUtils.toBean(updateReqVO, YfSipDeviceChannelDO.class);
        yfSipDeviceChannelMapper.updateById(updateObj);
    }

    @Override
    public void deleteYfSipDeviceChannel(Long id) {
        // 校验存在
        validateYfSipDeviceChannelExists(id);
        // 删除
        yfSipDeviceChannelMapper.deleteById(id);
    }

    private void validateYfSipDeviceChannelExists(Long id) {
        if (yfSipDeviceChannelMapper.selectById(id) == null) {
            throw exception(new ErrorCode(2,"不存在"));
        }
    }

    @Override
    public YfSipDeviceChannelDO getYfSipDeviceChannel(Long id) {
        return yfSipDeviceChannelMapper.selectById(id);
    }

    @Override
    public PageResult<YfSipDeviceChannelDO> getYfSipDeviceChannelPage(YfSipDeviceChannelPageReqVO pageReqVO) {
        return yfSipDeviceChannelMapper.selectPage(pageReqVO);
    }


    @Override
    public List<YfSipDeviceChannelRespVO> selectSipDeviceChannelList(YfSipDeviceChannelDO sipDeviceChannel) {
        List<YfSipDeviceChannelRespVO> list = yfSipDeviceChannelMapper.selectSipDeviceChannelList(sipDeviceChannel);
        List<YfSipDeviceChannelRespVO> newList = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (YfSipDeviceChannelRespVO channel : list) {
                newList.add(updateChannelStatus(channel));
            }
        }
        return list;
    }

    public YfSipDeviceChannelRespVO updateChannelStatus(YfSipDeviceChannelRespVO channel) {
        String playsid = String.format("%s_%s_%s", SipUtil.PREFIX_PLAY, channel.getDeviceSipId(), channel.getChannelSipId());
        String playrsid = String.format("%s_%s_%s", SipUtil.PREFIX_PLAYRECORD, channel.getDeviceSipId(), channel.getChannelSipId());
        VideoSessionInfo pinfo = streamSession.getSessionInfo(channel.getDeviceSipId(),
                channel.getChannelSipId(), playsid, SessionType.play.name());
        if (pinfo != null) {
            channel.setStreamPush(pinfo.isPushing() ? 1 : 0);
//        channel.setStreamPush(1);
        }
        VideoSessionInfo prinfo = streamSession.getSessionInfo(channel.getDeviceSipId(),
                channel.getChannelSipId(), playrsid, SessionType.playrecord.name());
        if (prinfo != null) {
            channel.setStreamRecord(prinfo.isRecording() ? 1 : 0);
        }
//        channel.setStreamRecord(0);
        return channel;
    }

    @Override
    public void updateChannel(String deviceId, YfSipDeviceChannelDO channel) {
        YfSipDeviceChannelDO deviceChannel = yfSipDeviceChannelMapper.selectSipDeviceChannelByChannelSipId(channel.getChannelSipId());
        if (deviceChannel == null) {
            IotYfProductDO product = iotYfProductService.getProductBySerialNumber(deviceId);
            if (product != null) {
                YfSipDeviceChannelSaveReqVO bean = BeanUtils.toBean(channel, YfSipDeviceChannelSaveReqVO.class);
                insertSipDeviceChannel(bean);
            } else {
                log.error("未注册设备：{}", deviceId);
            }

        } else {
            channel.setId(deviceChannel.getId());
            yfSipDeviceChannelMapper.updateSipDeviceChannel(channel);
        }
    }

    @Override
    public List<BaseTree<YfSipDeviceChannelDO>> queryVideoDeviceTree(String deviceId, String parentId, boolean onlyCatalog) {
        YfSipDeviceDO device = yfSipDeviceMapper.selectSipDeviceBySipId(deviceId);
        if (device == null) {
            return null;
        }
        if (parentId == null || parentId.equals(deviceId)) {
            // 字根节点开始查询
            List<YfSipDeviceChannelDO> rootNodes = getRootNodes(deviceId, true, !onlyCatalog);
            return transportChannelsToTree(rootNodes, "");
        }

        if (parentId.length() % 2 != 0) {
            return null;
        }
        if (parentId.length() == 10) {
            if (onlyCatalog) {
                return null;
            }
            // parentId为行业编码， 其下不会再有行政区划
            List<YfSipDeviceChannelDO> channels = yfSipDeviceChannelMapper.selectChannelByCivilCode(deviceId, parentId);
            return transportChannelsToTree(channels, parentId);
        }
        // 查询其下的行政区划和摄像机
        List<YfSipDeviceChannelDO> channelsForCivilCode = yfSipDeviceChannelMapper.selectChannelWithCivilCodeAndLength(deviceId, parentId, parentId.length() + 2);
        if (!onlyCatalog) {
            List<YfSipDeviceChannelDO> channels = yfSipDeviceChannelMapper.selectChannelByCivilCode(deviceId, parentId);

            for (YfSipDeviceChannelDO channel : channels) {
                boolean flag = false;
                for (YfSipDeviceChannelDO deviceChannel : channelsForCivilCode) {
                    if (channel.getChannelSipId().equals(deviceChannel.getChannelSipId())) {
                        flag = true;
                    }
                }
                if (!flag) {
                    channelsForCivilCode.add(channel);
                }
            }
        }
        return transportChannelsToTree(channelsForCivilCode, parentId);
    }


    private List<YfSipDeviceChannelDO> getRootNodes(String deviceId, boolean haveCatalog, boolean haveChannel) {
        if (!haveCatalog && !haveChannel) {
            return null;
        }
        List<YfSipDeviceChannelDO> result = new ArrayList<>();
        // 使用行政区划
        Integer length = yfSipDeviceChannelMapper.getChannelMinLength(deviceId);
        if (length == null) {
            return null;
        }
        if (length <= 10) {
            if (haveCatalog) {
                List<YfSipDeviceChannelDO> provinceNode = yfSipDeviceChannelMapper.selectChannelWithCivilCodeAndLength(deviceId, null, length);
                if (provinceNode != null && provinceNode.size() > 0) {
                    result.addAll(provinceNode);
                }
            }
            if (haveChannel) {
                // 查询那些civilCode不在通道中的不规范通道，放置在根目录
                List<YfSipDeviceChannelDO> nonstandardNode = yfSipDeviceChannelMapper.selectChannelWithoutCiviCode(deviceId);
                if (nonstandardNode != null && nonstandardNode.size() > 0) {
                    result.addAll(nonstandardNode);
                }
            }
        } else {
            if (haveChannel) {
                List<YfSipDeviceChannelDO> deviceChannels = yfSipDeviceChannelMapper.selectSipDeviceChannelByDeviceSipId(deviceId);
                if (deviceChannels != null && deviceChannels.size() > 0) {
                    result.addAll(deviceChannels);
                }
            }
        }
        return result;
    }

    private List<BaseTree<YfSipDeviceChannelDO>> transportChannelsToTree(List<YfSipDeviceChannelDO> channels, String parentId) {
        if (channels == null) {
            return null;
        }
        List<BaseTree<YfSipDeviceChannelDO>> treeNotes = new ArrayList<>();
        if (channels.size() == 0) {
            return treeNotes;
        }
        for (YfSipDeviceChannelDO channel : channels) {
            BaseTree<YfSipDeviceChannelDO> node = new BaseTree<>();
            node.setId(channel.getChannelSipId());
            node.setDeviceId(channel.getDeviceSipId());
            node.setName(channel.getChannelName());
            node.setPid(parentId);
            node.setBasicData(channel);
            node.setParent(false);
            if (channel.getChannelSipId().length() > 8) {
                if (channel.getChannelSipId().length() > 13) {
                    String gbCodeType = channel.getChannelSipId().substring(10, 13);
                    node.setParent(gbCodeType.equals(SipUtil.BUSINESS_GROUP) || gbCodeType.equals(SipUtil.VIRTUAL_ORGANIZATION));
                }
            } else {
                node.setParent(true);
            }
            treeNotes.add(node);
        }
        Collections.sort(treeNotes);
        return treeNotes;
    }
}
