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

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.annotation.UnAuth;
import com.mortals.framework.ap.GlobalSysInfo;
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.web.BaseCRUDJsonBodyMappingController;
import com.mortals.xhx.base.system.param.service.ParamService;
import com.mortals.xhx.base.system.upload.service.UploadService;
import com.mortals.xhx.common.code.*;
import com.mortals.xhx.common.pdu.RespData;
import com.mortals.xhx.common.pdu.site.SiteHallPdu;
import com.mortals.xhx.common.pdu.site.SitePdu;
import com.mortals.xhx.common.pdu.skin.SkinBasePdu;
import com.mortals.xhx.common.utils.QRCodeUtil;
import com.mortals.xhx.feign.site.ISiteFeign;
import com.mortals.xhx.feign.site.ISiteHallFeign;
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.site.model.SiteEntity;
import com.mortals.xhx.module.site.service.SiteService;
import lombok.extern.slf4j.Slf4j;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

/**
 * 设备
 *
 * @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 UploadService uploadService;
    @Autowired
    private ISkinBaseFeign skinBaseFeign;
    @Autowired
    private ISiteFeign siteFeign;
    @Value("${platform.type:cloud}")
    private String platFormType;//版本，默认云服务版本
    @Autowired
    private SiteService siteService;
    @Autowired
    public ISiteHallFeign siteHallFeign;


    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", DeviceSrcEnum.getEnumMap());
        this.addDict(model, "deviceDataSourceWay", DeviceDataSourceWayEnum.getEnumMap());
        this.addDict(model, "isReceiveMess", IsReceiveMessEnum.getEnumMap());
        this.addDict(model, "deviceStatus", DeviceStatusEnum.getEnumMap());
        this.addDict(model, "enabled", EnabledEnum.getEnumMap());
        this.addDict(model, "source", DeviceSourceEnum.getEnumMap());
        this.addDict(model, "showSms", YesNoEnum.getEnumMap());
        this.addDict(model, "showPrint", YesNoEnum.getEnumMap());
        this.addDict(model, "showWechatQrCode", YesNoEnum.getEnumMap());
        //返回产品列表及其样式
        //productService.find(new ProductEntity()).stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getProductName())).
        if (platFormType.equalsIgnoreCase(PlatformTypeEnum.CLOUD.getValue())) {
            Rest<RespData<List<SkinBasePdu>>> resp = skinBaseFeign.list(new SkinBasePdu());
            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() == null ? "" : a.getImageResolution(), b -> b.getImageResolutionValue() == null ? "" : b.getImageResolutionValue(), (o, n) -> n)));
                this.addDict(model, "skinProductCodeMap", skinProductCodeMap);
            }
        }
        //siteHallFeign.list(new SiteHallPdu().setSiteId(context.g);)
        super.init(model, context);
    }

    @Override
    protected void doListBefore(DeviceEntity query, Map<String, Object> model, Context context) throws AppException {
        if (ObjectUtils.isEmpty(query.getOrderColList())) {
            query.setOrderColList(Arrays.asList(new OrderCol("createTime", OrderCol.DESCENDING)));
        }
        SiteHallPdu siteHallPdu = new SiteHallPdu();
        siteHallPdu.setSiteId(query.getSiteId());
        Rest<RespData<List<SiteHallPdu>>> rest = siteHallFeign.list(siteHallPdu);
        if(rest.getCode()==YesNoEnum.YES.getValue()){
            Map<String, String> hallMap = rest.getData().getData().stream().collect(Collectors.toMap(x -> x.getId().toString(), y -> y.getHallName(), (o, n) -> n));
            this.addDict(model, "hallId", hallMap);
        }

        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())) {
            if (platFormType.equalsIgnoreCase(PlatformTypeEnum.STANDALONE.getValue())) {
                SiteEntity siteEntity = siteService.get(entity.getSiteId(), getContext());
                if (!ObjectUtils.isEmpty(siteEntity)) {
                    entity.setLon(siteEntity.getLongitude());
                    entity.setLati(siteEntity.getLatitude());
                }
            } else {
                Rest<SitePdu> resp = siteFeign.info(entity.getSiteId());
                if (resp.getCode() == YesNoEnum.YES.getValue()) {
                    entity.setLon(resp.getData().getLongitude());
                    entity.setLati(resp.getData().getLatitude());
                }
            }
        }
        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 = "batchActive")
    public Rest<Void> deviceBatchActive(@RequestBody DeviceEntity deviceEntity) {
        log.info("批量设备激活：{}", deviceEntity.getDeviceCode());
        String busiDesc = this.getModuleDesc() + "设备激活";
        Rest<Void> rest = Rest.ok(busiDesc + " 【成功】");
        try {
            DeviceQuery deviceQuery = new DeviceQuery();
            deviceQuery.setIdList(deviceEntity.getIdList());
            List<DeviceEntity> deviceEntities = this.service.find(deviceQuery, getContext());
            for (DeviceEntity entity : deviceEntities) {
                try {
                    this.service.active(entity.getDeviceCode(), getContext());
                } catch (Exception e) {
                    log.error("设备激活", e);
                }
            }
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            log.error("批量设备激活", e);
            rest = Rest.fail(super.convertException(e));
        }
        return rest;
    }


    /**
     * 设备批量重启应用
     */
    @PostMapping(value = "batchRestartApp")
    public Rest<Void> batchRestartApp(@RequestBody DeviceEntity deviceEntity) {
        log.info("批量设备重启", deviceEntity.getDeviceCode());
        String busiDesc = this.getModuleDesc() + "设备重启";
        Rest<Void> rest = Rest.ok(busiDesc + " 【成功】");
        try {
            this.service.restartApp(deviceEntity,getContext());
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            log.error("批量设备重启", e);
            rest = Rest.fail(super.convertException(e));
        }
        return rest;
    }

    /**
     * 查看二维码
     */
    @PostMapping(value = "viewQrCode")
    public String viewQrCode(@RequestBody DeviceEntity deviceEntity) {
        JSONObject jsonObject = new JSONObject();
        try {
            if (deviceEntity.getId() == null) {
                throw new AppException("二维码为空");
            }
            String qrCodeUrl = GlobalSysInfo.getParamValue("qrcode", "http://192.168.0.98:18222/m/test");
            String productType = "phj";
            DeviceEntity device = service.get(deviceEntity.getId(), null);

            if (ObjectUtils.isEmpty(device)) throw new AppException("当前设备不存在！");
            // TODO: 2022/9/14 设备生成二维码内容待定
            String qrCode = qrCodeUrl + "?productType=" + productType + "&deviceCode=" + device.getDeviceCode();

            jsonObject.put("qrCode", "data:image/png;base64," + QRCodeUtil.encode(qrCode, null, false));
            jsonObject.put("qrCodeUrl", qrCode);
            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 = "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());
            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);
    }

    /**
     * 设备批量更新设备所属大厅
     */
    @PostMapping(value = "batchUpdateHall")
    public Rest<Void> batchUpdateHall(@RequestBody DeviceEntity deviceEntity) {
        log.info("批量设备重启:{}", deviceEntity.getDeviceCode());
        String busiDesc = this.getModuleDesc() + "批量更新所属大厅";
        Rest<Void> rest = Rest.ok(busiDesc + " 【成功】");
        try {
            this.service.batchUpdateHall(deviceEntity,getContext());
            recordSysLog(request, busiDesc + " 【成功】");
        } catch (Exception e) {
            log.error("批量更新所属大厅", e);
            rest = Rest.fail(super.convertException(e));
        }
        return rest;
    }


    @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/fileupload/" + 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);
    }


    @Override
    protected void saveBefore(DeviceEntity entity, Map<String, Object> model, Context context) throws AppException {
        super.saveBefore(entity, model, context);
        if(ObjectUtils.isEmpty(entity.getProductId())) throw new AppException("所属产品ID不能为空！");
        if(ObjectUtils.isEmpty(entity.getPlatformId())) throw new AppException("所属平台ID不能为空！");
        //判断如果存在相同的
        DeviceEntity deviceEntity = this.service.selectOne(new DeviceQuery().deviceCode(entity.getDeviceCode()));
        if(!ObjectUtils.isEmpty(deviceEntity)){
            entity.setId(deviceEntity.getId());
        }

    }

    @Override
    public void doExportBefore(Context context, DeviceEntity query, List<String> properties) throws AppException {
        super.doExportBefore(context, query, properties);
        if(ObjectUtils.isEmpty(query.getIdList())){
            query.setIdList(null);
        }
    }

    public static void main(String[] args) {
        String str2 = "510000000000".replaceAll("(0)+$", "");
        System.out.println(str2);
        //System.out.println(new BigDecimal("510105000000").stripTrailingZeros().toPlainString());
    }
}