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

import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.sz.admin.monitor.mapper.CameraMapper;
import com.sz.admin.monitor.mapper.PresetMapper;
import com.sz.admin.monitor.pojo.dto.preset.PresetCreateDTO;
import com.sz.admin.monitor.pojo.dto.preset.PresetDeleteDTO;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.Preset;
import com.sz.admin.monitor.pojo.po.table.CameraTableDef;
import com.sz.admin.monitor.pojo.po.table.PresetTableDef;
import com.sz.admin.monitor.pojo.vo.preset.PresetVO;
import com.sz.admin.monitor.pojo.vo.watchful.WatchfulVO;
import com.sz.admin.monitor.sdk.ManageNVR;
import com.sz.admin.monitor.service.IpChannelService;
import com.sz.admin.monitor.service.PresetService;
import com.sz.core.common.exception.common.BusinessException;
import com.sz.core.util.BeanCopyUtils;
import com.sz.platform.enums.AdminResponseEnum;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * ClassName: PresetServiceImpl
 * Package: com.sz.admin.monitor.service.impl
 * Description:
 */
@Service
public class PresetServiceImpl extends ServiceImpl<PresetMapper, Preset> implements PresetService {
    private static final Logger log = LoggerFactory.getLogger(PresetServiceImpl.class);
    @Resource
    private PresetMapper presetMapper;
    @Resource
    private CameraMapper cameraMapper;
    @Resource
    private ManageNVR manageNVR;

    @Override
    public List<PresetVO> getPresetList(Long cameraId) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .from(PresetTableDef.PRESET)
                .where(PresetTableDef.PRESET.CAMERA_ID.eq(cameraId));
        List<Preset> presets = presetMapper.selectListByQuery(queryWrapper);
        Map<Integer, String> definedMap = presets.stream().collect(Collectors.toMap(Preset::getPresetId, Preset::getPresetName));
        // 构造1-8条预置位给前端
        List<PresetVO> result = new ArrayList<>();
        for (int i = 1; i <= 8; i++) {
            PresetVO presetVO = new PresetVO();
            presetVO.setPresetIndex(i);
            if (definedMap.containsKey(i)) {
                presetVO.setPresetName(definedMap.get(i));
                presetVO.setIsSet(true);
            } else {
                presetVO.setPresetName("未定义");
                presetVO.setIsSet(false);
            }
            result.add(presetVO);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removePreset(PresetDeleteDTO dto) {
        log.info("准备删除预置位，请求参数：{}", dto);
        // 1. 获取守望信息，并做防空处理
        WatchfulVO watchful = manageNVR.getWatchful(dto.getCameraId());
        if (watchful != null) {
            // 安全比对预置位索引是否相同
            boolean isCurrentWatchful = Objects.equals(watchful.getWatchfulIndex(), dto.getCurrentPresetIndex());
            if (watchful.getWatchfulState() == 1 && isCurrentWatchful) {
                throw new BusinessException(AdminResponseEnum.CHANNEL_PRESET_FAIL, null, "当前预置位被设置为守望位，请先关闭或者修改守望位");
            }
            if (watchful.getWatchfulState() == 0 && isCurrentWatchful) {
                Camera updateEntity = new Camera();
                updateEntity.setWatchfulIndex(null);
                QueryWrapper updateWrapper = QueryWrapper.create()
                    .from(CameraTableDef.CAMERA)
                    .where(CameraTableDef.CAMERA.ID.eq(dto.getCameraId()))
                    .and(CameraTableDef.CAMERA.WATCHFUL_INDEX.eq(dto.getCurrentPresetIndex()));
                int updateCount = cameraMapper.updateByQuery(updateEntity, updateWrapper);
            }
        }
        // 3. 删除预置位表中的数据
        QueryWrapper deleteWrapper = QueryWrapper.create()
            .from(PresetTableDef.PRESET)
            .where(PresetTableDef.PRESET.CAMERA_ID.eq(dto.getCameraId()))
            .and(PresetTableDef.PRESET.PRESET_ID.eq(dto.getCurrentPresetIndex()));
        int deleteCount = presetMapper.deleteByQuery(deleteWrapper);
        log.info("预置位删除完成，受影响行数：{}", deleteCount);
    }

    @Override
    @Transactional
    public void create(PresetCreateDTO dto) {
        // 先删除和新增
        Integer presetId = dto.getPresetId();
        Long cameraId = dto.getCameraId();
        Preset curPreset = selectByCameraIdAndPresetIndex(cameraId, presetId);
        if (curPreset != null) {
            this.removeById(curPreset);
        }
        Preset preset = BeanCopyUtils.copy(dto, Preset.class);
        save(preset);
    }

    @Override
    public Preset selectByCameraIdAndPresetIndex(Long cameraId, int presetIndex) {
        QueryWrapper wrapper = QueryWrapper.create()
                .from(PresetTableDef.PRESET)
                .where(PresetTableDef.PRESET.CAMERA_ID.eq(cameraId))
                .and(PresetTableDef.PRESET.PRESET_ID.eq(presetIndex));
        return presetMapper.selectOneByQuery(wrapper);
    }

    @Override
    public List<PresetVO> getExistPresetList(Long cameraId) {
        QueryWrapper wrapper = QueryWrapper.create()
                .from(PresetTableDef.PRESET)
                .where(PresetTableDef.PRESET.CAMERA_ID.eq(cameraId));
        List<Preset> presets = presetMapper.selectListByQuery(wrapper);
        return presets.stream().map(preset -> {
            PresetVO presetVO = new PresetVO();
            presetVO.setPresetName(preset.getPresetName());
            presetVO.setPresetIndex(preset.getPresetId());
            presetVO.setIsSet(true);
            return presetVO;
        }).toList();

    }

    @Override
    public List<Preset> selectByCameraIds(List<Long> cameraIds) {
        QueryWrapper wrapper = QueryWrapper.create()
                .from(PresetTableDef.PRESET)
                .where(PresetTableDef.PRESET.CAMERA_ID.in(cameraIds))
                .and(PresetTableDef.PRESET.IS_BASIC_POINT.eq(1));
        return list(wrapper);
    }




}
