package com.sz.admin.monitor.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sz.admin.monitor.enums.HKPTZPreEnum;
import com.sz.admin.monitor.mapper.*;
import com.sz.admin.monitor.pojo.dto.camera.CameraListDTO;
import com.sz.admin.monitor.pojo.dto.camera.CameraUpdateDTO;
import com.sz.admin.monitor.pojo.po.AlgorithmTask;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.EdgeBox;
import com.sz.admin.monitor.pojo.po.Nvr;
import com.sz.admin.monitor.pojo.po.table.CameraTableDef;
import com.sz.admin.monitor.pojo.vo.camera.CameraVO;
import com.sz.admin.monitor.pojo.vo.camerasnapshot.CameraSnapshotVO;
import com.sz.admin.monitor.pojo.vo.edgebox.AlgorithmTaskVO;
import com.sz.admin.monitor.pojo.vo.preset.PresetVO;
import com.sz.admin.monitor.sdk.ManageNVR;
import com.sz.admin.monitor.enums.HCPlayControlEnum;
import com.sz.admin.monitor.service.*;
import com.sz.admin.monitor.utils.AiBoxRequestUtil;
import com.sz.admin.monitor.utils.RtspUtil;
import com.sz.admin.monitor.utils.ZLMediaKitUtils;
import com.sz.admin.teacher.pojo.po.TeacherStatistics;
import com.sz.admin.teacher.pojo.vo.TeacherStatisticsVO;
import com.sz.core.common.entity.PageResult;
import com.sz.core.common.entity.SelectIdsDTO;
import com.sz.core.common.enums.CommonResponseEnum;
import com.sz.core.common.exception.common.BusinessException;
import com.sz.core.datascope.SimpleDataScopeHelper;
import com.sz.core.util.BeanCopyUtils;
import com.sz.core.util.PageUtils;
import com.sz.core.util.Utils;
import com.sz.platform.enums.AdminResponseEnum;
import com.sz.security.core.util.LoginUtils;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.sz.admin.monitor.pojo.po.table.NvrTableDef.NVR;

/**
 * ClassName: CameraServiceImpl
 * Package: com.sz.admin.monitor.service.impl
 * Description: 摄像机业务类
 */
@Service
@Slf4j
public class CameraServiceImpl extends ServiceImpl<CameraMapper, Camera> implements CameraService {
    @Resource
    private CameraMapper cameraMapper;
    @Resource
    private NvrMapper nvrMapper;
    @Resource
    private AlgorithmTaskService algorithmTaskService;
    @Resource
    private PresetMapper presetMapper;
    @Resource
    private CameraSnapshotMapper cameraSnapshotMapper;
    @Resource
    private AiBoxRequestUtil aiBoxRequestUtil;
    @Resource
    private EdgeBoxMapper edgeBoxMapper;
    // 自己注入自己
    @Resource
    @Lazy
    private CameraService cameraService;
    @Override
    public Camera getByChannelId(Integer channelId) {
        QueryWrapper wrapper = QueryWrapper.create()
            .select()
            .from(Camera.class)
            .eq(Camera::getChannelId, channelId);
        return  cameraMapper.selectOneByQuery(wrapper);
    }

    @Override
    public void update(CameraUpdateDTO dto) {
        Camera camera = BeanCopyUtils.copy(dto, Camera.class);
        QueryWrapper wrapper;
        // id有效性校验
        wrapper = QueryWrapper.create().eq(Camera::getId, dto.getId());
        CommonResponseEnum.INVALID_ID.assertTrue(count(wrapper) <= 0);
        // 唯一性校验
        saveOrUpdate(camera);
    }

