package com.mortals.xhx.module.device.web;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.OrderCol;
import com.mortals.framework.util.FileUtil;
import com.mortals.framework.utils.ReflectUtils;
import com.mortals.framework.utils.poi.ExcelUtil;
import com.mortals.framework.web.BaseCRUDJsonBodyMappingController;
import com.mortals.xhx.base.system.message.MessageService;
import com.mortals.xhx.base.system.param.service.ParamService;
import com.mortals.xhx.base.system.upload.service.UploadService;
import com.mortals.xhx.base.system.user.model.UserEntity;
import com.mortals.xhx.busiz.rsp.ApiResp;
import com.mortals.xhx.common.code.ApiRespCodeEnum;
import com.mortals.xhx.common.code.DeviceStatusEnum;
import com.mortals.xhx.common.code.YesNoEnum;
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.feign.site.ISiteFeign;
import com.mortals.xhx.module.device.model.DeviceEntity;
import com.mortals.xhx.module.device.model.DeviceQuery;
import com.mortals.xhx.module.device.service.DeviceService;
import com.mortals.xhx.module.firm.model.FirmEntity;
import com.mortals.xhx.module.firm.service.FirmService;
import com.mortals.xhx.module.platform.model.PlatformEntity;
import com.mortals.xhx.module.platform.service.PlatformService;
import com.mortals.xhx.module.product.model.ProductEntity;
import com.mortals.xhx.module.product.service.ProductService;
import com.mortals.xhx.queue.TbQueueMsgHeaders;
import com.mortals.xhx.queue.TopicPartitionInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 设备
 *
 * @author zxfei
 * @date 2022-06-27
 */
@RestController
@RequestMapping("device")
public class DeviceController extends BaseCRUDJsonBodyMappingController<DeviceService, DeviceEntity, Long> {

    @Autowired
    private ParamService paramService;
    @Autowired
    private FirmService firmService;
    @Autowired
    private ProductService productService;
    @Autowired
    private PlatformService platformService;
    @Autowired
    private MessageService messageService;
    @Autowired
    private UploadService uploadService;

    public DeviceController() {
        super.setModuleDesc("设备");
    }

