package com.yeejoin.amos.boot.module.common.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Joiner;
import com.yeejoin.amos.boot.biz.common.constants.BizConstant;
import com.yeejoin.amos.boot.biz.common.service.impl.DataDictionaryServiceImpl;
import com.yeejoin.amos.boot.biz.common.utils.EnumsUtils;
import com.yeejoin.amos.boot.biz.common.utils.Menu;
import com.yeejoin.amos.boot.module.common.api.dto.*;
import com.yeejoin.amos.boot.module.common.api.entity.*;
import com.yeejoin.amos.boot.module.common.api.enums.WaterResourceTypeEnum;
import com.yeejoin.amos.boot.module.common.api.feign.EquipFeignClient;
import com.yeejoin.amos.boot.module.common.api.mapper.WaterResourceMapper;
import com.yeejoin.amos.boot.module.common.api.service.IWaterResourceService;
import io.github.classgraph.utils.Join;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
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.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.annotation.Condition;
import org.typroject.tyboot.core.rdbms.annotation.Operator;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2021-06-29
 */
@Service
public class WaterResourceServiceImpl extends BaseService<WaterResourceDto, WaterResource, WaterResourceMapper> implements IWaterResourceService {

    @Autowired
    WaterResourceCraneServiceImpl waterResourceCraneService;
    @Autowired
    WaterResourceHydrantServiceImpl waterResourceHydrantService;
    @Autowired
    WaterResourceNaturalServiceImpl waterResourceNaturalService;
    @Autowired
    WaterResourcePoolServiceImpl waterResourcePoolService;
    @Autowired
    WaterResourceIotServiceImpl waterResourceIotService;
    @Resource
    WaterResourceMapper waterResourceMapper;
    @Autowired
    WaterResourceIndexServiceImpl waterResourceIndexServiceImpl;

    @Autowired
    DataDictionaryServiceImpl dataDictionaryService;
    @Autowired
    EquipFeignClient equipFeignClient;

    private static final String RESOURCE_ID ="resource_id";
    private static final String  CHILDREN ="children";
    private static final String  NAMEKEY ="nameKey";

    @Value("classpath:/json/equipmentWaterCode.json")
    private org.springframework.core.io.Resource equipmentWaterCode;

    /**
     * 分页查询
     */
    public Page<WaterResourceDto> queryForWaterResourcePage(Page<WaterResourceDto> page,
                                                            @Condition(Operator.like) String name,
                                                            @Condition(Operator.eq) String resourceType,
                                                            @Condition(Operator.in) ArrayList<Long> belongBuildingId,
                                                            @Condition(Operator.eq) Long belongFightingSystemId,
                                                            @Condition(Operator.eq) Long sequenceNbr,
                                                            String equipId,
                                                            String bizOrgCode,
                                                            String equipCateGoryCode,List<String> ids,  String companyId) {
        return this.waterResourceMapper.getWaterResourcePageByParams(page, name, resourceType, belongBuildingId,
                belongFightingSystemId, sequenceNbr, equipId, bizOrgCode, equipCateGoryCode,ids,companyId);
    }

    /**
     * 分页查询
     */
    public Page<WaterResourceDto> pageByDefect(Page<WaterResourceDto> page,
                                               String nameOrCode,
                                               String bizOrgCode,
                                               String systemName) {
        return this.waterResourceMapper.pageByDefect(page, nameOrCode, bizOrgCode, systemName);
    }

    /**
     * 列表查询 示例
     */
    public List<WaterResourceDto> queryForWaterResourceList(@Condition(Operator.eq) Boolean isDelete) {
        return this.queryForList("", false, isDelete);
    }

    /**
     * 列表条件查询
     */
    public List<WaterResourceDto> queryWaterResourceList(@Condition(Operator.eq) Boolean isDelete,
                                                         @Condition(Operator.like) String name,
                                                         @Condition(Operator.eq) Long sequenceNbr,
                                                         @Condition(Operator.eq) Long belongFightingSystemId,
                                                         @Condition(Operator.eq) Long belongBuildingId,
                                                         @Condition(Operator.like) String belongBuilding,
                                                         @Condition(Operator.eq) String resourceType) {
        return this.queryForList("", false, isDelete, name, sequenceNbr, belongFightingSystemId, belongBuildingId,
                belongBuilding, resourceType);
    }


