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

import com.mybatisflex.core.paginate.Page;
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.NvrMapper;
import com.sz.admin.monitor.mapper.RegionMapper;
import com.sz.admin.monitor.pojo.dto.nvr.NvrCreateDTO;
import com.sz.admin.monitor.pojo.dto.nvr.NvrListDTO;
import com.sz.admin.monitor.pojo.dto.nvr.NvrUpdateDTO;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.Nvr;
import com.sz.admin.monitor.pojo.po.Region;
import com.sz.admin.monitor.pojo.po.table.RegionTableDef;
import com.sz.admin.monitor.pojo.po.table.SubstationTableDef;
import com.sz.admin.monitor.pojo.vo.nvr.NvrVO;
import com.sz.admin.monitor.service.NvrService;
import com.sz.core.common.entity.PageQuery;
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 jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;

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

/**
 * ClassName: NvrServiceImpl
 * Package: com.sz.admin.monitor.service.impl
 * Description:
 */
@Service
public class NvrServiceImpl extends ServiceImpl<NvrMapper, Nvr> implements NvrService {
    private static final Logger log = LoggerFactory.getLogger(NvrServiceImpl.class);
    @Resource
    private RegionMapper regionMapper;
    @Resource
    private CameraMapper cameraMapper;

    @Resource
    private NvrMapper nvrMapper;
    @Override
    public void upStatusById(Long id, int status) {
        QueryWrapper wrapper = QueryWrapper.create()
            .eq(Nvr::getId, id);
        update(Nvr.builder().status(status).build(), wrapper);
    }
    @Override
    public Long create(NvrCreateDTO dto) {
        Nvr nvr = BeanCopyUtils.copy(dto, Nvr.class);
        // 唯一性校验
         nvrMapper.insert(nvr);
        return nvr.getId();
    }

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

    @Override
    public PageResult<NvrVO> page(NvrListDTO dto) {
        try {
            SimpleDataScopeHelper.start(Nvr.class); // 指定要追加条件的表PO实体
            Page<NvrVO> page = pageAs(PageUtils.getPage(dto), buildQueryWrapper(dto), NvrVO.class); // 调试sql
            return PageUtils.getPageResult(page);
        } finally {
            SimpleDataScopeHelper.clearDataScope();
        }
    }

    @Override
    public List<NvrVO> list(NvrListDTO dto) {
        try {
            SimpleDataScopeHelper.start(Nvr.class); // 指定要追加条件的表PO实体
            return listAs(buildQueryWrapper(dto), NvrVO.class);
        } finally {
            SimpleDataScopeHelper.clearDataScope();
        }
    }

    @Override
    public void remove(SelectIdsDTO dto) {
        CommonResponseEnum.INVALID_ID.assertTrue(dto.getIds().isEmpty());
        // 批量查询nvr信息
        List<Nvr> nvrList = listByIds(dto.getIds());
        if (nvrList.isEmpty()) {
            return;
        }
        nvrList.forEach(nvr -> {
            Long id = nvr.getId();
            // 根据nvr的ID，去查询关联的摄像头
            List<Camera> cameras = cameraMapper.selectByNvrId(id);
            if (!cameras.isEmpty())
            {
                throw new BusinessException(AdminResponseEnum.OPERATION_FAIL,null,nvr.getName()+"下存在摄像头，请先删除摄像头");
            }
        });
        removeByIds(dto.getIds());
    }

    @Override
    public NvrVO detail(Long id) {
        Nvr nvr = getById(id);
        CommonResponseEnum.INVALID_ID.assertNull(nvr);
        return BeanCopyUtils.copy(nvr, NvrVO.class);
    }

