package com.zd.laboratory.onemachine.controller;

import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.zd.common.core.constant.SecurityConstants;
import com.zd.common.core.domain.R;
import com.zd.common.core.enums.HardwareTypeEnum;
import com.zd.common.core.enums.SignEnum;
import com.zd.common.core.exception.ServiceException;
import com.zd.common.core.utils.*;
import com.zd.common.core.web.controller.BaseController;
import com.zd.common.core.web.domain.ResultData;
import com.zd.common.core.web.page.TableDataInfo;
import com.zd.common.swagger.config.Knife4jConfiguration;
import com.zd.laboratory.domain.FaceVO;
import com.zd.laboratory.domain.LabRotationChart;
import com.zd.laboratory.domain.dto.LabHazardDTO;
import com.zd.laboratory.domain.dto.LabHazardNewVo;
import com.zd.laboratory.domain.vo.SubLayoutVO;
import com.zd.laboratory.domain.vo.SubSimpleVO;
import com.zd.laboratory.mapper.LabHazardMapper;
import com.zd.laboratory.mqtt.service.impl.SubMessageSendManager;
import com.zd.laboratory.onemachine.domain.SignInPerInfoVO;
import com.zd.laboratory.onemachine.service.OneMachineService;
import com.zd.laboratory.service.*;
import com.zd.laboratory.service.impl.LabSubjectManagerService;
import com.zd.system.api.RemoteUserService;
import com.zd.system.api.domain.SysLogoConfigVO;
import com.zd.system.api.domain.SysUser;
import com.zd.system.api.laboratory.domain.SensorFunctionStatus;
import com.zd.system.api.laboratory.domain.vo.HardwareCVO;
import com.zd.system.api.laboratory.domain.vo.SenseValVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: zhoupan
 * @Date: 2021/09/15/10:35
 * @Description:
 */
@RestController
@RequestMapping("/onemachine")
@ApiSupport(author = Knife4jConfiguration.Author.ZP)
@Api(tags = {"【一体机】"})
public class OneMachineController extends BaseController {
    /**
     * 用户服务
     */
    @Autowired
    private RemoteUserService userService;
    /**
     * 一体机服务
     */
    @Autowired
    OneMachineService oneMachineService;
    /**
     * 实验室
     */
    @Autowired
    ILabSubjectService subjectService;
    @Autowired
    private LabHazardMapper labHazardMapper;
    @Autowired
    private LabSubjectManagerService subjectManagerService;

    @Autowired
    private ILabSafeClasstypeService safeClasstypeService;
    @Autowired
    private ILabHardwareService labHardwareService;

    /**
     * 硬件服务
     */
    @Autowired
    ILabHardwareService hardwareService;

    @Autowired
    ILabRiskPlanAbnormalGroupService labRiskPlanAbnormalGroupService;

    @Autowired
    private ILabRotationChartService labRotationChartService;

    @Autowired
    private ILabSubjectAccessRecordService labSubjectAccessRecordService;

    @Autowired
    private FileConfigUtils fileConfigUtils;

    @Autowired
    private SubMessageSendManager messageSendService;

//    /**
//     * 最低危险等级
//     */
//    @Autowired
//    private LabSubClassVO getNONELabSubClassVO;


