package com.mvc.service.taizhang;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.ctg.ag.sdk.biz.aep_device_management.CreateDeviceResponse;
import com.ctg.ag.sdk.biz.aep_nb_device_management.DeleteDeviceByImeiResponse;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mvc.constant.BaseConstant;
import com.mvc.constant.DeviceState;
import com.mvc.constant.DeviceType;
import com.mvc.dao.DeviceAccMapper;
import com.mvc.entity.DeviceAcc;
import com.mvc.entity.DeviceAccExample;
import com.mvc.iot.aep.AepApiHelper;
import com.mvc.iot.aep.config.AepConfig;
import com.mvc.iot.aep.model.AepDeviceApiModel;
import com.mvc.iot.aep.model.AepResponseRootModel;
import com.mvc.iot.onenet.OneNetApiHelper;
import com.mvc.iot.onenet.config.OneNetConfig;
import com.mvc.iot.onenet.model.OneNetApiResponseModel;
import com.mvc.iot.onenet.model.OneNetDeviceApiModel;
import com.mvc.model.DeviceAccModel;
import com.mvc.utils.NumberUtil;
import com.mvc.utils.PoiUtils;
import com.mvc.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;

@Service
@Transactional
public class DeviceAccService {

    @Resource
    private DeviceAccMapper deviceAccMapper;

    @Resource
    private OneNetApiHelper oneNetApiHelper;

    @Resource
    private AepApiHelper aepApiHelper;

    @Resource
    private OneNetConfig oneNetConfig;
    @Resource
    private AepConfig aepConfig;

