package com.mortals.xhx.module.device.service.impl;

import com.alibaba.fastjson.JSON;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.impl.AbstractCRUDCacheServiceImpl;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.xhx.common.code.DeviceMethodEnum;
import com.mortals.xhx.common.code.DeviceStatusEnum;
import com.mortals.xhx.common.code.EnabledEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.common.pdu.LoginForm;
import com.mortals.xhx.common.pdu.RespData;
import com.mortals.xhx.common.pdu.device.DevicePdu;
import com.mortals.xhx.common.pdu.device.DeviceReq;
import com.mortals.xhx.common.pdu.product.ProductPdu;
import com.mortals.xhx.common.pdu.site.SitePdu;
import com.mortals.xhx.common.utils.BeanUtil;
import com.mortals.xhx.feign.device.IDeviceFeign;
import com.mortals.xhx.feign.site.ISiteFeign;
import com.mortals.xhx.module.device.dao.DeviceDao;
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 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.stereotype.Service;
import org.springframework.util.ObjectUtils;

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

/**
* DeviceService
* 设备 service实现
*
* @author zxfei
* @date 2023-02-25
*/
@Service("deviceService")
@Slf4j
public class DeviceServiceImpl extends AbstractCRUDCacheServiceImpl<DeviceDao, DeviceEntity, Long> implements DeviceService {

    @Autowired
    private IDeviceFeign deviceFeign;
    @Value("${token.loginName:'admin'}")
    private String loginName;
    @Value("${token.password:'admin'}")
    private String password;


    @Autowired
    private ISiteFeign siteFeign;


    @Override
    protected String getExtKey(DeviceEntity data) {
        return data.getDeviceCode();
    }


    @Override
    public void active(String deviceCode, Context context) {
        DeviceEntity deviceEntity = this.selectOne(new DeviceQuery().deviceCode(deviceCode));
        if (ObjectUtils.isEmpty(deviceEntity)) throw new AppException("当前设备不存在！");
        if (deviceEntity.getDeviceStatus() > DeviceStatusEnum.未激活.getValue())
            throw new AppException("当前设备已激活！");
        deviceEntity.setDeviceStatus(DeviceStatusEnum.离线.getValue());
        deviceEntity.setEnabled(EnabledEnum.启用.getValue());
        this.getDao().update(deviceEntity);
        this.putCache(deviceEntity.getId().toString(), deviceEntity);

        DeviceReq deviceReq = new DeviceReq();
        deviceReq.setReceiveMethod(DeviceMethodEnum.ACTIVE.getValue());
        deviceReq.setDeviceCode(deviceCode);
        Rest<String> rest = deviceFeign.deviceCall(deviceReq);
        log.info("激活结果：{}", JSON.toJSONString(rest));
    }

    @Override
    public void deviceEnabled(Long id, Integer enabled, Context context) {
        DeviceEntity deviceEntity = this.get(id, context);
        if (ObjectUtils.isEmpty(deviceEntity)) throw new AppException("当前设备不存在！");
        deviceEntity.setEnabled(enabled);
        deviceEntity.setUpdateTime(new Date());
        deviceEntity.setUpdateUserId(getContextUserId(context));
        this.getDao().update(deviceEntity);
        this.putCache(deviceEntity.getId().toString(), deviceEntity);
        DeviceReq deviceReq = new DeviceReq();
        deviceReq.setReceiveMethod(DeviceMethodEnum.ENABLED.getValue());
        deviceReq.setDeviceCode(deviceEntity.getDeviceCode());
        Rest<String> rest = deviceFeign.deviceCall(deviceReq);
        log.info("启用结果：{}", JSON.toJSONString(rest));
    }

