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

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.annotation.UnAuth;
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.model.PageInfo;
import com.mortals.framework.model.Result;
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.*;
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.pdu.RespData;
import com.mortals.xhx.common.pdu.site.SitePdu;
import com.mortals.xhx.common.pdu.skin.SkinBasePdu;
import com.mortals.xhx.feign.site.ISiteFeign;
import com.mortals.xhx.feign.skin.ISkinBaseFeign;
import com.mortals.xhx.module.device.model.DeviceEntity;
import com.mortals.xhx.module.device.model.DeviceMapEntity;
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.module.sitestat.model.SitestatEntity;
import com.mortals.xhx.module.sitestat.model.SitestatQuery;
import com.mortals.xhx.queue.TbQueueMsgHeaders;
import com.mortals.xhx.queue.TopicPartitionInfo;
import lombok.extern.slf4j.Slf4j;
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;

import static com.mortals.framework.ap.SysConstains.MESSAGE_INFO;
import static com.mortals.framework.ap.SysConstains.PAGEINFO_KEY;

/**
 * 设备
 *
 * @author zxfei
 * @date 2022-06-27
 */
@RestController
@RequestMapping("device")
@Slf4j
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;
    @Autowired
    private ISkinBaseFeign skinBaseFeign;
    @Autowired
    private ISiteFeign siteFeign;

    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, "productCode", productService.find(new ProductEntity()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getProductCode())));

        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", DeviceStatusEnum.getEnumMap());
        this.addDict(model, "enabled", paramService.getParamBySecondOrganize("Device", "enabled"));
        this.addDict(model, "source", DeviceSourceEnum.getEnumMap());

        //返回产品列表及其样式
        //productService.find(new ProductEntity()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getProductName())).
        Rest<RespData<List<SkinBasePdu>>> resp = skinBaseFeign.list(new SkinBasePdu());
        log.info("skinBaseFeignResp:{}",JSON.toJSONString(resp));
        if (resp.getCode() == YesNoEnum.YES.getValue()) {
            Map<String, Map<String, String>> skinProductCodeMap = resp.getData().getData().stream().collect(Collectors.groupingBy(x -> x.getProductCode(), Collectors.toMap(a -> a.getImageResolution(), b -> b.getImageResolutionValue(),(o,n)->n)));
            this.addDict(model, "skinProductCodeMap", skinProductCodeMap);
        }
        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);
    }

    @Override
    protected int viewAfter(Long id, Map<String, Object> model, DeviceEntity entity, Context context) throws AppException {
        if(ObjectUtils.isEmpty(entity.getLon())){
            Rest<SitePdu> resp = siteFeign.info(entity.getSiteId());
            if(resp.getCode()==YesNoEnum.YES.getValue()){
                entity.setLon(entity.getLon());
                entity.setLati(entity.getLati());
            }
        }
        return super.viewAfter(id, model, entity, context);
    }

    /**
     * 设备激活
     */
    @PostMapping(value = "active")
    public Rest<Void> deviceActive(@RequestBody DeviceEntity deviceEntity) {
        log.info("设备激活：{}", deviceEntity.getDeviceCode());
        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+ EnabledEnum.getByValue(deviceEntity.getEnabled()).getDesc() + " 【成功】");
            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 = "stopOrStartComsumeQueue")
    public String stopOrStartComsumeQueue(@RequestBody DeviceEntity deviceEntity) {
        JSONObject jsonObject = new JSONObject();
        Map<String, Object> model = new HashMap<>();
        String busiDesc = this.getModuleDesc() + "设备消费队列";
        try {
            this.service.stopOrStartComsumeQueue(deviceEntity.getId(), deviceEntity.getEnabled(), getContext());
            recordSysLog(request, busiDesc+EnabledEnum.getByValue(deviceEntity.getEnabled()).getDesc() + " 【成功】");
            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())) {
            DeviceQuery deviceQuery = new DeviceQuery();
            deviceQuery.setSiteId(query.getSiteId());
            List<DeviceEntity> deviceEntityList = this.service.find(deviceQuery, 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();
    }


    @PostMapping(value = "maplist")
    @UnAuth
    public Rest<Object> maplist(@RequestBody DeviceEntity query) {
        Map<String, Object> model = new HashMap<>();
        Context context = this.getContext();
        String busiDesc = "查询" + this.getModuleDesc();
        try {
            List<DeviceMapEntity> list = this.service.deviceMap(query, context);
            model.put(KEY_RESULT_DATA, list);
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            this.doException(request, busiDesc, model, e);
            return Rest.fail(e.getMessage());
        }
        this.init(model, context);

        return Rest.ok(model);
    }


    @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);
    }


    @Override
    protected int editAfter(Long id, Map<String, Object> model, DeviceEntity entity, Context context) throws AppException {
        if(!ObjectUtils.isEmpty(entity.getProductId())){
            ProductEntity productEntity = productService.get(entity.getProductId());
            entity.setProductCode(productEntity.getProductCode());
        }
        return super.editAfter(id, model, entity, context);
    }
}