package com.fdkankan.ucenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fdkankan.common.constant.AppConstant;
import com.fdkankan.ucenter.common.PageInfo;
import com.fdkankan.common.util.DateUtil;
import com.fdkankan.common.util.FileSizeUtil;
import com.fdkankan.ucenter.common.constants.NacosProperty;
import com.fdkankan.ucenter.common.constants.ResultCode;
import com.fdkankan.ucenter.constant.CameraConstant;
import com.fdkankan.ucenter.constant.LoginConstant;
import com.fdkankan.ucenter.entity.*;
import com.fdkankan.ucenter.exception.BusinessException;
import com.fdkankan.ucenter.httpClient.service.LaserService;
import com.fdkankan.ucenter.mapper.ICameraMapper;
import com.fdkankan.ucenter.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fdkankan.ucenter.util.DateUserUtil;
import com.fdkankan.ucenter.vo.request.CameraParam;
import com.fdkankan.ucenter.vo.response.CameraAppVo;
import com.fdkankan.ucenter.vo.response.CameraSpaceVo;
import com.fdkankan.ucenter.vo.response.CameraVo;
import com.fdkankan.ucenter.vo.response.GroupByCount;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * 相机主表 服务实现类
 * </p>
 *
 * @author 
 * @since 2022-07-04
 */
@Service
public class CameraServiceImpl extends ServiceImpl<ICameraMapper, Camera> implements ICameraService {

    @Autowired
    IUserService userService;
    @Autowired
    LaserService fdkkLaserService;
    @Autowired
    ISceneProService sceneProService;
    @Autowired
    ICameraSpaceService cameraSpaceService;
    @Autowired
    IUserIncrementService userIncrementService;
    @Autowired
    ISceneService sceneService;
    @Autowired
    ISceneResourceCameraService sceneResourceCameraService;
    @Autowired
    ISceneResourceService sceneResourceService;
    @Autowired
    ICameraDetailService cameraDetailService;
    @Autowired
    IScenePlusService scenePlusService;
    @Autowired
    ISceneCooperationService sceneCooperationService;
    @Autowired
    ICameraIncrementLogService cameraIncrementLogService;
    @Autowired
    IMailTemplateService mailTemplateService;
    @Autowired
    IIncrementTypeService incrementTypeService;
    @Autowired
    ICameraTypeService cameraTypeService;