    //根据各种条件查询设备
    public Map<String, Object> findAllDeviceAcc(DeviceAccModel accmodel) {
        Integer page = accmodel.getPage();
        Integer rows = accmodel.getRows();
        Map<String, Object> resMap = new HashMap<>();
        Page<Object> pageObject = null;
        if (page != null && rows != null) {
            pageObject = PageHelper.startPage(page, rows);
        }
        DeviceAccExample example = new DeviceAccExample();
        DeviceAccExample.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotEmpty(accmodel.getDeviceSn())) {//根据设备sn模糊查询
            if (accmodel.getDeviceSn().length() == BaseConstant.LENGTH_DEVICE_SN) {
                criteria.andDeviceSnEqualTo(accmodel.getDeviceSn());
            } else {
                criteria.andDeviceSnLike(StringUtil.getLikeFormat(accmodel.getDeviceSn()));
            }
        }
        if (StringUtils.isNotEmpty(accmodel.getDeviceType())) {//根据设备类型
            criteria.andDeviceTypeEqualTo(accmodel.getDeviceType());
        }
//        if(StringUtils.isNotEmpty(accmodel.getDeviceType())){//根据遥测站名称
//            criteria.andDeviceTypeLike("%"+accmodel.getDeviceType()+"%");
//        }
        if (StringUtils.isNotEmpty(accmodel.getCurStateType())) {//当前状态
            List<String> liststirng = new ArrayList<String>();
            String[] split = accmodel.getCurStateType().split(",");
            for (int i = 0; i < split.length; i++) {
                liststirng.add(split[i]);
            }
            criteria.andCurStateTypeIn(liststirng);
        }
        List<DeviceAcc> deviceAccs = deviceAccMapper.selectByExample(example);
        List<DeviceAccModel> resList = new ArrayList<>();
        for (DeviceAcc acc : deviceAccs) {
            DeviceAccModel model = new DeviceAccModel();
            BeanUtils.copyProperties(acc, model);
            //设置遥测站名称(站点台账中不再登记遥测站编码)
            /*StationAccModel stationAccModel = stationAccService.findStationAccByDeviceSn(model.getDeviceSn());
            if (stationAccModel != null) {
                model.setStationCode(stationAccModel.getStationCode());
                model.setStationName(stationAccModel.getStationName());
            }*/
            model.setCurStateTypeName(DeviceState.findDeviceStateByflag(model.getCurStateType()).getDesc());
            resList.add(model);
        }
        if (page != null && rows != null) {
            resMap.put("total", pageObject.getTotal());
        }
        resMap.put("list", resList);
        return resMap;
    }

    public List<DeviceAccModel> saveDeviceAcc(DeviceAccModel model) {
        List<DeviceAccModel> resList = new ArrayList<>();
        if ("1".equals(model.getAddflag())) {//单个增加
            DeviceAcc deviceAcc = new DeviceAcc();
            model.setAccId(StringUtil.getUuid());
            model.setCreateDate(new Date());
            model.setCurStateType(DeviceState.Dengji.getFlag());
            model.setUseFlag("1");
            BeanUtils.copyProperties(model, deviceAcc);
            int insert = deviceAccMapper.insert(deviceAcc);
            model.setId(deviceAcc.getId());
            resList.add(model);
            return resList;
        } else if ("2".equals(model.getAddflag())) {//逗号分隔增加
            String[] split = model.getDeviceSn().replaceAll("，", ",").split(",");
            for (int i = 0; i < split.length; i++) {
                if (findDeviceAccBysn(split[i]) != null) {
                    continue;                   //编号重了
                }
                DeviceAcc deviceAcc = new DeviceAcc();
                model.setDeviceSn(split[i]);
                model.setAccId(StringUtil.getUuid());
                model.setCreateDate(new Date());
                model.setCurStateType(DeviceState.Dengji.getFlag());
                model.setUseFlag("1");
                BeanUtils.copyProperties(model, deviceAcc);
                int insert = deviceAccMapper.insert(deviceAcc);
                DeviceAccModel resModel = new DeviceAccModel();
                BeanUtils.copyProperties(deviceAcc, resModel);
                resList.add(resModel);
            }
        } else if ("3".equals(model.getAddflag())) {//数量增加
            int num = model.getAddnum().intValue();
            String deviceSn = model.getDeviceSn();
            for (int i = 0; i < num; i++) {
                long l = Long.valueOf(deviceSn).longValue();
                String sn = "00000000000" + (l + (int) i);
                sn = sn.substring(sn.length() - 11);          //转为数值后面前要补0 2022-08-15 guozhao
                model.setDeviceSn(sn);
                if (findDeviceAccBysn(model.getDeviceSn()) != null) {
                    continue;                   //编号重了
                }
                DeviceAcc deviceAcc = new DeviceAcc();
                model.setAccId(StringUtil.getUuid());
                model.setCreateDate(new Date());
                model.setCurStateType(DeviceState.Dengji.getFlag());
                model.setUseFlag("1");
                BeanUtils.copyProperties(model, deviceAcc);
                deviceAcc.setId(null);
                int insert = deviceAccMapper.insert(deviceAcc);
                model.setId(deviceAcc.getId());
                DeviceAccModel resModel = new DeviceAccModel();
                BeanUtils.copyProperties(deviceAcc, resModel);
                resList.add(resModel);
            }
        }
        return resList;
    }

    public DeviceAccModel updateDeviceAcc(DeviceAccModel model) {
        DeviceAcc deviceAcc = deviceAccMapper.selectByPrimaryKey(model.getId());
        BeanUtils.copyProperties(model, deviceAcc);
        int i = deviceAccMapper.updateByPrimaryKey(deviceAcc);
        return model;
    }

    public int deleteDeviceAcc(int id) {
        int i = deviceAccMapper.deleteByPrimaryKey(id);
        return i;
    }

    //根据设备sn 查询设备
    public DeviceAccModel findDeviceAccBysn(String deviceSn) {
        if (StringUtils.isEmpty(deviceSn)) return null;
        DeviceAccExample example = new DeviceAccExample();
        DeviceAccExample.Criteria criteria = example.createCriteria();
        criteria.andDeviceSnEqualTo(deviceSn);
        List<DeviceAcc> deviceAccs = deviceAccMapper.selectByExample(example);
        if (deviceAccs.size() > 0) {
            DeviceAccModel resModel = new DeviceAccModel();
            BeanUtils.copyProperties(deviceAccs.get(0), resModel);
            return resModel;
        } else {
            return null;
        }
    }

    /**
     * 检查数据合法性
     *
     * @param deviceAcc
     * @return
     */
    public String checkDataLegitimacy(DeviceAccModel deviceAcc) {
        if (deviceAcc == null || StringUtils.isEmpty(deviceAcc.getDeviceSn())) {
            return "请输入有效的设备SN";
        }

        if (deviceAcc.getAddflag().equals("1")) {
            if (!NumberUtil.isNumberic(deviceAcc.getDeviceSn())) {
                return "SN只能是纯数字;";
            }
            DeviceAccModel model = findDeviceAccBysn(deviceAcc.getDeviceSn());
            if (model != null) {
                return "SN已存在[" + deviceAcc.getDeviceSn() + "]";
            }
        } else if (deviceAcc.getAddflag().equals("2")) {
            String temp = deviceAcc.getDeviceSn().replaceAll("，", "").replaceAll(",", "");
            if (!NumberUtil.isNumberic(temp)) {
                return "SN只能是纯数字;";
            }

            String errMsg = "";
            String[] arr = deviceAcc.getDeviceSn().replace('，', ',').split(",");
            for (String sn : arr) {
                if (sn.length() != 11) {
                    errMsg += (sn + ",");
                }
            }
            return StringUtils.isNotEmpty(errMsg) ? "SN长度错误:" + errMsg : errMsg;
        } else if (deviceAcc.getAddflag().equals("3")) {
            if (deviceAcc.getDeviceSn().length() != 11) {
                return "SN长度错误:[" + deviceAcc.getDeviceSn() + "];";
            }
            if (!NumberUtil.isNumberic(deviceAcc.getDeviceSn())) {
                return "SN只能是纯数字;";
            }
            if (deviceAcc.getAddnum() == null || deviceAcc.getAddnum() < 1 || deviceAcc.getAddnum() > 9999) {
                return "设备数量不合法;";
            }
            long sn = Long.valueOf(deviceAcc.getDeviceSn());
            if (sn + deviceAcc.getAddnum() > 99999999999L) {
                return "起始编号+数量超过11位;";
            }
        }

        return "";
    }

    /**
     * 导入数据更新台账
     *
     * @param file
     * @param type
     * @param operator
     * @return
     * @throws Exception
     */
    public String importDeviceAccData(MultipartFile file, String type, String operator) throws Exception {
        String resMsg = "";
        List<DeviceAccModel> deviceAccs = readDeviceAccExcel(file);

        if (deviceAccs == null || deviceAccs.isEmpty()) {
            resMsg = "未读取到有效记录";
            return resMsg;
        }
        StringBuilder sb = new StringBuilder();
        String temp = "";
        int failNum = 0;
        for (int i = 0; i < deviceAccs.size(); i++) {
            DeviceAccModel model = deviceAccs.get(i);
            if (type.equals("1")) {//增加
                model.setCreateMan(operator);
                temp = addIotDeviceAccData(model, operator);
            } else {//删除
                temp = deleteIotDeviceAccData(model);
            }
            if (StringUtils.isNotEmpty(temp)) {
                sb.append(temp);
                sb.append(BaseConstant.HTML_NEW_LINE);
                failNum++;
            }
        }
        sb.insert(0, String.format("共%d条数据,成功%d条,失败%d条%s", deviceAccs.size(), deviceAccs.size() - failNum, failNum, BaseConstant.HTML_NEW_LINE));
        return sb.toString();
    }

    /**
     * 添加设备IOT平台并添加设备台账
     *
     * @param model
     * @param operator
     * @return
     */
    private String addIotDeviceAccData(DeviceAccModel model, String operator) {
        if (StringUtils.isEmpty(model.getImei()) || model.getImei().length() != BaseConstant.LENGTH_IMEI) {
            return String.format("%s:IMEI长度错误", model.getImei());
        }
        model.setAddflag("1");
        String errMsg = checkDataLegitimacy(model);
        if (StringUtils.isNotEmpty(errMsg)) {
            return String.format("%s:%s", model.getImei(), errMsg);
        }
        if (StringUtils.isEmpty(model.getIotType())) {
            return String.format("%s:%s", model.getImei(), "平台类型不能为空");
        }
        String deviceId = "";
        try {
            if (model.getIotType().equals("1")) {
                OneNetApiResponseModel oneNetRes = oneNetApiHelper.createDevice(new OneNetDeviceApiModel(oneNetConfig.getIotProductId(), model.getDeviceName(), model.getImei(), model.getImei()));
                if (oneNetRes.getCode() != 0 || !oneNetRes.getMsg().equals(OneNetApiHelper.RESPONSE_MSG_SUCC)) {
                    return String.format("%s:%s", model.getImei(), oneNetRes.getMsg());
                } else {
                    deviceId = oneNetRes.getData().getString("did");
                }
            } else {
                AepDeviceApiModel aepDeviceApiModel = new AepDeviceApiModel(model.getDeviceName(), model.getDeviceSn(), model.getImei(), operator, Integer.valueOf(aepConfig.getProductId()));
                CreateDeviceResponse createDeviceResponse = aepApiHelper.createDevice(aepDeviceApiModel);
                if (createDeviceResponse.getStatusCode() == 200) {
                    String json = new String(createDeviceResponse.getBody(), "utf-8");
                    //AepResponseRootModel aepResModel = JSON.parseObject(json, AepResponseRootModel.class);
                    AepResponseRootModel<JSONObject> aepResModel = JSON.parseObject(json, new TypeReference<AepResponseRootModel<JSONObject>>() {
                    });

                    if (aepResModel.getCode() != 0) {
                        return String.format("%s:%s", model.getImei(), aepResModel.getResult().getString("reason"));
                    }
                    deviceId = aepResModel.getResult().getString("deviceId");
                }
            }

            model.setIotDeviceId(deviceId);
            saveDeviceAcc(model);
        } catch (Exception e) {
            return String.format("%s:发生异常%s", model.getImei(), e.getMessage());
        }

        return "";
    }

    private String deleteIotDeviceAccData(DeviceAccModel model) {
        if (StringUtils.isEmpty(model.getImei()) || model.getImei().length() != BaseConstant.LENGTH_IMEI) {
            return String.format("%s:IMEI长度错误", model.getImei());
        }
        if (StringUtils.isEmpty(model.getIotType())) {
            return String.format("%s:%s", model.getImei(), "平台类型不能为空");
        }
        try {
            if (model.getIotType().equals("1")) {
                OneNetApiResponseModel oneNetRes = oneNetApiHelper.deleteDevice(new OneNetDeviceApiModel(oneNetConfig.getIotProductId(), model.getDeviceName(), model.getImei(), model.getImei()));
                if (oneNetRes.getCode() != 0 || !oneNetRes.getMsg().equals(OneNetApiHelper.RESPONSE_MSG_SUCC)) {
                    return String.format("%s:%s", model.getImei(), oneNetRes.getMsg());
                }
            } else {
                DeleteDeviceByImeiResponse deleteDeviceResponse = aepApiHelper.deleteDevice(model.getImei());
                if (deleteDeviceResponse.getStatusCode() == 200) {
                    String json = new String(deleteDeviceResponse.getBody(), "utf-8");
                    AepResponseRootModel<JSONObject[]> aepResModel = JSON.parseObject(json, new TypeReference<>() {
                    });
                    if (aepResModel.getCode() != 0) {
                        return String.format("%s:%s", model.getImei(), aepResModel.getResult()[0].getString("reason"));
                    }
                }
            }
            deleteDeviceAccByImei(model.getImei());
        } catch (Exception e) {
            return String.format("%s:发生异常%s", model.getImei(), e.getMessage());
        }
        return "";
    }

    /**
     * 根据IMEI删除设备台账
     *
     * @param imei
     * @return
     */
    private int deleteDeviceAccByImei(String imei) {
        DeviceAccExample example = new DeviceAccExample();
        example.createCriteria().andImeiEqualTo(imei);
        return deviceAccMapper.deleteByExample(example);
    }

    /**
     * 根据设备编码管理表ID删除设备台账
     * @param deviceSnManagementId
     * @return
     */
    public int deleteByDeviceSnManagementId(int deviceSnManagementId){
        DeviceAccExample example = new DeviceAccExample();
        example.createCriteria().andDeviceSnManagementIdEqualTo(deviceSnManagementId);
        return deviceAccMapper.deleteByExample(example);
    }

    /**
     * 读取台账模板表格
     *
     * @param file excel文件
     * @return
     */
    private List<DeviceAccModel> readDeviceAccExcel(MultipartFile file) {
        List<DeviceAccModel> list = new ArrayList<>();
        try {
            XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
            XSSFSheet sheet = workbook.getSheetAt(0);

            Iterator<Row> rowIterator = sheet.iterator();

            int rowIndex = 0;
            while (rowIterator.hasNext()) {
                if (rowIndex == 0) {
                    rowIterator.next();
                    rowIndex++;
                    continue;
                }

                DeviceAccModel model = new DeviceAccModel();
                Row row = rowIterator.next();
                Cell cellImei = row.getCell(1);
                Cell cellDeviceSn = row.getCell(2);
                Cell cellDeviceType = row.getCell(3);
                Cell cellIotType = row.getCell(4);
                Cell cellDeviceName = row.getCell(5);
                if (cellImei == null) {
                    break;
                }

                model.setImei(PoiUtils.getCellValueAsString(cellImei));
                model.setDeviceSn(PoiUtils.getCellValueAsString(cellDeviceSn));
                String deviceType = PoiUtils.getCellValueAsString(cellDeviceType);
                model.setDeviceType(StringUtils.isEmpty(deviceType) ? DeviceType.WATER_METER.getCode() : deviceType);
                model.setIotType(PoiUtils.getCellValueAsString(cellIotType));
                String deviceName = PoiUtils.getCellValueAsString(cellDeviceName);
                model.setDeviceName(StringUtils.isEmpty(deviceName) ? model.getDeviceSn() : deviceName);
                if (StringUtils.isEmpty(model.getDeviceName())) {//设备名称允许为空,默认使用设备SN
                    model.setDeviceName(model.getDeviceSn());
                }
                list.add(model);
                rowIndex++;
            }
            workbook.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 根据设备SN串查询设备台账Map
     * @param deviceSns
     * @return
     */
    public Map<String, DeviceAccModel> findDeviceAccMapByDeviceSns(String deviceSns) {
        if (StringUtils.isEmpty(deviceSns)) return null;
        //返回MAP是为了使用时不需要遍例
        DeviceAccExample example = new DeviceAccExample();
        DeviceAccExample.Criteria criteria = example.createCriteria();

        List<String> codes = Arrays.asList(deviceSns.split(","));
        if (codes == null || codes.size() == 0) return null;
        criteria.andDeviceSnIn(codes);

        Map<String, DeviceAccModel> accModelMap = new HashMap<>();
        List<DeviceAcc> findlist = deviceAccMapper.selectByExample(example);
        for (DeviceAcc acc : findlist) {
            DeviceAccModel model = new DeviceAccModel();
            BeanUtils.copyProperties(acc, model);
            accModelMap.put(acc.getDeviceSn(), model);
        }

        return accModelMap;
    }
}