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.enums.AlarmReportEnums;
import com.sz.admin.monitor.mapper.CameraAlarmMapper;
import com.sz.admin.monitor.mapper.CameraMapper;
import com.sz.admin.monitor.pojo.dto.cameraalarm.CameraAlarmCreateDTO;
import com.sz.admin.monitor.pojo.dto.cameraalarm.CameraAlarmImportDTO;
import com.sz.admin.monitor.pojo.dto.cameraalarm.CameraAlarmListDTO;
import com.sz.admin.monitor.pojo.dto.cameraalarm.CameraAlarmUpdateDTO;
import com.sz.admin.monitor.pojo.po.Camera;
import com.sz.admin.monitor.pojo.po.CameraAlarm;
import com.sz.admin.monitor.pojo.vo.camera.CameraVO;
import com.sz.admin.monitor.pojo.vo.cameraalarm.CameraAlarmVO;
import com.sz.admin.monitor.pojo.vo.edgebox.AlarmReportVO;
import com.sz.admin.monitor.pojo.vo.offset.OffsetVO;
import com.sz.admin.monitor.service.CameraAlarmService;
import com.sz.admin.monitor.service.CameraService;
import com.sz.admin.monitor.utils.UrlConvert;
import com.sz.core.common.entity.ImportExcelDTO;
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.datascope.SimpleDataScopeHelper;
import com.sz.core.util.*;
import com.sz.excel.core.ExcelResult;
import com.sz.excel.utils.ExcelUtils;
import com.sz.security.core.util.LoginUtils;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.io.OutputStream;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 告警工单表 服务实现类
 * </p>
 *
 * @author Lz
 * @since 2026-02-10
 */
@Service
@RequiredArgsConstructor
public class CameraAlarmServiceImpl extends ServiceImpl<CameraAlarmMapper, CameraAlarm> implements CameraAlarmService {
    private final CameraService cameraService;
    @Override
    public void create(CameraAlarmCreateDTO dto) {
        CameraAlarm ryCameraAlarm = BeanCopyUtils.copy(dto, CameraAlarm.class);
        save(ryCameraAlarm);
    }

    @Override
    public void update(CameraAlarmUpdateDTO dto) {
        CameraAlarm ryCameraAlarm = BeanCopyUtils.copy(dto, CameraAlarm.class);
        QueryWrapper wrapper;
        // id有效性校验
        wrapper = QueryWrapper.create()
                .eq(CameraAlarm::getId, dto.getId());
        CommonResponseEnum.INVALID_ID.assertTrue(count(wrapper) <= 0);
        // 设置处理人，即为当前登录的用户
        String username = LoginUtils.getLoginUser().getUserInfo().getUsername();
        ryCameraAlarm.setHandleTime(LocalDateTime.now());
        ryCameraAlarm.setHandleBy(username);
        saveOrUpdate(ryCameraAlarm);
    }

    @Override
    public PageResult<CameraAlarmVO> page(CameraAlarmListDTO dto) {
        try {
            SimpleDataScopeHelper.start(CameraAlarm.class);
            Page<CameraAlarmVO> page = pageAs(PageUtils.getPage(dto), buildQueryWrapper(dto), CameraAlarmVO.class);
            List<CameraAlarmVO> result = page.getRecords().stream().map(cameraAlarmVO -> {
                String baseImage = cameraAlarmVO.getBaseImage();
                cameraAlarmVO.setBaseImage(UrlConvert.convertToUrl(baseImage));
                String captureImage = cameraAlarmVO.getCaptureImage();
                cameraAlarmVO.setCaptureImage(UrlConvert.convertToUrl(captureImage));
                return cameraAlarmVO;
            }).toList();
            page.setRecords(result);
            return PageUtils.getPageResult(page);
        } finally {
            SimpleDataScopeHelper.clearDataScope();
        }
    }

