package com.inspect.metadata.patrolpointmnt.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.inspect.base.core.constant.Color;
import com.inspect.metadata.alg.domain.BasedataAlgSubtype;
import com.inspect.metadata.alg.service.IBasedataAlgSubtypeService;
import com.inspect.metadata.montdatamqhandle.service.component.BasedataMontPatrolPointHandleComponent;
import com.inspect.metadata.patrolpointmnt.domain.BasedataPatrolPoint;
import com.inspect.metadata.patrolpointmnt.domain.BasedataStdPatrolPoint;
import com.inspect.metadata.patrolpointmnt.domain.vo.DevicePointModelItem;
import com.inspect.metadata.patrolpointmnt.domain.vo.PointLatestResultVo;
import com.inspect.metadata.patrolpointmnt.domain.vo.PointStatsVo;
import com.inspect.metadata.patrolpointmnt.service.IBasedataPatrolPointService;
import com.inspect.metadata.patrolpointmnt.service.IBasedataStdPatrolPointService;
import com.inspect.metadata.prodevmnt.domain.BasedataDevice;
import com.inspect.metadata.prodevmnt.service.IBasedataDeviceService;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.base.core.utils.poi.ExcelUtil;
import com.inspect.base.core.web.controller.BaseController;
import com.inspect.base.core.web.domain.AjaxResult;
import com.inspect.base.core.web.page.TableDataInfo;
import com.inspect.common.log.annotation.Log;
import com.inspect.common.log.enums.BizType;
import com.inspect.common.security.annotation.RequiresPermissions;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@RestController
@RequestMapping({"/patrolpointmnt/patrolpoint"})
public class BasedataPatrolPointController extends BaseController {
    private final IBasedataPatrolPointService basedataPatrolPointService;
    private final IBasedataStdPatrolPointService basedataStdPatrolPointService;
    private final IBasedataDeviceService basedataDeviceService;
    private final IBasedataAlgSubtypeService basedataAlgSubtypeService;
    private final String INSERT_PATROL_POINT_PURPOSE = "数据分析,在线监视";
    final
    BasedataMontPatrolPointHandleComponent basedataMontPatrolPointHandleComponent;

    public BasedataPatrolPointController(IBasedataPatrolPointService basedataPatrolPointService, IBasedataStdPatrolPointService basedataStdPatrolPointService, IBasedataDeviceService basedataDeviceService, IBasedataAlgSubtypeService basedataAlgSubtypeService, BasedataMontPatrolPointHandleComponent basedataMontPatrolPointHandleComponent) {
        this.basedataPatrolPointService = basedataPatrolPointService;
        this.basedataStdPatrolPointService = basedataStdPatrolPointService;
        this.basedataDeviceService = basedataDeviceService;
        this.basedataAlgSubtypeService = basedataAlgSubtypeService;
        this.basedataMontPatrolPointHandleComponent = basedataMontPatrolPointHandleComponent;
    }

    @RequiresPermissions({"basedata/patrolpointmnt:patrolpoint:list"})
    @GetMapping({"/list"})
    public TableDataInfo list(BasedataPatrolPoint basedataPatrolpoint) {
        this.startPage();
        List<BasedataPatrolPoint> basedataPatrolPointList = basedataPatrolPointService.selectBasedataPatrolPointList(basedataPatrolpoint);
        if (!basedataPatrolPointList.isEmpty()) {
            for (BasedataPatrolPoint patrolPoint : basedataPatrolPointList) {
                if (!StringUtils.isEmpty(patrolPoint.getAlarmThreshold())) {
                    List<BasedataAlgSubtype> defectTypes = basedataAlgSubtypeService.selectBasedataAlgSubtypeList(new BasedataAlgSubtype());
                    Map<String, String> map = new HashMap<>();
                    defectTypes.forEach((item) -> {
                        map.put(item.getAlgSubtypeCode(), item.getAlgSubtypeName());
                    });
                    List<JSONObject> jsonArray = JSONArray.parseArray(patrolPoint.getAlarmThreshold(), JSONObject.class);
                    String algSubtypeNames = jsonArray.stream().map((item) -> map.get(item.getString("code"))).collect(Collectors.joining(","));
                    patrolPoint.setAlgSubtypeName(algSubtypeNames);
                }
            }
        }

        return this.getDataTable(basedataPatrolPointList);
    }