    @Override
    public PageResult<CameraVO> page(CameraListDTO dto) {
        try {
            SimpleDataScopeHelper.start(Camera.class); // 指定要追加条件的表PO实体
            Page<CameraVO> page = pageAs(PageUtils.getPage(dto), buildQueryWrapper(dto), CameraVO.class); // 调试sql
            page.getRecords().forEach(r -> {
                Long nvrId = r.getNvrId();
                Nvr nvr = nvrMapper.selectOneById(nvrId);
                if(nvr!=null)
                {
                    r.setNvrName(nvr.getName());
                    Map<String, String> rtsp = RtspUtil.getRtsp(nvr.getDriver(), nvr.getAccount(), nvr.getPassword(), r.getChannelId() - 32, nvr.getIp(), 554);
                    r.setRtsp(rtsp.get("mainRtsp"));
                }
                // 根据摄像机的id查询算法任务表
                AlgorithmTaskVO algorithmTaskVO = algorithmTaskService.getAlgorithmTaskByCameraId(r.getId());
                if (algorithmTaskVO != null)
                {
                    r.setAlgInfo(algorithmTaskVO.getAlgInfo());
                }
            });
            return PageUtils.getPageResult(page);
        } finally {
            SimpleDataScopeHelper.clearDataScope();
        }
    }

    @Override
    public List<CameraVO> list(CameraListDTO dto) {
        try {
            SimpleDataScopeHelper.start(Camera.class); // 指定要追加条件的表PO实体
            return listAs(buildQueryWrapper(dto), CameraVO.class);
        } finally {
            SimpleDataScopeHelper.clearDataScope();
        }
    }
    @Override
    public void remove(SelectIdsDTO dto) {
        CommonResponseEnum.INVALID_ID.assertTrue(dto.getIds().isEmpty());
        List<Camera> cameraList = listByIds(dto.getIds());
        if (cameraList.isEmpty()) {
            return;
        }
        List<AlgorithmTaskVO> taskList = algorithmTaskService.listByCameraIds(dto.getIds());
        for (AlgorithmTaskVO task : taskList) {
            if (task != null && task.getAlgTaskSession() != null) {
                try {
                    Long cameraId = task.getCameraId();
                    Camera camera = this.getById(cameraId);
                    Long boxId = camera.getBoxId();
                    EdgeBox edgeBox = edgeBoxMapper.selectOneById(boxId);
                    // 删除任务
                    aiBoxRequestUtil.controlTask(edgeBox.getIp(), edgeBox.getPort(), task.getAlgTaskSession(), 0);
                    aiBoxRequestUtil.deleteTask(edgeBox.getIp(), edgeBox.getPort(), task.getAlgTaskSession());
                } catch (Exception e) {
                    log.error("清理 AI 盒子任务失败，摄像机ID: {}, Session: {}", task.getCameraId(), task.getAlgTaskSession(), e);
                    throw new BusinessException(AdminResponseEnum.OPERATION_FAIL,null,"同步清理设备算法任务失败，请检查网络后重试");
                }
            }
        }
        for (Camera camera : cameraList) {
            // 删除通道
            Long boxId = camera.getBoxId();
            EdgeBox edgeBox = edgeBoxMapper.selectOneById(boxId);
            aiBoxRequestUtil.deleteVideoChannel(edgeBox.getIp(), edgeBox.getPort(), camera.getId().toString());
        }
        cameraService.batchDeleteLocalData(dto.getIds(), taskList);
    }
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteLocalData(List<? extends Serializable> cameraIds, List<AlgorithmTaskVO> taskList) {
        // 1. 批量删除预置位
        presetMapper.removeByCameraIds(cameraIds);
        // 2. 批量删除快照图
        cameraSnapshotMapper.removeByCameraIds(cameraIds);
        // 3. 批量删除算法任务
        if (!taskList.isEmpty()) {
            List<Long> taskIds = taskList.stream().map(AlgorithmTaskVO::getId).toList();
            algorithmTaskService.removeByIds(taskIds);
        }
        // 4. 最后删除摄像头本身
        removeByIds(cameraIds);
    }

    @Override
    public List<CameraVO> getUnboundList() {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select()
                .from(Camera.class)
                .isNull(Camera::getBoxId);
        List<Camera> cameraList = cameraMapper.selectListByQuery(queryWrapper);
        return BeanCopyUtils.copyList(cameraList, CameraVO.class);
    }