    @Override
    public List<CameraAlarmVO> list(CameraAlarmListDTO dto) {
        try {
            SimpleDataScopeHelper.start(CameraAlarm.class);
            return listAs(buildQueryWrapper(dto), CameraAlarmVO.class);
        } finally {
            SimpleDataScopeHelper.clearDataScope();
        }
    }

    @Override
    public void remove(SelectIdsDTO dto) {
        CommonResponseEnum.INVALID_ID.assertTrue(dto.getIds().isEmpty());
        removeByIds(dto.getIds());
    }

    @Override
    public CameraAlarmVO detail(Object id) {
        CameraAlarm ryCameraAlarm = getById((Serializable) id);
        String baseImage = ryCameraAlarm.getBaseImage();
        ryCameraAlarm.setBaseImage(UrlConvert.convertToUrl(baseImage));
        String captureImage = ryCameraAlarm.getCaptureImage();
        ryCameraAlarm.setCaptureImage(UrlConvert.convertToUrl(captureImage));
        CommonResponseEnum.INVALID_ID.assertNull(ryCameraAlarm);
        return BeanCopyUtils.copy(ryCameraAlarm, CameraAlarmVO.class);
    }

    @SneakyThrows
    @Override
    public void importExcel(ImportExcelDTO dto) {
        ExcelResult<CameraAlarmImportDTO> excelResult = ExcelUtils.importExcel(dto.getFile().getInputStream(), CameraAlarmImportDTO.class, true);
        List<CameraAlarmImportDTO> list = excelResult.getList();
        // 入库
        List<CameraAlarm> importList = BeanCopyUtils.copyList(list, CameraAlarm.class);
        saveBatch(importList);
        List<String> errorList = excelResult.getErrorList();
        String analysis = excelResult.getAnalysis();
        System.out.println(" analysis : " + analysis);
        System.out.println(" isCover : " + dto.getIsCover());
    }

    @SneakyThrows
    @Override
    public void exportExcel(CameraAlarmListDTO dto, HttpServletResponse response) {
        List<CameraAlarmVO> list = list(dto);
        String fileName = "告警工单表模板";
        OutputStream os = FileUtils.getOutputStream(response, fileName + ".xlsx");
        ExcelUtils.exportExcel(list, "告警工单表", CameraAlarmVO.class, os);
    }

    @Override
    public AlarmReportVO getAlarmReportDetail(Long id) {
        CameraAlarm cameraAlarm = this.getById(id);
        if (!Utils.isNotNull(cameraAlarm)) {
            return null;
        }
        AlarmReportVO reportVO = BeanCopyUtils.copy(cameraAlarm, AlarmReportVO.class);
        String baseImage = reportVO.getBaseImage();
        reportVO.setBaseImage(UrlConvert.convertToUrl(baseImage));
        String captureImage = reportVO.getCaptureImage();
        reportVO.setCaptureImage(UrlConvert.convertToUrl(captureImage));
        String algoResult = cameraAlarm.getAlgoResult();
        // {"x": "-113.48", "y": "-6.36", "unit": "px"}
        AlarmReportEnums alarmReportEnums = AlarmReportEnums.getAlarmReportEnums(cameraAlarm.getAlarmType());
        if (Utils.isNotNull(alarmReportEnums)) {
            reportVO.setAlarmType(alarmReportEnums.getAlarmDescription());
            reportVO.setSummary(alarmReportEnums.getAlarmType());
        }
        // 区别出移位报警
        if(cameraAlarm.getAlarmType() == 1)
        {
            OffsetVO offsetVO = JsonUtils.parseObject(algoResult, OffsetVO.class);
            if (offsetVO != null)
            {
                // 如果是移位报警，则需要特殊处理
                AlarmReportVO.SimpleResult simpleResult = getSimpleResult(offsetVO);
                reportVO.setResult(simpleResult);
            }

        }else {
            AlarmReportVO.SimpleResult simpleResult = JsonUtils.parseObject(algoResult, AlarmReportVO.SimpleResult.class);
            reportVO.setResult(simpleResult);
        }
        Long cameraId = cameraAlarm.getCameraId();
        CameraVO cameraVO = cameraService.detail(cameraId);
        if (Utils.isNotNull(cameraVO)) {
            reportVO.setRtspUrl(cameraVO.getRtsp());
        }
        return reportVO;
    }