    @Override
    public void syncDevice() {
        Long productId = null;
        ProductPdu productPdu = new ProductPdu();
        productPdu.setProductCode("ybj");
        Rest<RespData<List<ProductPdu>>> rest = deviceFeign.list(productPdu);
        if (rest.getCode() == YesNoEnum.YES.getValue() && !ObjectUtils.isEmpty(rest.getData())) {
            if (!ObjectUtils.isEmpty(rest.getData().getData())) {
                ProductPdu pdu = rest.getData().getData().get(0);
                productId = pdu.getId();
            }
        }

        SitePdu sitePdu = new SitePdu();
        sitePdu.setId(1L);
        Rest<List<SitePdu>> siteRest = siteFeign.getFlatSitesBySiteId(sitePdu);
        if (siteRest.getCode() == YesNoEnum.YES.getValue()) {
            log.info("站点总数量：{}", siteRest.getData().size());
            for (SitePdu site : siteRest.getData()) {
                log.info("站点名称:{}", site.getSiteName());
                DevicePdu devicePdu = new DevicePdu();
                if (!ObjectUtils.isEmpty(productId)) {
                    devicePdu.setProductId(productId);
                } else {
                    devicePdu.setProductName("样表机");
                }
                devicePdu.setSiteId(site.getId());
                devicePdu.setSize(-1);
                Rest<RespData<List<DevicePdu>>> deviceRest = deviceFeign.list(devicePdu);
                log.info("deviceRest：{}", JSON.toJSONString(deviceRest));
                if (YesNoEnum.YES.getValue() == deviceRest.getCode()) {
                    List<DevicePdu> devicePduList = deviceRest.getData().getData();
                    log.info("样表机总数量：{}", devicePduList.size());
                    if (!ObjectUtils.isEmpty(devicePduList)) {
                        List<DeviceEntity> newDeviceList = devicePduList.stream().map(newDevice -> {
                            DeviceEntity deviceEntity = new DeviceEntity();
                            deviceEntity.initAttrValue();
                            BeanUtils.copyProperties(newDevice, deviceEntity, BeanUtil.getNullPropertyNames(newDevice));
                            deviceEntity.setDeviceId(newDevice.getId());
                            return deviceEntity;
                        }).collect(Collectors.toList());

                        List<DeviceEntity> oldDeviceList = this.find(new DeviceQuery().siteId(site.getId()));
                        log.info("siteId:{} oldDeviceList size：{}", site.getId(), oldDeviceList.size());

                        Map<String, DeviceEntity> oldDeviceMap = oldDeviceList.stream().collect(Collectors.toMap(x -> x.getDeviceCode(), y -> y, (o, n) -> n));
                        Map<String, DeviceEntity> newDeviceMap = newDeviceList.stream().collect(Collectors.toMap(x -> x.getDeviceCode(), y -> y, (o, n) -> n));

                        //log.info("oldDeviceMap：{}", JSON.toJSONString(oldDeviceMap));

                        List<DeviceEntity> updateDeviceLsit = newDeviceList.stream().map(item -> {
                            if (oldDeviceMap.containsKey(item.getDeviceCode())) {
                                item.setId(oldDeviceMap.get(item.getDeviceCode()).getId());
                                // item.setDeviceId(item.getId());
                                item.setProductCode(oldDeviceMap.get(item.getDeviceCode()).getProductCode());
                                item.setProductName(oldDeviceMap.get(item.getDeviceCode()).getProductName());
                                item.setUpdateTime(new Date());
                                return item;
                            }
                            return null;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        List<DeviceEntity> saveDeviceList = newDeviceList.stream().map(item -> {
                            //log.info("deviceCode:{},oldDeviceMap:{}",item.getDeviceCode(),oldDeviceMap.containsKey(item.getDeviceCode()));
                            if (!oldDeviceMap.containsKey(item.getDeviceCode())) {
                                //  item.setDeviceId(item.getId());
                                item.setCreateUserId(1L);
                                item.setProductName("样表机");
                                item.setCreateUserName("系统管理员");
                                item.setCreateTime(new Date());
                                return item;
                            }
                            return null;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        //做差集
                        List<Long> delDeviceList = oldDeviceList.stream().map(item -> {
                            if (!newDeviceMap.containsKey(item.getDeviceCode())) {
                                return item.getId();
                            }
                            return null;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        if (!ObjectUtils.isEmpty(updateDeviceLsit)) {
                            log.info("设备更新，size:{}", updateDeviceLsit.size());
                            this.update(updateDeviceLsit);
                        }

                        if (!ObjectUtils.isEmpty(saveDeviceList)) {
                            log.info("设备新增，size:{}", saveDeviceList.size());
                            this.save(saveDeviceList);
                        }

                        if (!ObjectUtils.isEmpty(delDeviceList)) {
                            log.info("设备删除，size:{}", delDeviceList.size());
                            this.remove(delDeviceList, null);
                        }
                    }
                } else {
                    log.info("设备列表查询异常，{}", JSON.toJSONString(deviceRest));
                }
            }
        } else {
            log.info("站点列表查询异常，{}", JSON.toJSONString(siteRest));
        }
    }


/*    private String getToken() {
        LoginForm loginForm = new LoginForm();
        loginForm.setLoginName(loginName);
        loginForm.setPassword(password);
        Rest<String> rest = deviceFeign.getToken(loginForm);
        String token = rest.getData();
        return token;
    }*/
}