    @GetMapping({"/list/monitor"})
    public TableDataInfo monitorList(BasedataPatrolPoint basedataPatrolpoint) {
        startPage();
        if (null == basedataPatrolpoint.getDeviceId()) {
            return getDataTable(new ArrayList<>());
        } else {
            logger.info("[META] monitorList: basedataPatrolPoint: {}", basedataPatrolpoint);
            List<BasedataPatrolPoint> list = basedataPatrolPointService.selectBasedataMonitorList(basedataPatrolpoint);
            logger.info("[META] deviceId: {}, size: {}", basedataPatrolpoint.getDeviceId(), list.size());
            List<BasedataPatrolPoint> listEx = new ArrayList<>();
            for(int i = 0; i < list.size(); i++) {
                BasedataPatrolPoint basedataPatrolPoint = list.get(i);
                logger.info(Color.GREEN + "[META] monitorList result: {}" + Color.END, basedataPatrolPoint);
                BasedataPatrolPoint basedataPatrolPoint2 = new BasedataPatrolPoint();
                basedataPatrolPoint2.setDeviceId(basedataPatrolpoint.getDeviceId());
                basedataPatrolPoint2.setPatrolPointId(basedataPatrolPoint.getPatrolPointId());
                basedataPatrolPoint2.setDeviceId(basedataPatrolPoint.getDeviceId());
                basedataPatrolPoint2.setMainDeviceId(basedataPatrolPoint.getMainDeviceId());
                basedataPatrolPoint2.setPatrolPointCode(basedataPatrolPoint.getPatrolPointCode());
                basedataPatrolPoint2.setPointTypeName(basedataPatrolPoint.getPointTypeName());
                basedataPatrolPoint2.setPointTypeCode(basedataPatrolPoint.getPointTypeCode());
                basedataPatrolPoint2.setPatrolPointName(basedataPatrolPoint.getPatrolPointName());
                basedataPatrolPoint2.setDeviceName(basedataPatrolPoint.getDeviceName());
                basedataPatrolPoint2.setAlgSubtypeId(basedataPatrolPoint.getAlgSubtypeId());
                basedataPatrolPoint2.setAlgSubtypeIds(basedataPatrolPoint.getAlgSubtypeIds());
                basedataPatrolPoint2.setPatrolContent(basedataPatrolPoint.getPatrolContent());
                basedataPatrolPoint2.setAreaId(basedataPatrolPoint.getAreaId());
                basedataPatrolPoint2.setDeviceTypeId(basedataPatrolPoint.getDeviceTypeId());
                basedataPatrolPoint2.setPatrolTypeId(basedataPatrolPoint.getPatrolTypeId());
                basedataPatrolPoint2.setPointImptLevel(basedataPatrolPoint.getPointImptLevel());
                basedataPatrolPoint2.setAlgSubtypeName(basedataPatrolPoint.getAlgSubtypeName());
                basedataPatrolPoint2.setPurpose(basedataPatrolPoint.getPurpose());
                basedataPatrolPoint2.setAlarmThreshold(basedataPatrolPoint.getAlarmThreshold());
                listEx.add(basedataPatrolPoint2);
            }
            return getDataTable(listEx);
        }
    }


