package com.mortals.xhx.busiz.web;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.service.IAuthTokenService;
import com.mortals.framework.util.AESUtil;
import com.mortals.framework.util.DateUtils;
import com.mortals.xhx.base.framework.annotation.ApiUserAuth;
import com.mortals.xhx.base.login.web.LoginForm;
import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.base.system.user.service.UserService;
import com.mortals.xhx.busiz.req.DeviceReq;
import com.mortals.xhx.busiz.req.UploadDeviceReq;
import com.mortals.xhx.busiz.rsp.*;
import com.mortals.xhx.common.code.ActiveEnum;
import com.mortals.xhx.common.code.ApiRespCodeEnum;
import com.mortals.xhx.common.code.DeviceOnlineStatusEnum;
import com.mortals.xhx.common.code.StatusEnum;
import com.mortals.xhx.common.key.Constant;
import com.mortals.xhx.common.model.DefaultTbQueueMsgHeaders;
import com.mortals.xhx.common.model.MessageHeader;
import com.mortals.xhx.common.utils.BeanUtil;
import com.mortals.xhx.module.device.model.DeviceEntity;
import com.mortals.xhx.module.device.service.DeviceService;
import com.mortals.xhx.module.platform.model.PlatformEntity;
import com.mortals.xhx.module.platform.model.PlatformQuery;
import com.mortals.xhx.module.platform.service.PlatformService;
import com.mortals.xhx.module.product.model.ProductEntity;
import com.mortals.xhx.module.product.model.ProductQuery;
import com.mortals.xhx.module.product.service.ProductService;
import com.mortals.xhx.queue.TbQueueMsgHeaders;
import com.mortals.xhx.queue.TopicPartitionInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 设备
 *
 * @author: zxfei
 * @date: 2021/8/24 20:28
 */
@RestController
@Slf4j
@RequestMapping("/api")
public class DeviceApiController {

    @Autowired
    private DeviceService deviceService;
    @Autowired
    private ProductService productService;
    @Autowired
    private UserService userService;
    @Autowired
    private IAuthTokenService authTokenService;
    @Autowired
    private PlatformService platformService;

    @Value("${queue.rabbitmq.virtual_host:}")
    private String virtualHost;
    @Value("${queue.rabbitmq.password:}")
    private String password;
    @Value("${queue.rabbitmq.host:}")
    private String host;
    @Value("${queue.rabbitmq.port:}")
    private int port;
    @Value("${queue.rabbitmq.username:}")
    private String username;
    @Value("${token.secret}")
    private String secret;


    /**
     * 设备注册
     *
     * @param req
     * @return
     */
    @PostMapping("register")
    public String register(@RequestBody DeviceReq req) {
        log.info("【设备注册】【请求体】-->  " + JSONObject.toJSONString(req));
        ApiResp<DeviceResp> rsp = new ApiResp<>();
        rsp.setCode(ApiRespCodeEnum.SUCCESS.getValue());
        DeviceResp deviceResp = new DeviceResp();
        try {
            DeviceEntity deviceEntity = deviceService.getExtCache(req.getDeviceCode());
            if (ObjectUtils.isEmpty(deviceEntity)) {
                throw new AppException("当前设备不存在！");
            }
            if (deviceEntity.getActive() != ActiveEnum.已激活.getValue()) {
                throw new AppException("当前设备未激活，请在后台配置后再激活！");
            }

            if (deviceEntity.getStatus() != StatusEnum.启用.getValue()) {
                throw new AppException("当前设备未启用，请在后台启用当前设备！");
            }

            DeviceQueueAuthInfo authInfo = new DeviceQueueAuthInfo();
            authInfo.setHost(host);
            authInfo.setPort(port);
            authInfo.setUsername(username);
            authInfo.setPassword(password);
            authInfo.setVirtualHost(virtualHost);
            PlatformEntity platformEntity = platformService.get(deviceEntity.getPlatformId());
            if (ObjectUtils.isEmpty(platformEntity)) {
                throw new AppException("当前设备未配置所属系统平台，请在后台配置后再激活！");
            }

            ProductEntity productEntity = productService.get(deviceEntity.getProductId());
            if (ObjectUtils.isEmpty(productEntity)) {
                throw new AppException("当前设备未配置所属产品，请在后台配置后再激活！");
            }
            authInfo.setExchangeName(platformEntity.getPlatformSn() + Constant.EXCHANGE_SPLIT + productEntity.getProductCode());
            authInfo.setUploadTopicFilter(Constant.UPLOAD_TOPIC + deviceEntity.getDeviceCode());
            authInfo.setDownTopicFilter(Constant.DOWN_TOPIC + deviceEntity.getDeviceCode());
            String content = AESUtil.encryptForApp(JSON.toJSONString(authInfo), secret);
            deviceResp.setContent(content);
            deviceEntity.setOnlineTime(new Date());
            deviceEntity.setDeviceOnlineStatus(DeviceOnlineStatusEnum.在线.getValue());
            deviceService.update(deviceEntity);
            rsp.setData(deviceResp);
        } catch (Exception e) {
            log.error("接收数据失败", e);
            rsp.setCode(ApiRespCodeEnum.FAILED.getValue());
            rsp.setMsg(e.getMessage());
            return JSON.toJSONString(rsp);
        }
        log.info("响应【设备注册】【响应体】-->  " + JSONObject.toJSONString(rsp));
        return JSON.toJSONString(rsp);
    }