    @Override
    protected void init(Map<String, Object> model, Context context) {
        this.addDict(model, "platformId", platformService.find(new PlatformEntity()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getPlatformName())));
        this.addDict(model, "productId", productService.find(new ProductEntity()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getProductName())));

        this.addDict(model, "deviceFirmId", firmService.find(new FirmEntity()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getFirmName())));
        this.addDict(model, "deviceSrc", paramService.getParamBySecondOrganize("Device", "deviceSrc"));
        this.addDict(model, "deviceDataSourceWay", paramService.getParamBySecondOrganize("Device", "deviceDataSourceWay"));

        this.addDict(model, "isReceiveMess", paramService.getParamBySecondOrganize("Device", "isReceiveMess"));
        this.addDict(model, "deviceStatus", paramService.getParamBySecondOrganize("Device", "deviceStatus"));
        this.addDict(model, "enabled", paramService.getParamBySecondOrganize("Device", "enabled"));

        super.init(model, context);
    }

    @Override
    protected void doListBefore(DeviceEntity query, Map<String, Object> model, Context context) throws AppException {
        List<OrderCol> orderColList = new ArrayList<>();
        orderColList.add(new OrderCol("createTime",OrderCol.DESCENDING));
        query.setOrderColList(orderColList);
        super.doListBefore(query, model, context);
    }

    /**
     * 下发信息
     */
    @PostMapping(value = "downMsg")
    public String downMsg(@RequestParam(value = "deviceId") Long deviceId, @RequestParam(value = "content") String content) {
        JSONObject jsonObject = new JSONObject();
        Map<String, Object> model = new HashMap<>();
        String busiDesc = this.getModuleDesc() + "下发设备消息";
        try {
            //根据设备编码查询设备
            DeviceEntity deviceEntity = this.service.get(deviceId, getContext());
            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.DOWN_TOPIC + deviceEntity.getDeviceCode()).build();
                TbQueueMsgHeaders header = new DefaultTbQueueMsgHeaders();
                header.put(MessageHeader.MESSAGETYPE, Constant.MESSAGETYPE_UPGREAD);
                JSONObject obj = new JSONObject();
                obj.put("content", content);

                ApiResp<String> sendDeviceMessageResp = this.service.sendDeviceMessage(deviceEntity, info, header, JSON.toJSONString(obj), null);
                log.info(String.format("sendMsgResp:%s", JSON.toJSONString(sendDeviceMessageResp)));
                if (ApiRespCodeEnum.SUCCESS.getValue() != sendDeviceMessageResp.getCode()) {
                    throw new AppException("下发消息失败！");
                }
                // Thread.sleep(50);

                //log.info(String.format("sendMsgResp:%s", JSON.toJSONString(sendDeviceMessageResp)));
            } else {
                throw new AppException("设备不存在！deviceId:" + deviceId);
            }

            // this.init(request, response, null, model, getContext());
            recordSysLog(request, busiDesc + " 【成功】");
            jsonObject.put(KEY_RESULT_DATA, model);
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("下发设备消息", e);
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            jsonObject.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return jsonObject.toJSONString();
    }


    /**
     * 设备激活
     */
    @PostMapping(value = "active")
    public Rest<Void> deviceActive(@RequestBody DeviceEntity deviceEntity) {
        String busiDesc = this.getModuleDesc() + "设备激活";
        Rest<Void> rest = Rest.ok(busiDesc + " 【成功】");
        try {
            this.service.active(deviceEntity.getDeviceCode(), getContext());
            ;
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            log.error("设备激活消息", e);
            rest = Rest.fail(super.convertException(e));
        }
        return rest;
    }

    /**
     * 设备启用停用
     */
    @PostMapping(value = "enable")
    public String deviceEnable(@RequestBody DeviceEntity deviceEntity) {
        JSONObject jsonObject = new JSONObject();
        Map<String, Object> model = new HashMap<>();
        String busiDesc = this.getModuleDesc() + "设备启用停用";
        try {
            this.service.deviceEnabled(deviceEntity.getId(),deviceEntity.getEnabled(), getContext());
            //this.init(request, response, null, model, getContext());
            recordSysLog(request, busiDesc + " 【成功】");
            jsonObject.put(KEY_RESULT_DATA, model);
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        } catch (Exception e) {
            log.error("设备启用停用消息", e);
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            jsonObject.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return jsonObject.toJSONString();
    }


    @Override
    protected int doListAfter(DeviceEntity query, Map<String, Object> model, Context context) throws AppException {
        //统计当前站点设备情况
        if (!ObjectUtils.isEmpty(query.getSiteId())) {
            List<DeviceEntity> deviceEntityList = this.service.find(query, context);
            if (!ObjectUtils.isEmpty(deviceEntityList)) {
                model.put("totalCount", deviceEntityList.size());
                model.put("onlineCount", deviceEntityList.stream().filter(f -> f.getDeviceStatus() == DeviceStatusEnum.在线.getValue()).count());
                model.put("offlineCount", deviceEntityList.stream().filter(f -> f.getDeviceStatus() == DeviceStatusEnum.离线.getValue()).count());
                model.put("stopCount", deviceEntityList.stream().filter(f -> f.getDeviceStatus() != DeviceStatusEnum.未激活.getValue() && f.getEnabled() == YesNoEnum.NO.getValue()).count());
                model.put("unActiveCount", deviceEntityList.stream().filter(f -> f.getDeviceStatus() == DeviceStatusEnum.未激活.getValue()).count());
            }
        }
        return super.doListAfter(query, model, context);
    }


    /**
     * 首页统计
     */
    @PostMapping(value = "indexStat")
    public String indexStat() {
        JSONObject jsonObject = new JSONObject();
        Map<String, Object> model = new HashMap<>();
        jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_SUCCESS);
        jsonObject.put(KEY_RESULT_MSG, "");
        try {
            jsonObject.put(KEY_RESULT_DATA, model);
            recordSysLog(request,  "首页统计 【成功】");
        } catch (Exception e) {
            log.error("异常", e);
            jsonObject.put(KEY_RESULT_CODE, VALUE_RESULT_FAILURE);
            jsonObject.put(KEY_RESULT_MSG, super.convertException(e));
        }
        return jsonObject.toJSONString();
    }


    @Override
    public void doImportDataBefore(List<DeviceEntity> list, boolean updateSupport, Context context) throws AppException {
        String siteId = request.getParameter("siteId");
        if(!ObjectUtils.isEmpty(siteId)){
            list.stream().forEach(item->item.setSiteId(Convert.toLong(siteId,0L)));
        }
        list.stream().peek(item -> {
                    if (!ObjectUtils.isEmpty(item.getPicObj())) {
                        String extension = item.getPicObj().suggestFileExtension();
                        String newName = "/file/uploadfile/" + new Date().getTime() + "." + extension;
                        String filePath = uploadService.getFilePath(newName);
                        try {
                            boolean bool = FileUtil.write(filePath, item.getPicObj().getData(), true, true);
                            if (bool) {
                                item.setDevicePhotoPath(newName);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
        ).count();

        super.doImportDataBefore(list, updateSupport, context);
    }


}