    @Override
    public List<CameraVO> getBoundList(Long boxId) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select()
                .from(Camera.class)
                .eq(Camera::getBoxId, boxId);
        List<Camera> cameraList = cameraMapper.selectListByQuery(queryWrapper);
        return BeanCopyUtils.copyList(cameraList, CameraVO.class);
    }

    @Override
    public CameraVO detail(Long id) {
        // 查询时忽略逻辑删除
        Camera camera = LogicDeleteManager.execWithoutLogicDelete(() -> cameraService.getById(id));
        if (camera == null)
        {
            return null;
        }
        CommonResponseEnum.INVALID_ID.assertNull(camera);
        CameraVO cameraVO = BeanCopyUtils.copy(camera, CameraVO.class);
        Long nvrId = cameraVO.getNvrId();
        Nvr nvr = nvrMapper.selectOneById(nvrId);
        if (nvr!=null)
        {
            Map<String, String> rtsp = RtspUtil.getRtsp(nvr.getDriver(), nvr.getAccount(), nvr.getPassword(), cameraVO.getChannelId() - 32, nvr.getIp(), 554);
            cameraVO.setNvrName(nvr.getName());
            cameraVO.setRtsp(rtsp.get("mainRtsp"));
        }
        return cameraVO;
    }

    @Override
    public void updateWatchfulStateByIp(String ipAddress, int watchfulState) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .from(CameraTableDef.CAMERA)
                .where(CameraTableDef.CAMERA.IP_ADDRESS.eq(ipAddress));
        Camera camera = new Camera();
        camera.setWatchfulState(watchfulState);
        cameraMapper.updateByQuery(camera, queryWrapper);
    }

    @SneakyThrows
    @Override
    public List<CameraVO.CameraTypeEnum> remoteSearch(String keyword) {
        Thread.sleep(1000);
        QueryWrapper wrapper = QueryWrapper.create().from(Camera.class).like(Camera::getChannelId, keyword);
        return listAs(wrapper, CameraVO.CameraTypeEnum.class);
    }

    @Override
    public List<Camera> selectListByInspection() {
        QueryWrapper wrapper = QueryWrapper.create().select()
                .from(CameraTableDef.CAMERA)
                .where(CameraTableDef.CAMERA.ENABLE_INSPECTION.eq(1))
            .and(CameraTableDef.CAMERA.STATUS.eq(1));
        return this.list(wrapper);
    }


    private QueryWrapper buildQueryWrapper(CameraListDTO dto) {
        QueryWrapper wrapper = QueryWrapper.create().from(Camera.class);
       // wrapper.orderBy(Camera::getUpdateTime).desc();
        if (Utils.isNotNull(dto.getNvrName())) {
            // 根据NVR名称模糊查询NVR数据
            QueryWrapper where = QueryWrapper.create().from(NVR).select(NVR.ID)
                    .where(NVR.NAME.like(dto.getNvrName()));
            List<Nvr> nvrList = nvrMapper.selectListByQuery(where);
            List<Long> ids = nvrList.stream().map(Nvr::getId).toList();
            wrapper.in(Camera::getNvrId, ids);
        }
        if (Utils.isNotNull(dto.getChannelDriver())) {
            wrapper.eq(Camera::getChannelDriver, dto.getChannelDriver());
        }
        if (Utils.isNotNull(dto.getName())) {
            wrapper.like(Camera::getName, dto.getName());
        }

        if (Utils.isNotNull(dto.getStatus())) {
            wrapper.eq(Camera::getStatus, dto.getStatus());
        }
        if (Utils.isNotNull(dto.getType())) {
            wrapper.eq(Camera::getType, dto.getType());
        }
        if (Utils.isNotNull(dto.getNvrId())) {
            wrapper.eq(Camera::getNvrId, dto.getNvrId());
        }
        if (Utils.isNotNull(dto.getIpAddress())) {
            wrapper.eq(Camera::getIpAddress, dto.getIpAddress());
        }
        if (Utils.isNotNull(dto.getVideoType())) {
            wrapper.eq(Camera::getVideoType, dto.getVideoType());
        }
        if (Utils.isNotNull(dto.getChannelId()))
        {
            wrapper.eq(Camera::getChannelId, dto.getChannelId());
        }
        return wrapper;
    }


}