    /**
     * excel导入
     *
     * @param model
     * @return
     */
    public WaterResourceDto importByExcel(WaterResourceDto model) {
        String resourceType = model.getResourceType();
        Optional<WaterResourceTypeEnum> resourceTypeEnum = EnumsUtils.getEnumObject(WaterResourceTypeEnum.class,
                e -> e.getCode().equals(resourceType));
        model.setResourceTypeName(resourceTypeEnum.isPresent()?resourceTypeEnum.get().getName():null);
        model.setRealityImg(JSON.toJSONString(model.getRealityImgList()));
        model.setOrientationImg(JSON.toJSONString(model.getOrientationImgList()));
        if (!StringUtils.isEmpty(resourceType)) {
            switch (resourceType) {
                case "hydrant":
                    // 新增基础信息
                    model.setIsIot(true);
                    createWithModel(model);
                    // 新增属性信息
                    WaterResourceHydrantDto waterResourceHydrantDto = new WaterResourceHydrantDto();
                    BeanUtils.copyProperties(model, waterResourceHydrantDto);
                    waterResourceHydrantDto.setSequenceNbr(null);
                    waterResourceHydrantDto.setResourceId(model.getSequenceNbr());
                    waterResourceHydrantService.createWithModel(waterResourceHydrantDto);
                    break;
                case "crane":
                    // 新增基础信息
                    model.setIsIot(true);
                    createWithModel(model);
                    WaterResourceCraneDto waterResourceCraneDto = new WaterResourceCraneDto();
                    BeanUtils.copyProperties(model, waterResourceCraneDto);
                    waterResourceCraneDto.setSequenceNbr(null);
                    waterResourceCraneDto.setResourceId(model.getSequenceNbr());
                    waterResourceCraneService.createWithModel(waterResourceCraneDto);
                    break;
                case "natural":
                    // 新增基础信息
                    model.setIsIot(true);
                    createWithModel(model);
                    WaterResourceNaturalDto waterResourceNaturalDto = new WaterResourceNaturalDto();
                    BeanUtils.copyProperties(model, waterResourceNaturalDto);
                    waterResourceNaturalDto.setSequenceNbr(null);
                    waterResourceNaturalDto.setResourceId(model.getSequenceNbr());
                    waterResourceNaturalService.createWithModel(waterResourceNaturalDto);
                    break;
                case "industryPool":
                case "waterTank":
                case "pool":
                    // 新增基础信息
                    model.setIsIot(true);
                    createWithModel(model);
                    WaterResourcePoolDto waterResourcePoolDto = new WaterResourcePoolDto();
                    BeanUtils.copyProperties(model, waterResourcePoolDto);
                    waterResourcePoolDto.setSequenceNbr(null);
                    waterResourcePoolDto.setResourceId(model.getSequenceNbr());
                    waterResourcePoolService.createWithModel(waterResourcePoolDto);
                    break;
            }


        } else {
            createWithModel(model);
        }
        return model;
    }

    /**
     * 导出列表
     */
    public List<WaterResourceForExportDto> exportToExcel(Boolean isDelete, String name,
                                                         String resourceType, String bizOrgCode ) {
    	if ("null".equals(name)) {
    		name = null;
		}
    	if ("null".equals(resourceType)) {
    		resourceType = null;
		}
    	if ("null".equals(bizOrgCode)) {
    		bizOrgCode = null;
		}
        return waterResourceMapper.exportToExcel(isDelete, name, resourceType,bizOrgCode);
    }

    @Override
    public List<WaterResourceZhDto> getWaterResourceList(Integer pageNum, Integer pageSize, RequestData requestData) {
        if (null == pageNum || null == pageSize) {
            pageNum = 1;
            pageSize = Integer.MAX_VALUE;
        } else {
            pageNum = (pageNum - 1) * pageSize;
        }
        return waterResourceMapper.getWaterResourceList(pageNum, pageSize, requestData);
    }

    @Override
    public Integer getWaterResourceListCount(RequestData requestData) {
        return waterResourceMapper.getWaterResourceListCount(requestData);
    }