    /**
     * 这个查询的是迁移过后的表basedata_patrolpoint_relation，basedata_device_relation
     * @param basedataPatrolpoint
     * @return
     */
    @GetMapping({"/list/monitor/relation"})
    public TableDataInfo monitorRelationList(BasedataPatrolPoint basedataPatrolpoint) {
        startPage();
        if (null == basedataPatrolpoint.getDeviceId()) {
            return getDataTable(new ArrayList<>());
        } else {
            logger.info("[META] monitorList: basedataPatrolPoint: {}", basedataPatrolpoint);
            List<BasedataPatrolPoint> list = basedataPatrolPointService.selectBasedataMonitorRelationList(basedataPatrolpoint);
            logger.info("[META] deviceId: {}, size: {}", basedataPatrolpoint.getDeviceId(), list.size());
            List<BasedataPatrolPoint> listEx = new ArrayList<>();
            for(int i = 0; i < list.size(); i++) {
                BasedataPatrolPoint basedataPatrolPoint = list.get(i);
                logger.info(Color.GREEN + "[META] monitorList result: {}" + Color.END, basedataPatrolPoint);
                BasedataPatrolPoint basedataPatrolPoint2 = new BasedataPatrolPoint();
                basedataPatrolPoint2.setDeviceId(basedataPatrolpoint.getDeviceId());
                basedataPatrolPoint2.setPatrolPointId(basedataPatrolPoint.getPatrolPointId());
                basedataPatrolPoint2.setDeviceId(basedataPatrolPoint.getDeviceId());
                basedataPatrolPoint2.setMainDeviceId(basedataPatrolPoint.getMainDeviceId());
                basedataPatrolPoint2.setPatrolPointCode(basedataPatrolPoint.getPatrolPointCode());
                basedataPatrolPoint2.setPointTypeName(basedataPatrolPoint.getPointTypeName());
                basedataPatrolPoint2.setPointTypeCode(basedataPatrolPoint.getPointTypeCode());
                basedataPatrolPoint2.setPatrolPointName(basedataPatrolPoint.getPatrolPointName());
                basedataPatrolPoint2.setDeviceName(basedataPatrolPoint.getDeviceName());
                basedataPatrolPoint2.setAlgSubtypeId(basedataPatrolPoint.getAlgSubtypeId());
                basedataPatrolPoint2.setAlgSubtypeIds(basedataPatrolPoint.getAlgSubtypeIds());
                basedataPatrolPoint2.setPatrolContent(basedataPatrolPoint.getPatrolContent());
                basedataPatrolPoint2.setAreaId(basedataPatrolPoint.getAreaId());
                basedataPatrolPoint2.setDeviceTypeId(basedataPatrolPoint.getDeviceTypeId());
                basedataPatrolPoint2.setPatrolTypeId(basedataPatrolPoint.getPatrolTypeId());
                basedataPatrolPoint2.setPointImptLevel(basedataPatrolPoint.getPointImptLevel());
                basedataPatrolPoint2.setAlgSubtypeName(basedataPatrolPoint.getAlgSubtypeName());
                basedataPatrolPoint2.setPurpose(basedataPatrolPoint.getPurpose());
                basedataPatrolPoint2.setAlarmThreshold(basedataPatrolPoint.getAlarmThreshold());
                listEx.add(basedataPatrolPoint2);
            }
            return getDataTable(listEx);
        }
    }

    @RequiresPermissions({"basedata/patrolpointmnt:patrolpoint:export"})
    @Log(
            title = "巡检点位",
            businessType = BizType.EXPORT
    )
    @PostMapping({"/export"})
    public void export(HttpServletResponse response, BasedataPatrolPoint basedataPatrolpoint) {
        List<BasedataPatrolPoint> list = this.basedataPatrolPointService.selectBasedataPatrolPointList(basedataPatrolpoint);
        ExcelUtil<BasedataPatrolPoint> util = new ExcelUtil<>(BasedataPatrolPoint.class);
        util.exportExcel(response, list, "巡检点位数据");
    }

    @RequiresPermissions({"basedata/patrolpointmnt:patrolpoint:query"})
    @GetMapping({"/{patrolpointId}"})
    public AjaxResult getInfo(@PathVariable("patrolpointId") Long patrolPointId) {
        return AjaxResult.success(this.basedataPatrolPointService.selectBasedataPatrolPointByPatrolPointId(patrolPointId));
    }