    /**
     * 获取Token
     *
     * @return
     */
    @PostMapping("getToken")
    public String getToken(@RequestBody LoginForm loginForm) {
        ApiResp<String> rsp = new ApiResp<>();
        rsp.setCode(ApiRespCodeEnum.SUCCESS.getValue());
        try {
            UserEntity userEntity = userService.doLogin(loginForm.getLoginName(), loginForm.getPassword(), "");
            if (!ObjectUtils.isEmpty(userEntity)) {
                this.authTokenService.setUser(userEntity);
                userEntity.setExpireTime(DateUtils.addCurrDate(7).getTime());
                userEntity.setToken(IdUtil.fastSimpleUUID());
                String token = authTokenService.createToken(userEntity);
                rsp.setData(token);
            }
        } catch (Exception e) {
            log.error("异常", e);
            rsp.setCode(ApiRespCodeEnum.FAILED.getValue());
            rsp.setMsg(e.getMessage());
            return JSON.toJSONString(rsp);
        }
        log.info("响应【获取Token】【响应体】--> {}", JSONObject.toJSONString(rsp));
        return JSON.toJSONString(rsp);
    }

    /**
     * 获取平台与产品
     *
     * @return
     */
    @GetMapping("getPlatformAndProduct")
    public String getPlatformAndProduct() {
        ApiResp<PlatformAndProductResp> rsp = new ApiResp<>();
        rsp.setCode(ApiRespCodeEnum.SUCCESS.getValue());
        PlatformAndProductResp platformAndProductResp = new PlatformAndProductResp();
        try {
            List<PlatformInfo> platformInfoList = platformService.find(new PlatformQuery()).stream().map(item -> {
                PlatformInfo platformInfo = new PlatformInfo();
                BeanUtils.copyProperties(item, platformInfo, BeanUtil.getNullPropertyNames(item));
                return platformInfo;
            }).collect(Collectors.toList());
            platformAndProductResp.setPlatformList(platformInfoList);
            List<ProductInfo> productInfoList = productService.find(new ProductQuery()).stream().map(item -> {
                ProductInfo productInfo = new ProductInfo();
                BeanUtils.copyProperties(item, productInfo, BeanUtil.getNullPropertyNames(item));
                return productInfo;
            }).collect(Collectors.toList());
            platformAndProductResp.setProductList(productInfoList);

            rsp.setData(platformAndProductResp);
        } catch (Exception e) {
            log.error("异常", e);
            rsp.setCode(ApiRespCodeEnum.FAILED.getValue());
            rsp.setMsg(e.getMessage());
            return JSON.toJSONString(rsp);
        }
        log.info("响应【获取平台与产品】【响应体】--> {}", JSONObject.toJSONString(rsp));
        return JSON.toJSONString(rsp);
    }


    /**
     * 设备数据上报
     *
     * @param req
     * @return
     */
    @PostMapping("upload")
    //@DeviceAuth
    public String upload(@RequestBody UploadDeviceReq req) {
        log.info("【设备数据上报】【请求体】-->  " + JSONObject.toJSONString(req));
        ApiResp<String> rsp = new ApiResp<>();
        rsp.setMsg(ApiRespCodeEnum.SUCCESS.getLabel());
        rsp.setCode(ApiRespCodeEnum.SUCCESS.getValue());
        try {
            //根据设备编码查询设备
            DeviceEntity deviceEntity = deviceService.getExtCache(req.getDeviceCode());
            if (!ObjectUtils.isEmpty(deviceEntity)) {
                //将上报信息转发到mq中

                PlatformEntity platformEntity = platformService.get(deviceEntity.getPlatformId());
                if (ObjectUtils.isEmpty(platformEntity)) {
                    throw new AppException("当前设备未配置所属系统平台，请在后台配置后再激活！");
                }
                // authInfo.setHost(platformEntity.getPlatformSn());
                ProductEntity productEntity = productService.get(deviceEntity.getProductId());
                if (ObjectUtils.isEmpty(productEntity)) {
                    throw new AppException("当前设备未配置所属产品，请在后台配置后再激活！");
                }
                String exchangeName = platformEntity.getPlatformSn() + Constant.EXCHANGE_SPLIT + productEntity.getProductCode();

                TopicPartitionInfo info = TopicPartitionInfo.builder().exchangeName(exchangeName).topic(Constant.UPLOAD_TOPIC + deviceEntity.getDeviceMac()).build();
                TbQueueMsgHeaders header = new DefaultTbQueueMsgHeaders();
                header.put(MessageHeader.MESSAGETYPE, Constant.MESSAGETYPE_HEARTBEAT);
                for (int i = 0; i < 1000; i++) {
                    deviceService.sendDeviceMessage(deviceEntity, info, header, JSON.toJSONString(req), null);
                    // Thread.sleep(50);
                }
                //log.info(String.format("sendMsgResp:%s", JSON.toJSONString(sendDeviceMessageResp)));
            }
        } catch (Exception e) {
            log.error("接收数据失败", e);
            rsp.setCode(ApiRespCodeEnum.FAILED.getValue());
            rsp.setMsg(e.getMessage());
            return JSON.toJSONString(rsp);
        }

        log.debug("响应【设备数据上报】【响应体】-->  " + JSONObject.toJSONString(rsp));
        return JSON.toJSONString(rsp);
    }