    @Override
    public WaterResourceDto selectBySequenceNbr(Long sequenceNbr) {
        // 查询基本信息
        WaterResourceDto waterResourceDto = this.queryBySeq(sequenceNbr);
        waterResourceDto.setRealityImgList(JSON.parseArray(waterResourceDto.getRealityImg(), Object.class));
        waterResourceDto.setOrientationImgList(JSON.parseArray(waterResourceDto.getOrientationImg()));

        if (ValidationUtil.isEmpty(waterResourceDto.getContactUser())) {
            waterResourceDto.setContactUser("");
        }

        if (ValidationUtil.isEmpty(waterResourceDto.getContactPhone())) {
            waterResourceDto.setContactPhone("");
        }

        if (ValidationUtil.isEmpty(waterResourceDto.getManagementUnit())) {
            waterResourceDto.setManagementUnit("");
        }

        if (ValidationUtil.isEmpty(waterResourceDto.getSection())) {
            waterResourceDto.setSection("");
        }


        if (ValidationUtil.isEmpty(waterResourceDto.getWaterSupplyName())) {
            waterResourceDto.setWaterSupplyName("");
        }

        Boolean isDelete = waterResourceDto.getIsDelete();
        // 查询属性信息
        String resourceType = waterResourceDto.getResourceType();
        if (!StringUtils.isEmpty(resourceType)) {
            switch (resourceType) {
                case "hydrant":
                    WaterResourceHydrant waterResourceHydrant =
                            waterResourceHydrantService.getOne(new QueryWrapper<WaterResourceHydrant>().eq(
                                    RESOURCE_ID,
                                    sequenceNbr));
                    if (null != waterResourceHydrant) {
                        BeanUtils.copyProperties(waterResourceHydrant, waterResourceDto);
                    }
                    break;
                case "crane":
                    WaterResourceCrane waterResourceCrane =
                            waterResourceCraneService.getOne(new QueryWrapper<WaterResourceCrane>().eq(RESOURCE_ID,
                                    sequenceNbr));
                    if (null != waterResourceCrane) {
                        BeanUtils.copyProperties(waterResourceCrane, waterResourceDto);
                    }
                    break;
                case "natural":
                    WaterResourceNatural waterResourceNatural =
                            waterResourceNaturalService.getOne(new QueryWrapper<WaterResourceNatural>().eq(
                                    RESOURCE_ID,
                                    sequenceNbr));
                    if (null != waterResourceNatural) {
                        BeanUtils.copyProperties(waterResourceNatural, waterResourceDto);
                    }

                    break;
                case "pool":
                    WaterResourcePool waterResourcePool =
                            waterResourcePoolService.getOne(new QueryWrapper<WaterResourcePool>().eq(RESOURCE_ID,
                                    sequenceNbr));
                    if (null != waterResourcePool) {
                        BeanUtils.copyProperties(waterResourcePool, waterResourceDto);
                    }
                    break;
            }
        }
        waterResourceDto.setSequenceNbr(sequenceNbr);
        waterResourceDto.setIsDelete(isDelete);
        // 查询物联参数
        LambdaQueryWrapper<WaterResourceIndex> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WaterResourceIndex::getWaterId, waterResourceDto.getSequenceNbr());
        List<WaterResourceIndex> list = waterResourceIndexServiceImpl.list(queryWrapper);
        if (list.size() > 0) {
            Map<String, Object> map = new HashMap<>();
            list.stream().forEach(e -> {
                map.put(e.getNameKey(), e.getPerfValue());
            });
            waterResourceDto.setWaterResourceIotDto(map);
        }
        return waterResourceDto;
    }

    @Override
    public Map<String, Object> getResourcesCount() {
        return  waterResourceMapper.getResourcesCount();
    }

    public List<WaterResourceTypeDto> getWaterResourceTypeList(Boolean isDelete) {
        return waterResourceMapper.getWaterResourceTypeList(isDelete);
    }

    public static JSONObject getLongLatFromAddress(String address) {
        JSONObject result = new JSONObject();
        result.put(BizConstant.ADDRESS, "");
        result.put(BizConstant.LONGITUDE, "0");
        result.put(BizConstant.LATITUDE, "0");
        if (StringUtils.isNotEmpty(address)) {
            String[] addressData = address.split("@address@");
            if (addressData.length > 1) {
                result.put(BizConstant.ADDRESS, addressData[0]);
                JSONObject langLatObj = JSON.parseObject(addressData[1]);
                if (StringUtils.isNotEmpty(langLatObj.getString(BizConstant.LONGITUDE))) {
                    result.put(BizConstant.LONGITUDE, langLatObj.getString(BizConstant.LONGITUDE));
                } else {
                    result.put(BizConstant.LONGITUDE, "0");
                }
                if (StringUtils.isNotEmpty(langLatObj.getString(BizConstant.LATITUDE))) {
                    result.put(BizConstant.LATITUDE, langLatObj.getString(BizConstant.LATITUDE));
                } else {
                    result.put(BizConstant.LATITUDE, "0");
                }
            } else {
                result.put(BizConstant.ADDRESS, addressData[0]);
            }
        }
        return result;
    }

    public List<Menu> getwaterResourceTypeTree(String bizOrgCode) throws Exception {
        List<Menu> da=null;
        List<Menu> list = new ArrayList<>();
        ResponseModel<Object> response = equipFeignClient.list();
        if (response.getStatus() != 200) {
            return da;
        }
        Object resultObject = response.getResult();
        JSONArray childrenArray = null;
        JSONArray waterTypeDetailArray = null;
        JSONObject waterTypeDetailJson = null;
        JSONArray resultArray = JSON.parseArray(JSON.toJSONString(resultObject));
        for (Object obj : resultArray) {
            JSONObject detailJsonObject = JSON.parseObject(JSON.toJSONString(obj));
            String codeString = detailJsonObject.getString("code");
            if (codeString.equals("90000000")) {
                childrenArray = detailJsonObject.getJSONArray(CHILDREN);
                break;
            }
        }
        if (childrenArray != null && childrenArray.size() > 0) {
            for (Object childObject : childrenArray) {
                JSONObject detailChildJsonObject = JSON.parseObject(JSON.toJSONString(childObject));
                String codeStr = detailChildJsonObject.getString("code");
                if (codeStr.equals("93000000")) {
                    waterTypeDetailArray = detailChildJsonObject.getJSONArray(CHILDREN);
                    break;
                }
            }

        }
        if (waterTypeDetailArray != null && waterTypeDetailArray.size() > 0) {
            for (Object childObject : waterTypeDetailArray) {
                JSONObject waterTypeDetail = JSON.parseObject(JSON.toJSONString(childObject));
                String codeStr = waterTypeDetail.getString("code");
                if (codeStr.equals("93060000")) {
                    waterTypeDetailJson = waterTypeDetail;
                    break;
                }
            }
        }
        if (waterTypeDetailJson != null) {
            List<Map<String, Object>> mapList = waterResourceMapper.getWaterTypeByBizOrgCode(bizOrgCode);
            Map<String, Object> map = new HashMap<>();
            for (Map<String, Object> m : mapList) {
                String key = "";
                String value = "";
                for(Map.Entry<String,Object> entry : m.entrySet()) {
                    if(entry.getKey().equals("num")) {
                        value = entry.getValue().toString();
                    }
                    if(entry.getKey().equals("type")) {
                        key = entry.getValue().toString();
                    }
                }
                map.put(key,value);
            }
            int num = 0;
            JSONArray waterTypeDetailChildrenArray = waterTypeDetailJson.getJSONArray(CHILDREN);
            for (Object childObject : waterTypeDetailChildrenArray) {

                JSONObject detail = JSON.parseObject(JSON.toJSONString(childObject));
                String codeStr = detail.getString("code");
                if(map!=null && map.containsKey(codeStr)) {
                    num=num+Integer.parseInt( map.get(codeStr).toString());
                    detail.put("num", Integer.parseInt( map.get(codeStr).toString()));
                }else {
                    detail.put("num", 0);
                }
                if (ObjectUtils.isNotEmpty( detail.getJSONArray(CHILDREN))){
                    JSONArray children = detail.getJSONArray(CHILDREN);
                    for (Object child : children) {
                        JSONObject childDetail = JSON.parseObject(JSON.toJSONString(child));
                        String codeStrChild = childDetail.getString("code");
                        if(map!=null && map.containsKey(codeStrChild)) {
                            int parentNum = Integer.parseInt(detail.get("num").toString());
                            int sum = parentNum+Integer.parseInt( map.get(codeStrChild).toString());
                            detail.put("num", sum);
                        }
                    }
                }

                Menu menu = new Menu(Long.valueOf(detail.get("code").toString()), detail.get("name").toString(), null, Integer.parseInt(detail.containsKey("num") ? detail.get("num").toString() : "0" ));
                list.add(menu);


        }

        }
        return list;
    }

    public Object getwaterResourceType() throws Exception {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        ResponseModel<Object> response = equipFeignClient.list();
        if (response.getStatus() != 200) {
            return null;
        }
        Object resultObject = response.getResult();
        JSONArray childrenArray = null;
        JSONArray waterTypeDetailArray = null;
        JSONObject waterTypeDetailJson = null;
        JSONArray resultArray = JSON.parseArray(JSON.toJSONString(resultObject));
        for (Object obj : resultArray) {
            JSONObject detailJsonObject = JSON.parseObject(JSON.toJSONString(obj));
            String codeString = detailJsonObject.getString("code");
            if (codeString.equals("90000000")) {
                childrenArray = detailJsonObject.getJSONArray(CHILDREN);
                break;
            }
        }
        if (childrenArray != null && childrenArray.size() > 0) {
            for (Object childObject : childrenArray) {
                JSONObject detailChildJsonObject = JSON.parseObject(JSON.toJSONString(childObject));
                String codeStr = detailChildJsonObject.getString("code");
                if (codeStr.equals("93000000")) {
                    waterTypeDetailArray = detailChildJsonObject.getJSONArray(CHILDREN);
                    break;
                }
            }

        }
        if (waterTypeDetailArray != null && waterTypeDetailArray.size() > 0) {
            for (Object childObject : waterTypeDetailArray) {
                JSONObject waterTypeDetail = JSON.parseObject(JSON.toJSONString(childObject));
                String codeStr = waterTypeDetail.getString("code");
                if (codeStr.equals("93060000")) {
                    waterTypeDetailJson = waterTypeDetail;
                    break;
                }
            }
        }
        if (waterTypeDetailJson != null) {
            JSONArray waterTypeDetailChildrenArray = waterTypeDetailJson.getJSONArray(CHILDREN);

            for (Object childObject : waterTypeDetailChildrenArray) {
                Map<String, Object> map = new LinkedHashMap<>();
                JSONObject detail = JSON.parseObject(JSON.toJSONString(childObject));
                String codeStr = detail.getString("code");
                String name = detail.getString("name");
                map.put("code", codeStr);
                map.put("name", name);
                list.add(map);
            }
        }
        return list;
    }

    public List<Map<String, Object>> getWaterResourceInfoList(String bizOrgCode) {
        String json = null;
        try {
            json = IOUtils.toString(equipmentWaterCode.getInputStream(), java.lang.String.valueOf(StandardCharsets.UTF_8));
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<Map> mapList = JSON.parseArray(json, Map.class);
        Map<String, Object> map = new HashMap<>();
        mapList.forEach(x -> map.put(String.valueOf(x.get(NAMEKEY)), x.get("type")));
        map.put("bizOrgCode", bizOrgCode);
        Map<String, Object> result = waterResourceMapper.getWaterResourceInfoList(map);
        List<Map<String, Object>> list = new ArrayList<>();
        mapList.forEach(y -> {
            Map<String, Object> tempMap = new HashMap<>();
            tempMap.put("name", y.get("name"));
            tempMap.put("code", y.get(NAMEKEY));
            tempMap.put("total", result.get(y.get(NAMEKEY)));
            list.add(tempMap);
        });
        return  list;
    }

    public Page<Map<String, Object>> getWaterInfoEquipListPage(Page<Map<String, Object>> page, String bizOrgCode, String id) {
        WaterResource resource = this.waterResourceMapper.selectById(id);
        String type = resource.getResourceType();
        if ("pool".equalsIgnoreCase(type)) {
            List<String> equipIds = this.waterResourceMapper.getPoolEquipIds(bizOrgCode);
            String ids = Joiner.on(",").join(equipIds);
            ResponseModel<List<Map<String, Object>>> response = equipFeignClient.getListByEquipmentSpesById(ids, "1");
            if (response.getStatus() != 200) {
                return new Page<>();
            }
            page.setRecords((response.getResult()));
        } else {
            List<String> equipmentIds = this.waterResourceMapper.getOtherResourceEquipIds(bizOrgCode, type);
            String equipIdStr = Joiner.on(",").join(equipmentIds);
            ResponseModel<List<Map<String, Object>>> response = equipFeignClient.getListByEquipmentSpesById(equipIdStr, "0");
            if (response.getStatus() != 200) {
                return new Page<>();
            }
            page.setRecords(response.getResult());
        }
        return page;
    }

}