    @Log(
            title = "巡检点位",
            businessType = BizType.INSERT
    )
    @PostMapping
    public AjaxResult add(@RequestBody JSONObject jsonObject) {
        BasedataPatrolPoint basedataPatrolpoint = jsonObject.toJavaObject(BasedataPatrolPoint.class);

        String patrolPointName = basedataPatrolpoint.getPatrolPointName();
        if (StringUtils.isNotEmpty(patrolPointName) && patrolPointName.length() > 255) {
            return AjaxResult.error("点位名称长度不能超过255个字符");
        }

        String purpose = basedataPatrolpoint.getPurpose();
        if (StringUtils.isNotEmpty(purpose) && purpose.length() > 255) {
            return AjaxResult.error("单位长度不能超过255个字符");
        }

        String algSubtypeIds = basedataPatrolpoint.getAlgSubtypeIds();
        if (StringUtils.isNotEmpty(algSubtypeIds) && algSubtypeIds.split(",").length > 10) {
            return AjaxResult.error("点位算法请勿配置超过10个");
        }

        if (null != basedataPatrolpoint.getStdParolPointId()) {
            this.combinePatrolPointByStd(basedataPatrolpoint);
        }

        if (null != basedataPatrolpoint.getDeviceId()) {
            BasedataDevice basedataDevice = this.basedataDeviceService.selectBasedataDeviceByDeviceId(basedataPatrolpoint.getDeviceId());
            basedataPatrolpoint.setDeviceTypeId(basedataDevice.getDeviceTypeId());

            while (null != basedataDevice.getParentId() && basedataDevice.getParentId() != 0L) {
                basedataDevice = this.basedataDeviceService.selectBasedataDeviceByDeviceId(basedataDevice.getParentId());
                if (basedataDevice == null) {
                    break;
                }
            }

            assert basedataDevice != null;
            basedataPatrolpoint.setMainDeviceId(basedataDevice.getDeviceId());
        }
        basedataPatrolpoint.setRelationAreaId(basedataPatrolpoint.getAreaId());
        basedataPatrolpoint.setRelationDeviceId(basedataPatrolpoint.getDeviceId());
        basedataPatrolpoint.setRelationMainDeviceId(basedataPatrolpoint.getMainDeviceId());

        basedataPatrolPointService.insertBasedataPatrolPoint(basedataPatrolpoint);
        if (basedataPatrolpoint.getPatrolPointId() == null) {
            return AjaxResult.error("新增异常");
        }
        basedataPatrolpoint.setPatrolPointCode(String.valueOf(basedataPatrolpoint.getPatrolPointId()));
        basedataPatrolPointService.updateBasedataPatrolPoint(basedataPatrolpoint);
        return AjaxResult.success(basedataPatrolpoint.getPatrolPointId());
    }

    private void combinePatrolPointByStd(BasedataPatrolPoint basedataPatrolpoint) {
        BasedataStdPatrolPoint basedataStdpatrolPoint = this.basedataStdPatrolPointService.selectBasedataStdPatrolPointByStdPatrolPointId(basedataPatrolpoint.getStdParolPointId());
        BasedataDevice basedataDevice = this.basedataDeviceService.selectBasedataDeviceByDeviceId(basedataPatrolpoint.getDeviceId());
        basedataPatrolpoint.setPatrolContent(basedataStdpatrolPoint.getPatrolContent());
        basedataPatrolpoint.setPurpose(INSERT_PATROL_POINT_PURPOSE);
        basedataPatrolpoint.setDeviceTypeId(basedataDevice.getDeviceTypeId());
        if (StringUtils.isEmpty(basedataPatrolpoint.getPatrolPointName())) {
            basedataPatrolpoint.setPatrolPointName(basedataStdpatrolPoint.getStdPatrolPointName());
        }

    }

    @RequiresPermissions({"basedata/patrolpointmnt:patrolpoint:edit"})
    @Log(
            title = "巡检点位",
            businessType = BizType.UPDATE
    )
    @PostMapping({"/edit"})
    public AjaxResult edit(@RequestBody JSONObject jsonObject) {
        BasedataPatrolPoint basedataPatrolpoint = jsonObject.toJavaObject(BasedataPatrolPoint.class);
        log.info("BASEDATA_PATROL_POINT_CONTROLLER EDIT param: {}", basedataPatrolpoint);

        String patrolPointName = basedataPatrolpoint.getPatrolPointName();
        if (StringUtils.isNotEmpty(patrolPointName) && patrolPointName.length() > 255) {
            return AjaxResult.error("点位名称长度不能超过255个字符");
        }

        String purpose = basedataPatrolpoint.getPurpose();
        if (StringUtils.isNotEmpty(purpose) && purpose.length() > 255) {
            return AjaxResult.error("单位长度不能超过255个字符");
        }

        String algSubtypeIds = basedataPatrolpoint.getAlgSubtypeIds();
        if (StringUtils.isNotEmpty(algSubtypeIds) && algSubtypeIds.split(",").length > 10) {
            return AjaxResult.error("点位算法请勿配置超过10个");
        }

        return this.toAjax(this.basedataPatrolPointService.updateBasedataPatrolPoint(basedataPatrolpoint));
    }