    private static AlarmReportVO. SimpleResult getSimpleResult(OffsetVO offsetVO) {
        AlarmReportVO.SimpleResult simpleResult = new AlarmReportVO.SimpleResult();
        simpleResult.setDescription("移位报警");
        AlarmReportVO.SimpleProperty simplePropertyX = new AlarmReportVO.SimpleProperty();
        simplePropertyX.setProperty("x");
        simplePropertyX.setDesc("水平方向偏移量");
        simplePropertyX.setValue(offsetVO.getX());
        AlarmReportVO.SimpleProperty simplePropertyY = new AlarmReportVO.SimpleProperty();
        simplePropertyX.setProperty("y");
        simplePropertyY.setDesc("垂直方向偏移量");
        simplePropertyY.setValue(offsetVO.getY());
        simpleResult.setProperties(List.of(simplePropertyX, simplePropertyY));
        return simpleResult;
    }

    private static QueryWrapper buildQueryWrapper(CameraAlarmListDTO dto) {
        QueryWrapper wrapper = QueryWrapper.create().from(CameraAlarm.class);
        wrapper.orderBy(CameraAlarm::getCreateTime).desc();
        if (Utils.isNotNull(dto.getCameraId())) {
            wrapper.eq(CameraAlarm::getCameraId, dto.getCameraId());
        }
        if (Utils.isNotNull(dto.getAlarmTimeStart()) && Utils.isNotNull(dto.getAlarmTimeEnd()))
        {
            wrapper.between(CameraAlarm::getCreateTime, dto.getAlarmTimeStart(), dto.getAlarmTimeEnd());
        }
        if (Utils.isNotNull(dto.getChannelId())) {
            wrapper.eq(CameraAlarm::getChannelId, dto.getChannelId());
        }
        if(Utils.isNotNull(dto.getAlarmAreaId()))
        {
            wrapper.eq(CameraAlarm::getAlarmAreaId, dto.getAlarmAreaId());
        }
        if (Utils.isNotNull(dto.getPresetIndex())) {
            wrapper.eq(CameraAlarm::getPresetIndex, dto.getPresetIndex());
        }
        if (Utils.isNotNull(dto.getAlarmType())) {
            wrapper.eq(CameraAlarm::getAlarmType, dto.getAlarmType());
        }
        if (Utils.isNotNull(dto.getBaseImage())) {
            wrapper.eq(CameraAlarm::getBaseImage, dto.getBaseImage());
        }
        if (Utils.isNotNull(dto.getCaptureImage())) {
            wrapper.eq(CameraAlarm::getCaptureImage, dto.getCaptureImage());
        }
        if (Utils.isNotNull(dto.getAlgoResult())) {
            wrapper.eq(CameraAlarm::getAlgoResult, dto.getAlgoResult());
        }
        if (Utils.isNotNull(dto.getStatus())) {
            wrapper.eq(CameraAlarm::getStatus, dto.getStatus());
        }
        if (Utils.isNotNull(dto.getHandleTimeStart()) && Utils.isNotNull(dto.getHandleTimeEnd())) {
            wrapper.between(CameraAlarm::getHandleTime, dto.getHandleTimeStart(), dto.getHandleTimeEnd());
        }
        if (Utils.isNotNull(dto.getHandleBy())) {
            wrapper.eq(CameraAlarm::getHandleBy, dto.getHandleBy());
        }
        if (Utils.isNotNull(dto.getHandleRemark())) {
            wrapper.eq(CameraAlarm::getHandleRemark, dto.getHandleRemark());
        }
        return wrapper;
    }
}