    /**
     * 保存或更新设备
     *
     * @param req
     * @return
     */
    @PostMapping("saveOrUpdate")
    @ApiUserAuth
    public String saveOrUpdate(@RequestBody DeviceReq req) {
        log.info("【保存或更新设备】【请求体】-->  " + JSONObject.toJSONString(req));
        ApiResp<String> rsp = new ApiResp<>();
        rsp.setMsg(ApiRespCodeEnum.SUCCESS.getLabel());
        rsp.setCode(ApiRespCodeEnum.SUCCESS.getValue());
        try {
            //根据设备编码查询设备
            DeviceEntity deviceEntity = deviceService.getExtCache(req.getDeviceCode());
            if (!ObjectUtils.isEmpty(deviceEntity)) {
                // TODO: 2022/5/13 设备更新

                //log.info(String.format("sendMsgResp:%s", JSON.toJSONString(sendDeviceMessageResp)));
            } else {
                if (ObjectUtils.isEmpty(req.getPlatformId())) {
                    throw new AppException("当前平台Id为空！");
                }
                PlatformEntity platformEntity = platformService.get(req.getPlatformId());
                if (ObjectUtils.isEmpty(platformEntity)) {
                    throw new AppException("当前设备未配置所属系统平！");
                }
                if (ObjectUtils.isEmpty(req.getProductId())) {
                    throw new AppException("当前产品Id为空！");
                }
                ProductEntity productEntity = productService.get(req.getProductId());
                if (ObjectUtils.isEmpty(productEntity)) {
                    throw new AppException("当前设备未配置所属产品，");
                }
                deviceEntity = new DeviceEntity();
                deviceEntity.initAttrValue();
                deviceEntity.setDeviceName(req.getDeviceName());
                deviceEntity.setDeviceCode(req.getDeviceCode());
                deviceEntity.setDeviceMac(req.getDeviceMac());
                deviceEntity.setSiteCode(req.getSiteCode());
                deviceEntity.setSiteName(req.getSiteName());
                deviceEntity.setIp(req.getIp());
                deviceEntity.setPort(req.getPort());
                deviceEntity.setPlatformId(platformEntity.getId());
                deviceEntity.setPlatformName(platformEntity.getPlatformName());
                deviceEntity.setProductId(productEntity.getId());
                deviceEntity.setProductName(productEntity.getProductName());
                deviceEntity.setDeviceRemark(req.getDeviceRemark());
                deviceEntity.setCreateUserId(1L);
                deviceEntity.setCreateTime(new Date());
                deviceService.save(deviceEntity);
            }
        } catch (Exception e) {
            log.error("接收数据失败", e);
            rsp.setCode(ApiRespCodeEnum.FAILED.getValue());
            rsp.setMsg(e.getMessage());
            return JSON.toJSONString(rsp);
        }

        log.info("响应【保存或更新设备】【响应体】-->  " + JSONObject.toJSONString(rsp));
        return JSON.toJSONString(rsp);
    }


    /**
     * 激活设备
     *
     * @param req
     * @return
     */
    @PostMapping("active")
    @ApiUserAuth
    public String active(@RequestBody DeviceReq req) {
        log.info("【激活设备】【请求体】-->  " + JSONObject.toJSONString(req));
        ApiResp<String> rsp = new ApiResp<>();
        rsp.setMsg(ApiRespCodeEnum.SUCCESS.getLabel());
        rsp.setCode(ApiRespCodeEnum.SUCCESS.getValue());
        try {
            //根据设备编码查询设备
            DeviceEntity deviceEntity = deviceService.getExtCache(req.getDeviceCode());
            if (ObjectUtils.isEmpty(deviceEntity)) {
                throw new AppException("当前设备不存在！");
            }
            if (deviceEntity.getActive() == ActiveEnum.已激活.getValue()) {
                throw new AppException("当前设备已激活！");
            }
            deviceEntity.setActive(ActiveEnum.已激活.getValue());
            deviceEntity.setUpdateTime(new Date());
            deviceEntity.setUpdateUserId(1L);
            deviceService.update(deviceEntity);
        } catch (Exception e) {
            log.error("接收数据失败", e);
            rsp.setCode(ApiRespCodeEnum.FAILED.getValue());
            rsp.setMsg(e.getMessage());
            return JSON.toJSONString(rsp);
        }

        log.info("响应【激活设备设备】【响应体】-->  " + JSONObject.toJSONString(rsp));
        return JSON.toJSONString(rsp);
    }


    public static void main(String[] args) {
        UserEntity userEntity = new UserEntity();
        userEntity.setToken("1231231");
        System.out.println(userEntity.getToken());
    }

}