    @RequiresPermissions({"basedata/patrolpointmnt:patrolpoint:remove"})
    @Log(
            title = "巡检点位",
            businessType = BizType.DELETE
    )
    @PostMapping({"/remove/{patrolpointIds}"})
    public AjaxResult remove(@PathVariable("patrolpointIds") Long[] patrolPointIds) {
        int i = this.basedataPatrolPointService.selectPresetPosByPatrolPointId(patrolPointIds);
        return i > 0 ? AjaxResult.error("删除失败，存在已绑定的预置点，请先删除预置点！") : this.toAjax(this.basedataPatrolPointService.deleteBasedataPatrolPointByPatrolPointIds(patrolPointIds));
    }

    @PostMapping({"/uploadXml"})
    public AjaxResult uploadXml(@RequestPart("file") MultipartFile file, @RequestPart("sendCode") String sendCode) throws Exception {
        InputStream inputStream = file.getInputStream();
        ByteArrayOutputStream result = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];

        int l;
        while ((l = inputStream.read(buffer)) != -1) {
            result.write(buffer, 0, l);
        }

        try {
            this.basedataMontPatrolPointHandleComponent.handPointModelData(sendCode, result.toString("UTF-8"));
        } catch (Exception var7) {
            return AjaxResult.error(var7.getMessage());
        }

        return AjaxResult.success();
    }

    @GetMapping({"/upPatrolpointModel"})
    public void upPatrolPointModel(BasedataPatrolPoint basedataPatrolpoint) {
        this.basedataPatrolPointService.upPatrolPointModel(basedataPatrolpoint);
    }

    @GetMapping({"/superSystemSynPatrolpointModel"})
    public String superSystemSynPatrolPointModel(BasedataPatrolPoint basedataPatrolpoint) {
        return this.basedataPatrolPointService.superSystemSynPatrolPointModel();
    }

    @GetMapping({"/xml"})
    public String xml(DevicePointModelItem devicePointModelItem, Long[] deviceIds) {
        return this.basedataPatrolPointService.xml(devicePointModelItem, deviceIds);
    }

    @PostMapping({"/queryPatrolPointId"})
    public Long queryPatrolPointId(@RequestBody String patrolPointCode) {
        if (StringUtils.isNotEmpty(patrolPointCode)) {
            BasedataPatrolPoint basedataPatrolpoint = new BasedataPatrolPoint();
            basedataPatrolpoint.setPatrolPointCode(patrolPointCode);
            List<BasedataPatrolPoint> basedataPatrolPoints = this.basedataPatrolPointService.selectBasedataPatrolPointList(basedataPatrolpoint);
            if (basedataPatrolPoints != null && !basedataPatrolPoints.isEmpty()) {
                return basedataPatrolPoints.get(0).getPatrolPointId();
            }
        }

        return null;
    }


    /**
     * 获取巡检点位总数和异常数
     * @param
     * @return
     * 获取巡检点位的总数以及异常点位的数量。比如查询当天的异常 点位数，如果⼀个点位多次告警，算⼀次统计。
     */
    @GetMapping({"/getInspectPointStats"})
    public AjaxResult getInspectPointStats (PointStatsVo pointStatsVo) {
        return AjaxResult.success(this.basedataPatrolPointService.getInspectPointStats(pointStatsVo));
    }


    /**
     * 获取某个巡视设备相关点位最近⼀次巡检结果列表接⼝
     * @param
     * @return
     * 获取某摄像头相关点位最近⼀次巡检结果列表接⼝
     */
    @GetMapping({"/pointLatestResult"})
    public AjaxResult pointLatestResult (PointLatestResultVo pointLatestResultVo) {
        return AjaxResult.success(this.basedataPatrolPointService.pointLatestResult(pointLatestResultVo));
    }
}