    @Override
    public PageResult<NvrVO> listByNode(Long nodeId, Integer type, Integer pageNum, Integer pageSize) {
        Page<NvrVO> page=null;
        if(type==0)
        {
            // 获取某个区域下的所有NVR
            // 查询区域信息，用于判断是否是根节点
            QueryWrapper regionWrapper = QueryWrapper.create()
                .select(RegionTableDef.REGION.ALL_COLUMNS)
                .from(Region.class)
                .where(RegionTableDef.REGION.ID.eq(nodeId));
            Region region = regionMapper.selectOneByQuery(regionWrapper);
            if (region.getParentId()==0)
            {
                // 根节点
                QueryWrapper subQuery1 = QueryWrapper.create()
                    .select(SubstationTableDef.SUBSTATION.ID)
                    .from(SubstationTableDef.SUBSTATION)
                    .join(RegionTableDef.REGION)
                    .on(SubstationTableDef.SUBSTATION.REGION_ID.eq(RegionTableDef.REGION.ID))
                    .where(RegionTableDef.REGION.PARENT_ID.eq(region.getId()));
                QueryWrapper subQuery2 = QueryWrapper.create()
                    .select(SubstationTableDef.SUBSTATION.ID)
                    .from(SubstationTableDef.SUBSTATION)
                    .where(SubstationTableDef.SUBSTATION.REGION_ID.eq(region.getId()));
                QueryWrapper mainQuery = QueryWrapper.create()
                    .select(NVR.ALL_COLUMNS)
                    .from(NVR)
                    .where(NVR.STATION_ID.in(
                        subQuery1.union(subQuery2)
                    ));
                PageQuery pageQuery = new PageQuery();
                pageQuery.setPage(pageNum);
                pageQuery.setLimit(pageSize);
                 page = pageAs(PageUtils.getPage(pageQuery),mainQuery, NvrVO.class);
            }else {
                QueryWrapper wrapper = QueryWrapper.create()
                    .select(NVR.ALL_COLUMNS)
                    .from(NVR)
                    .join(SubstationTableDef.SUBSTATION)
                    .on(NVR.STATION_ID.eq(SubstationTableDef.SUBSTATION.ID))
                    .where(SubstationTableDef.SUBSTATION.REGION_ID.eq(nodeId));
                PageQuery pageQuery = new PageQuery();
                pageQuery.setPage(pageNum);
                pageQuery.setLimit(pageSize);
                 page = pageAs(PageUtils.getPage(pageQuery), wrapper, NvrVO.class);
            }

        }else if (type==1)
        {
            // 获取某个变电站下的所有NVR
            QueryWrapper wrapper = QueryWrapper.create()
                .select()
                .where(NVR.STATION_ID.eq(nodeId));
            PageQuery pageQuery = new PageQuery();
            pageQuery.setPage(pageNum);
            pageQuery.setLimit(pageSize);
            page = pageAs(PageUtils.getPage(pageQuery), wrapper, NvrVO.class);
        }
        assert page != null;
        return PageUtils.getPageResult(page);
    }




    private static QueryWrapper buildQueryWrapper(NvrListDTO dto) {
        QueryWrapper wrapper = QueryWrapper.create().from(Nvr.class);
        if (Utils.isNotNull(dto.getIp())) {
            wrapper.eq(Nvr::getIp, dto.getIp());
        }
        if (Utils.isNotNull(dto.getId())) {
            wrapper.eq(Nvr::getId, dto.getId());
        }
        if (Utils.isNotNull(dto.getName())) {
            wrapper.like(Nvr::getName, dto.getName());
        }

        if (Utils.isNotNull(dto.getDriver())) {
            wrapper.eq(Nvr::getDriver, dto.getDriver());
        }
        if (Utils.isNotNull(dto.getStatus())) {
            wrapper.eq(Nvr::getStatus, dto.getStatus());
        }
        if (Utils.isNotNull(dto.getStationId())) {
            wrapper.eq(Nvr::getStationId, dto.getStationId());
        }
        if (Utils.isNotNull(dto.getPort())) {
            wrapper.eq(Nvr::getPort, dto.getPort());
        }
        return wrapper;
    }


}