    @Override
    public Camera getBySnCode(String snCode) {
        LambdaQueryWrapper<Camera> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Camera::getSnCode,snCode);
        List<Camera> list = this.list(wrapper);
        if(list !=null && list.size() > 0){
            return list.get(0);
        }
        return null;
    }
    @Override
    public Camera getByWfiName(String snCode) {
        LambdaQueryWrapper<Camera> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Camera::getWifiName,snCode);
        List<Camera> list = this.list(wrapper);
        if(list !=null && list.size() > 0){
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<Camera> getCameraLikeSnCode(String snCode) {
        LambdaQueryWrapper<Camera> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(Camera::getSnCode,snCode);
        return this.list(wrapper);
    }

    @Override
    public HashMap<Long, Camera> getByIds(List<Long> cameraIds) {
        HashMap<Long, Camera> map = new HashMap<>();
        if(cameraIds.size() >0){
            LambdaQueryWrapper<Camera> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Camera::getId,cameraIds);
            List<Camera> list = this.list(wrapper);
            list.forEach(entity -> map.put(entity.getId(),entity));
        }
        return map;
    }

    @Override
    public HashMap<String, Object> deadline(String username) {
        //7天内过期的集合
        List<CameraSpaceVo> cameraSpaceList = new ArrayList<>();
        //所有期限的集合
        List<CameraSpaceVo> cameraSpaceAll = new ArrayList<>();
        User user = userService.getByUserName(username);
        CameraParam param = new CameraParam();
        param.setPageNum(1);
        param.setPageSize(100);
        param.setUserId(user.getId());
        Page<CameraVo> page = this.getBaseMapper().pageList(new Page<>(param.getPageNum(),param.getPageSize()),param);
        List<Long> cameraIdList = page.getRecords().parallelStream().map(CameraVo::getId).collect(Collectors.toList());
        if(cameraIdList.size() >0){
            HashMap<Long, CameraSpaceVo> cameraSpaceMap = cameraSpaceService.getVoListByCameraIds(cameraIdList);
            for (CameraVo responseCamera : page.getRecords()) {
                CameraSpaceVo cameraSpace = cameraSpaceMap.get(responseCamera.getId());
                if(cameraSpace != null){
                    DateTime dateTime  = new DateTime(cameraSpace.getSpaceEndTime());
                    cameraSpace.setSnCode(responseCamera.getSnCode());
                    cameraSpace.setUsedSpace(Long.valueOf(responseCamera.getUsedSpace()));
                    cameraSpace.setUsedSpaceStr(responseCamera.getUsedSpaceStr());
                    cameraSpace.setTotalSpace(Double.parseDouble(responseCamera.getTotalSpace()));
                    cameraSpace.setTotalSpaceStr(responseCamera.getTotalSpaceStr());

                    Long space = cameraSpace.getSpace();
                    cameraSpace.setSpace((long)FileSizeUtil.formetFileSize(space, FileSizeUtil.SIZETYPE_GB));
                    cameraSpace.setSpaceStr(FileSizeUtil.formatFileSize(space));
                    cameraSpace.setSpaceEndStr(DateUtil.date2String(cameraSpace.getSpaceEndTime(), DateUtil.YYYY_MM_DD_DATE_FORMAT));

                    if(Days.daysBetween(new DateTime(), dateTime).getDays() < 7){
                        cameraSpaceList.add(cameraSpace);
                        cameraSpaceAll.add(cameraSpace);
                        continue;
                    }
                    cameraSpaceAll.add(cameraSpace);
                }
            }
        }
        HashMap<String,Object> map = new HashMap<>();
        map.put("nickName", user.getNickName());

        if(cameraSpaceList.size() > 0){
            map.put("isExpire", true);
            Collections.sort(cameraSpaceList);
            map.put("cameraList", cameraSpaceList);
            return map;
        }

        map.put("isExpire", false);
        Collections.sort(cameraSpaceAll);
        map.put("cameraList", cameraSpaceAll);
        return map;
    }

    @Override
    public PageInfo pageList(CameraParam param) {
        User user = userService.getByUserName(param.getUserName());
        param.setUserId(user.getId());
        Page<CameraVo> page = this.getBaseMapper().pageList(new Page<>(param.getPageNum(),param.getPageSize()),param);
        List<Long> cameraIdList = page.getRecords().parallelStream().map(CameraVo::getId).collect(Collectors.toList());
        HashMap<Long,GroupByCount> sceneNumMap = new HashMap<>();      //场景数量,最后拍摄时间
        //HashMap<Long, CameraSpaceVo> cameraSpaceMap = new HashMap<>();   //到期时间
        HashMap<Long, UserIncrement> incrementMap = new HashMap<>();   //到期时间，是否过期
        if(cameraIdList.size() >0){
            sceneNumMap =  sceneProService.findSceneNumByCameraIds(cameraIdList);
            //cameraSpaceMap = cameraSpaceService.getVoListByCameraIds(cameraIdList);
            incrementMap = userIncrementService.findByCameraIds(cameraIdList);
        }
        for (CameraVo responseCamera : page.getRecords()) {
            responseCamera.setCameraType(param.getCameraType());
            GroupByCount groupByCount = sceneNumMap.get(responseCamera.getId());

            Integer sceneNum = (groupByCount == null || groupByCount.getCount() == null) ? 0 : Math.toIntExact(groupByCount.getCount());
            Long space = (groupByCount == null || groupByCount.getSpace() == null) ? 0 : groupByCount.getSpace();

            if (responseCamera.getType() != 0){
                if("GB".equals(responseCamera.getUnit())){
                    responseCamera.setUsedSpaceStr(FileSizeUtil.formatFileSize(space));
                    responseCamera.setTotalSpaceStr(FileSizeUtil.formatFileSize(Long.parseLong(responseCamera.getTotalSpace())));
                    String usedSpace = String.valueOf(FileSizeUtil.formetFileSize(space, FileSizeUtil.SIZETYPE_GB));
                    String totalSpace = String.valueOf(FileSizeUtil.formetFileSize(Long.parseLong(responseCamera.getTotalSpace()), FileSizeUtil.SIZETYPE_GB));
                    responseCamera.setUsedSpace(usedSpace);
                    responseCamera.setTotalSpace(totalSpace);
                }
                if("SP".equals(responseCamera.getUnit())){
                    responseCamera.setUsedSpaceStr(String.valueOf(sceneNum));
                    responseCamera.setTotalSpaceStr(responseCamera.getTotalSpace());
                    responseCamera.setUsedSpace(String.valueOf(responseCamera.getUsedSpace()));
                    responseCamera.setTotalSpace(responseCamera.getTotalSpace());
                }

            }
            if(incrementMap.get(responseCamera.getId()) != null){
                UserIncrement userIncrement = incrementMap.get(responseCamera.getId());
                if(userIncrement != null){
                    responseCamera.setUserIncrementId(userIncrement.getId());
                    responseCamera.setMemberLevels(userIncrement.getMemberLevels());
                    responseCamera.setSpaceEndStr(DateUserUtil.getDayTime(userIncrement.getIncrementEndTime()));
                    responseCamera.setSpaceEndTime(userIncrement.getIncrementEndTime());
                    responseCamera.setSubscriptionOrder(userIncrement.getSubscriptionOrder());

                    String dayTime = userIncrement.getIncrementEndTime();
                    Integer surplusDate = Days.daysBetween(new DateTime(), new DateTime( DateUserUtil.getDate(dayTime))).getDays();
                    if(surplusDate < 31){
                        responseCamera.setIsExpire(true);
                        responseCamera.setSurplusDate(surplusDate);
                    }else {
                        responseCamera.setIsExpire(false);
                    }
                    IncrementType incrementType = incrementTypeService.getById(userIncrement.getIncrementTypeId());
                    String totalSpaceStr = null;
                    String totalSpace = null;
                    if("GB".equals(responseCamera.getUnit())){
                        if(incrementType!= null && "SE".equals(userIncrement.getMemberLevels()) && DateUserUtil.getDate(dayTime).getTime() > new Date().getTime() ){  //高级会员 50G容量
                            totalSpaceStr = incrementType.getCameraCapacity() + ".00GB";
                            totalSpace = incrementType.getCameraCapacity() + ".00";
                        }
                    }
                    if("SP".equals(responseCamera.getUnit())){
                        if(incrementType != null && "SE".equals(userIncrement.getMemberLevels()) && DateUserUtil.getDate(dayTime).getTime() > new Date().getTime() ){  //高级会员 50G容量
                            totalSpaceStr = String.valueOf(incrementType.getCameraSpace());
                            totalSpace = String.valueOf(incrementType.getCameraSpace());
                        }
                    }
                    if(totalSpace!=null){
                        responseCamera.setTotalSpaceStr(totalSpaceStr);
                        responseCamera.setTotalSpace(totalSpace);
                    }

                }
            }
            String lastTime = groupByCount == null ? "" : sceneNumMap.get(responseCamera.getId()).getLastTime();
            responseCamera.setSceneNum(sceneNum);
            responseCamera.setLastTime(lastTime);
        }
        return PageInfo.PageInfo(page);
    }

    @Override
    public void unbind(Long cameraId, String ids,String userName) {
        if(cameraId != null){
            ids = cameraId.toString();
        }
        String[] split = ids.split(",");
        List<Long> cameraIds = new ArrayList<>();
        for (String id : split) {
            cameraIds.add(Long.valueOf(id));
        }
        cameraIncrementLogService.saveLog(cameraIds,userName);
        userIncrementService.unbindCamera(cameraIds);                   //取消关联用户权益
        cameraDetailService.unbindCamera(cameraIds);                    //取消相机用户关联
        sceneService.bindOrUnCamera(cameraIds,null);                //取消关联场景
        sceneProService.bindOrUnCamera(cameraIds,null);             //取消关联场景
        scenePlusService.bindOrUnCamera(cameraIds,null);            //取消关联场景
        sceneResourceCameraService.deleteByCameraIds(cameraIds);       //删除协作相机

    }

    @Override
    public void bind(Integer cameraType, String snCodes, String username) {
        User user = userService.getByUserName(username);
        if(user == null){
            throw new BusinessException(LoginConstant.FAILURE_CODE_3015,LoginConstant.FAILURE_MSG_3015);
        }
        String[] snCodeArr = snCodes.split(",");
        List<Long> cameraIds = new ArrayList<>();
        for (String wifiName : snCodeArr) {
            Camera camera = null;
            if(wifiName.contains("_")){
                camera = this.getByWfiName(wifiName);
            }else {
                camera = this.getBySnCode(wifiName);
            }

            if(camera == null){
                throw new BusinessException(AppConstant.FAILURE_CODE_4010, wifiName +"-"+ AppConstant.FAILURE_MSG_4010);
            }
            CameraDetail cameraDetail = cameraDetailService.getByCameraId(camera.getId());
            if(cameraDetail == null){
                throw new BusinessException(AppConstant.FAILURE_CODE_4010, wifiName +"-"+ AppConstant.FAILURE_MSG_4010);
            }
            if( cameraDetail.getUserId() != null){
                throw new BusinessException(CameraConstant.FAILURE_CODE_6010, wifiName +"-"+ CameraConstant.FAILURE_MSG_6010);
            }
            cameraIds.add(camera.getId());
        }

        cameraIncrementLogService.saveLog(cameraIds,null,user.getId(),2);

        cameraDetailService.bindCamera(cameraIds,user);
        sceneService.bindOrUnCamera(cameraIds,user.getId());
        sceneProService.bindOrUnCamera(cameraIds,user.getId());
        scenePlusService.bindOrUnCamera(cameraIds,user.getId());

        if("local".equals(NacosProperty.uploadType)){   //局域网绑定相机，添加权益
            userIncrementService.addByCameraAndUser(cameraIds,user.getId());
        }
    }

    @Override
    public void saveCooperationUser(String ids, Long id,String resourceIds, String username,String lang) {
        User user = userService.getByUserName(username);
        if(user == null){
            throw new BusinessException(LoginConstant.FAILURE_CODE_3021, LoginConstant.FAILURE_MSG_3021);
        }
        if (id != null) {
            ids = id.toString();
        }
        String[] split = ids.split(",");
        List<Long> cameraIds = new ArrayList<>();
        for (String cameraId : split) {
            cameraIds.add(Long.valueOf(cameraId));
        }
        HashMap<Long, CameraDetail> detailMap = cameraDetailService.getByCameraIds(cameraIds);
        HashMap<Long, Camera> cameraMap = this.getByIds(cameraIds);
        cameraDetailService.updateCooperationByIds(cameraIds, user.getId());
        sceneResourceCameraService.deleteByCameraIds(cameraIds);


        List<ScenePro> sceneProList = sceneProService.getListByCameraIds(cameraIds);
        List<ScenePlus> scenePlusList = scenePlusService.getListByCameraIds(cameraIds);
        if(!"aws".equals(NacosProperty.uploadType)) {
            sceneCooperationService.deleteCooperationList(sceneProList,scenePlusList,null);
        }

        List<String> numList = new ArrayList<>();
        List<String> v3List = sceneProList.stream().map(ScenePro::getNum).collect(Collectors.toList());
        List<String> v4List = scenePlusList.stream().map(ScenePlus::getNum).collect(Collectors.toList());
        numList.addAll(v3List);
        numList.addAll(v4List);
        if( !numList.isEmpty()){
            sceneCooperationService.saveBatchByList(numList,Arrays.asList(user.getId()),"camera","mesh");
        }


        fdkkLaserService.disableCooperation(detailMap, cameraMap);
        fdkkLaserService.enableCameraCooperation(detailMap, cameraMap, username);
        if("aws".equals(NacosProperty.uploadType)){
            mailTemplateService.sendCameraCooperation(cameraMap,username,lang);
        }
    }

    @Override
    public void deleteCooperationUser(Long cameraId) {
        List<Long> cameraIds = new ArrayList<>();
        cameraIds.add(cameraId);
        HashMap<Long, CameraDetail> detailMap = cameraDetailService.getByCameraIds(cameraIds);
        HashMap<Long, Camera> cameraMap = this.getByIds(cameraIds);
        CameraDetail cameraDetail = detailMap.get(cameraId);
        Camera camera = cameraMap.get(cameraId);
        if(camera == null || cameraDetail == null){
            throw new BusinessException(ResultCode.CAMERA_NOT_EXIT);
        }
        if(cameraDetail.getCooperationUser() == null){
            throw new BusinessException(ResultCode.DIS_COO_ERROR);
        }

        List<ScenePro> sceneProList = sceneProService.getListByCameraIds(cameraIds);
        List<ScenePlus> scenePlusList = scenePlusService.getListByCameraIds(cameraIds);
        sceneCooperationService.deleteCooperationList(sceneProList,scenePlusList,Arrays.asList(cameraDetail.getCooperationUser()));

        cameraDetailService.updateCooperationByIds(cameraIds, null);
        sceneResourceCameraService.deleteByCameraIds(cameraIds);

        fdkkLaserService.disableCooperation(detailMap, cameraMap);

    }

    @Override
    public Camera getBySnCodeAndPassword(String appUserName, String appPassword) {
        LambdaQueryWrapper<Camera> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Camera::getChildName,appUserName)
                .eq(Camera::getChildPassword,appPassword);
        List<Camera> list = this.list(wrapper);
        if(list != null && list.size() >0){
            return list.get(0);
        }
        return null;
    }

    @Override
    public Camera getByChildName(String childName) {
        LambdaQueryWrapper<Camera> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Camera::getChildName,childName);
        List<Camera> list = this.list(wrapper);
        if(list != null && list.size() >0){
            return list.get(0);
        }
        return null;
    }

    @Override
    public CameraVo getVoByChildName(String childName) {
        CameraVo vo = null;
        Camera cameraEntity = this.getByChildName(childName);
        if (cameraEntity != null){
            CameraDetail detailEntity = cameraDetailService.getByCameraId(cameraEntity.getId());
            if (detailEntity != null){
                vo = new CameraVo();
                vo.setId(cameraEntity.getId());
                vo.setUserId(detailEntity.getUserId());
                vo.setActivatedTime(cameraEntity.getActivatedTime());
                vo.setBalance(Integer.valueOf(detailEntity.getBalance()));
                vo.setChildName(cameraEntity.getChildName());
                vo.setSnCode(cameraEntity.getSnCode());
                vo.setUnit(detailEntity.getUnit());
                if (detailEntity.getType() != 0){
                    if("GB".equals(detailEntity.getUnit())){
                        Long proSpace = sceneProService.getSpaceSumByCameraId(cameraEntity.getId());
                        Long plusSpace = scenePlusService.getSpaceSumByCameraId(cameraEntity.getId());
                        Long space = (plusSpace == null ?0L:plusSpace) + (proSpace == null ?0L:proSpace);
                        vo.setUsedSpace(Double.valueOf(FileSizeUtil.formetFileSize(space, FileSizeUtil.SIZETYPE_GB)).intValue() +"" );
                        vo.setTotalSpace(Double.valueOf(FileSizeUtil.formetFileSize(detailEntity.getTotalSpace().longValue(), FileSizeUtil.SIZETYPE_GB)).intValue() +"");
                        vo.setUsedSpaceStr(FileSizeUtil.formatFileSize(space));
                        vo.setTotalSpaceStr(FileSizeUtil.formatFileSize(detailEntity.getTotalSpace().longValue()));
                    }
                    if("SP".equals(detailEntity.getUnit())){
                        vo.setUsedSpace(String.valueOf(detailEntity.getUsedSpace()));
                        vo.setTotalSpace(String.valueOf(detailEntity.getTotalSpace()));
                        vo.setUsedSpaceStr(String.valueOf(detailEntity.getUsedSpace()));
                        vo.setTotalSpaceStr(String.valueOf(detailEntity.getTotalSpace()));
                    }
                }
                vo.setType(detailEntity.getType());
                vo.setCountry(detailEntity.getCountry());
                vo.setCameraType(detailEntity.getType()+"");
            }
        }
        return vo;
    }

    @Override
    public List<CameraAppVo> getCameraInfo(String childName, String childPassword) {
        return this.getBaseMapper().getCameraInfo(childName,childPassword);
    }

    @Override
    public List<Camera> getAllList(String childName,String token) {
        User user = userService.getByToken(token);
        if(user == null){
            return new ArrayList<>();
        }
        return  this.getBaseMapper().getAllListByUser(user.getId(),childName);
    }

    @Override
    public List<Camera> findLikeChildName(String searchKey) {
        LambdaQueryWrapper<Camera> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(Camera::getSnCode,searchKey);
        return this.list(wrapper);
    }

    @Override
    public List<Camera> getBySnCodes(List<String> snCodes) {
        LambdaQueryWrapper<Camera> wrapper = new LambdaQueryWrapper<>();
        if(snCodes == null || snCodes.size()<=0){
            return new ArrayList<>();
        }
        wrapper.in(Camera::getSnCode,snCodes);
        return this.list(wrapper);
    }
}