    @ApiOperation("实验室信息-登录获取实验室信息（待完善）")
    @GetMapping("/{id}")
    public ResultData<SubSimpleVO> querySubInfoById(@PathVariable("id") String num) {
        //转换实验室ID
        Long aLong = labHardwareService.querySubIdByNum(num);
        Assert.isNotNull(aLong, "无法获取一体机对应实验室信息");

        //todo 根据接收的参数 :设备ID 获取一体机绑定实验室ID
        SubSimpleVO subSimpleVO = subjectManagerService.querySubSimpleVO(aLong);
        //获取一体机logo图片信息
        R<SysLogoConfigVO> configLogoResult = userService.getConfigLogo();
        if (R.SUCCESS == configLogoResult.getCode()) {
            SysLogoConfigVO sysLogoConfig = configLogoResult.getData();
            subSimpleVO.setSignMap(fileConfigUtils.getLocalUrl()+sysLogoConfig.getSignMap());
            subSimpleVO.setVideoCover(fileConfigUtils.getLocalUrl()+sysLogoConfig.getVideoCover());
            subSimpleVO.setOperationGuide(fileConfigUtils.getLocalUrl()+sysLogoConfig.getOperationGuide());
            subSimpleVO.setRectangleLogo(fileConfigUtils.getLocalUrl()+sysLogoConfig.getRectangleLogo());
        }
        return ResultData.success(subSimpleVO);
    }

//    @ApiOperation("实验室安全信息")
//    @GetMapping("/safe/{subId}")
//    public ResultData<LabSafeClasstype> querySecurityInfoById(@PathVariable("subId") Long subId) {
//        //获取实验室安全等级，如果没，则获取最低危险等级
//        LabSafeClasstype labSafeClasstype = safeClasstypeService.selectLabSafeClasstypeById(getNONELabSubClassVO.getClasstypeId());
//        return ResultData.success(labSafeClasstype);
//    }

    @ApiOperation("实验室传感器信息")
    @GetMapping("/{subId}/sensor/val/list")
    public ResultData<List<SenseValVO>> querySubValList(@PathVariable("subId") Long subId) {
        List<SenseValVO> senseValVOS = subjectManagerService.querySenseValVOSBySubId(subId);
        //todo 设备来了完善
        return ResultData.success(senseValVOS);
    }

    @ApiOperation("实验室测点功能列表")
    @GetMapping("/{subId}/function/list")
    public ResultData<List<SensorFunctionStatus>> querySubFunctionList(@PathVariable("subId") Long subId) {
        List<SensorFunctionStatus> list = subjectManagerService.querySenseFunctionBySubId(subId);
        //todo 设备来了完善
        return ResultData.success(list);
    }


    @ApiOperation("获取实验室一体机可控制设备-仅电源和智能通风")
    @GetMapping("/{subId}/controller/list")
    public ResultData<List<HardwareCVO>> querySubHardwareValList(@PathVariable("subId") Long subId) {

        List<HardwareCVO> hardwareCVOS = subjectManagerService.queryHardwareCVOSBySubId(subId);
        //只需要电源和智能通风
        List<HardwareCVO> collect = hardwareCVOS.stream().filter(a -> {
            if (HardwareTypeEnum.AI_VENTILATION.equals(a.getHardwareTypeEnum()) || HardwareTypeEnum.SWITCH.equals(a.getHardwareTypeEnum())) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());
        return ResultData.success(collect);
    }


    @ApiOperation("获取平面图信息")
    @GetMapping("/{subId}/layer")
    public ResultData<SubLayoutVO> querySubLayer(@PathVariable("subId") Long subId) {
        return ResultData.success(subjectManagerService.querySubLayoutById(subId));
    }

    @ApiOperation("危险源信息")
    @GetMapping("/{subId}/Hazard/list")
    public TableDataInfo<List<LabHazardNewVo>> queryHazardList(@PathVariable("subId") Long subId) {
        LabHazardDTO labHazard = new LabHazardDTO();
        labHazard.setSubjectId(subId);
        startPage();
        List<LabHazardNewVo> labHazardVOS = labHazardMapper.selectLabHazardListVO(labHazard);
        for(LabHazardNewVo labHazardNewVo: labHazardVOS){
            String content=labHazardNewVo.getContent();
            content= EscapeUtils.unescape(content);
            Document doc = Jsoup.parse(content);
            Elements imgs=doc.getElementsByTag("img");
            for(Element img:imgs){
                String url=fileConfigUtils.getLocalUrl()+"/"+img.attr("src");
                url= UrlFormatUtils.getHttpsORHttpUrl(url);
                img.attr("src",url);
            }
            Elements videos=doc.getElementsByTag("video");
            for(Element video: videos){
                String url=fileConfigUtils.getLocalUrl()+"/"+video.attr("src");
                url= UrlFormatUtils.getHttpsORHttpUrl(url);
                video.attr("src",url);
            }
            String html=EscapeUtils.escape(doc.outerHtml());
            labHazardNewVo.setContent(html);
        }
        return getDataTable(labHazardVOS);
    }

    @ApiOperation("签到验证")
    @GetMapping("/{subId}/SignInCheck/{username}")
    public ResultData<SignInPerInfoVO> checkUser(@PathVariable("username") String username, @PathVariable("subId") Long subId, HttpServletRequest request) {
        //获取指定用户信息
        // 查询用户信息
        R<SysUser> userResult = getSysUserR(username);

        //验证用户账户状态
        SysUser sysUser = userResult.getData();
        if(sysUser.getStatus()==null || !sysUser.getStatus().equals("0")){
            throw new ServiceException("用户：" + username + " 账户停用，请联系管理员");
        }

        String url="";
        String baseUrl=request.getServerName() ;
        if(baseUrl.contains("192.168")){
            url=fileConfigUtils.getLocalUrl()+sysUser.getAvatar();
        }else {
            url=fileConfigUtils.getRemoteUrl()+sysUser.getAvatar();
        }
        String imgUrl = UrlFormatUtils.getHttpsORHttpUrl(url);
        sysUser.setAvatar(imgUrl);

        //判断当天是否已签到，没有签出
//        int num=labSubjectAccessRecordService.getRecordNoOut(userResult.getData().getUserId());
//        if(num==0){
//            return ResultData.fail(600,"你已经签到了,无法进行重复签到！");
//        }
        //签证前置信息
        return ResultData.success(oneMachineService.createSignInPerInfoVO(subId, userResult.getData(), SignEnum.SIGN_IN));
    }

    @ApiOperation("签出验证")
    @GetMapping("/{subId}/SignOutCheck/{username}")
    public ResultData<SignInPerInfoVO> checkOutUser(@PathVariable("username") String username, @PathVariable("subId") Long subId) {
        //获取指定用户信息
        R<SysUser> userResult = getSysUserR(username);
        //签证前置信息
        return ResultData.success(oneMachineService.createSignInPerInfoVO(subId, userResult.getData(), SignEnum.SIGN_OUT));
    }

    @ApiOperation("签到提交")
    @PostMapping("/{code}/SignIn")
    public ResultData postSignIn(@PathVariable @ApiParam("验证码") String code, @RequestBody @ApiParam("特征数据") byte[] data) {
        return oneMachineService.postSign(code, SignEnum.SIGN_IN, data);
    }

    /**
     * 当前一体机用的 现在修改为创建一个初始化状态的签到数据 成功后返回记录ID
     *
     * @param code
     * @param faceVO
     * @return
     */
    @ApiOperation("签到提交：人脸验证")
    @PostMapping("/{code}/SignIn2")
    public ResultData postSignIn2(@PathVariable @ApiParam("验证码") String code, @RequestBody @ApiParam("特征数据") FaceVO faceVO) {
        return oneMachineService.postSign(code, SignEnum.SIGN_IN, faceVO.getData());
    }

    @ApiOperation("签到提交-字符串特征码")
    @PostMapping("/{code}/strFace/SignIn")
    public ResultData postSignIn(@PathVariable @ApiParam("验证码") String code, @RequestBody @ApiParam("特征数据") String data) {
//        return oneMachineService.faceCompare(2l, data.getBytes());
        return oneMachineService.postSign(code, SignEnum.SIGN_IN, data.getBytes());
    }

    @ApiOperation("签到提交:最终提交")
    @PostMapping("/{id}/SignIn/commit")
    public ResultData commitSign(@PathVariable @ApiParam("签到记录id") Long id) {
        return oneMachineService.commitSign(id);
    }

    /**
     * 离开提交：和签到提交不一样的点在于 不强制限制人脸验证和提交验证在一个请求链中
     *
     * @param code
     * @return
     */
    @ApiOperation("离开提交")
    @PostMapping("/{code}/SignOut")
    public ResultData outSub(@PathVariable String code) {
        return oneMachineService.postSign(code, SignEnum.SIGN_OUT, null);
    }

    /**
     * 查询实验室当前预警测点功能
     *
     * @param subId
     * @return
     */
    @ApiOperation("查询实验室当前预警测点功能")
    @PostMapping("/{subId}/warn")
    public ResultData<List<SensorFunctionStatus>> warnFunction(@PathVariable Long subId) {
        return ResultData.success(labRiskPlanAbnormalGroupService.queryWranFunNumBySubId(subId));
    }


    /**
     * 根据卡号获取用户
     *
     * @param username
     * @return
     */
    private R<SysUser> getSysUserR(@PathVariable("username") String username) {
        //查询卡号转换到16位后去数据库查询
        if(StringUtils.isNumeric(username)) {
            Long carNum10 = Long.parseLong(username);
            String carNum16 = carNum10.toHexString(carNum10).toUpperCase();
            username = carNum16;
        }
        // 查询用户信息
        R<SysUser> userResult = userService.getUserInfoByCardNum(username, SecurityConstants.INNER);
        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }
        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
            throw new ServiceException("用户：" + username + " 不存在");
        }
        return userResult;
    }


    /**
     * 一体机查询实验室人员信息
     * 实验室id subId
     *
     * @return
     */
    @ApiOperation("一体机查询实验室人员信息")
    @PostMapping("/sub/online/user")
    public TableDataInfo querySubOnlineUser(@RequestBody Map<String, Object> params, HttpServletRequest request) {
        if (params.get("pageNum") != null && params.get("pageSize") != null) {
            startPage(Integer.parseInt(params.get("pageNum") + ""), Integer.parseInt(params.get("pageSize") + ""));
        }
        List<SysUser> sysList=oneMachineService.querySubOnlineUser(params);
        logger.error("一体机查询实验室人员信息ServerName：" + request.getServerName()+":"+request.getRemoteAddr()+request.getHeader("X-Forwarded-For"));
        logger.error("一体机查询实验室人员信息RequestUrl：" + request.getRequestURL());
        String baseUrl=request.getServerName() ;
        logger.error("baseUrl:"+baseUrl);
        String url="";
        for(SysUser sysUser: sysList){
            if(baseUrl.contains("192.168")){
                url=fileConfigUtils.getLocalUrl()+sysUser.getAvatar();
            }else {
                url=fileConfigUtils.getRemoteUrl()+sysUser.getAvatar();
            }
            url= UrlFormatUtils.getHttpsORHttpUrl(url);
            logger.error("url:"+url);
            sysUser.setAvatar(url);
        }
        return getDataTable(sysList);
    }


    /**
     * 查询一体机轮播图
     *
     * @return
     */
    @ApiOperation("查询一体机轮播图")
    @GetMapping("/rotation/chart")
    public ResultData<List<LabRotationChart>> rotationChart(String hardwareNum, HttpServletRequest request) {
        List<LabRotationChart> list=labRotationChartService.selectChartFiveList(hardwareNum);
        String url="";
        String baseUrl=request.getServerName() ;
        for(LabRotationChart rotationChart:list){
           if(baseUrl.contains("192.168")){
               url=fileConfigUtils.getLocalUrl()+rotationChart.getImgUrl();
           }else {
               url=fileConfigUtils.getRemoteUrl()+rotationChart.getImgUrl();
           }
//           String imgUrl= rotationChart.getImgUrl();
           String imgUrl = UrlFormatUtils.getHttpsORHttpUrl(url);
           rotationChart.setImgUrl(imgUrl);
        }
        return ResultData.success(list);
    }

    /****
     * 一体机logo修改通知
     * @return
     */
    @GetMapping("/logoNotice")
    public void logoNotice() {
        messageSendService.noticeFunctionToOneMachine();
    }


}
