package com.hotent.uc.manager.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hotent.uc.dao.DIngApiDao;
import com.hotent.uc.dao.ZabbixAlertLogDao;
import com.hotent.uc.manager.*;
import com.alibaba.fastjson.JSON;
import com.hotent.uc.model.*;
import com.hotent.uc.util.Request;
import com.hotent.uc.util.RequestBuilder;
import lombok.NoArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.hotent.uc.util.ZabbixAPiConstant.*;
@Repository
@NoArgsConstructor
public class DefaultZabbixApiImpl implements ZabbixApi {
    private static final Logger logger = LoggerFactory.getLogger(DefaultZabbixApiImpl.class);
    private CloseableHttpClient httpClient;
    private URI uri;
    private volatile String auth;
    @Autowired
    private  DIngApiDao dIngApiDao;
    @Autowired
    private ZabbixAlertLogManager zabbixAlertLogManager;
    @Autowired
    private ZabbixAlertLogDao zabbixAlertLogDao;
    @Autowired
    private DingApiManager dingApiManager;
    @Autowired
    private ShortMsgLogManager shortMsgLogManager;
    @Autowired
    private UserManager userManager;
    public DefaultZabbixApiImpl(String url) {
        try {
            uri = new URI(url.trim());
        } catch (URISyntaxException e) {
            throw new RuntimeException("url invalid", e);
        }
    }

    @Override
    public void init() {
        if (httpClient == null) {
            httpClient = HttpClients.custom().build();
        }
    }

    @Override
    public void destroy() {
        if (httpClient != null) {
            try {
                httpClient.close();
            } catch (Exception e) {
                logger.error("close httpclient error!", e);
            }
        }
    }

    @Override
    public String apiVersion() {
        Request request = RequestBuilder.newBuilder().method(ZABBIX_VERSION_GET_URL).build();
        JSONObject response = call(request, false);
        return (String) response.get(ZABBIX_RESPONSE_RESULT);
    }

    @Override
    public JSONObject call(Request request, boolean auth) {
        if (request.getAuth() == null && auth) {
            request.setAuth(this.auth);
        }
        if(!auth){
            request.setAuth(null);
        }
        try {
            String result=JSON.toJSONString(request);
            if(request.getParamsList()!=null&&request.getParamsList().size()>0){
                JSONObject jsonObject= JSONObject.parseObject(JSON.toJSONString(request));
                jsonObject.put("params",request.getParamsList());
                result=jsonObject.toJSONString();
            }

            HttpUriRequest httpRequest = org.apache.http.client.methods.RequestBuilder.post().setUri(uri)
                    .addHeader("Content-Type", "application/json")
                    .setEntity(new StringEntity(result, ContentType.APPLICATION_JSON)).build();
            CloseableHttpResponse response = httpClient.execute(httpRequest);
            HttpEntity entity = response.getEntity();
            byte[] data = EntityUtils.toByteArray(entity);
            String str = new String(data);
            if(StringUtils.isBlank(str) || StringUtils.isEmpty(str)){
                return new JSONObject();
            }
            return (JSONObject) JSON.parse(str);
        } catch (IOException e) {
            throw new RuntimeException("DefaultZabbixApi call exception!", e);
        }
    }

    @Override
    public boolean login(String user, String password) {
        this.auth = null;
        Request request = RequestBuilder.newBuilder()
                .paramEntry(ZABBIX_AUTH_USERNAME, user)
                .paramEntry(ZABBIX_AUTH_PASSWORD, password)
                .method(USER_LOGIN_URL)
                .id(1)
                .auth(null)
                .jsonrpc("2.0").build();
        JSONObject response = call(request, false);
        String auth = (String) response.get(ZABBIX_RESPONSE_RESULT);
        if (auth != null && !auth.isEmpty()) {
            this.auth = auth;
            return true;
        }
        return false;
    }

    @Override
    public List<Host> hostList() {
        Request request = RequestBuilder.newBuilder()
                .method(HOST_GET_URL)
                .build();
        JSONObject response = call(request, true);
        return getHosts(response);
    }

    @Override
    public List<Host> hostListByIp(List<String> ips) {
        JSONObject filter = new JSONObject();
        filter.put(ZABBIX_QUERY_IP, ips);
        Request request = RequestBuilder.newBuilder()
                .method(HOST_GET_URL)
                .paramEntry(ZABBIX_QUERY_FILTER, filter)
                .build();
        JSONObject response = call(request, true);
        return getHosts(response);
    }

    @Override
    public List<Host> hostListByName(String name) {
        JSONObject filter = new JSONObject();
        filter.put(ZABBIX_QUERY_NAME, Arrays.asList(name));
        Request request = RequestBuilder.newBuilder()
                .method(HOST_GET_URL)
                .paramEntry(ZABBIX_QUERY_FILTER, filter)
                .build();
        JSONObject response = call(request, true);
        return getHosts(response);
    }

    @Override
    public List<Item> hostMonitorItems(String hoistId) {
        Request request = RequestBuilder.newBuilder()
                .method(HOST_MONITOR_ITEMS_GET_URL)
                .paramEntry(ZABBIX_QUERY_OUTPUT, ZABBIX_QUERY_EXTEND)
                .paramEntry(ZABBIX_QUERY_HOSTIDS, hoistId)
                .build();
        JSONObject response = call(request, true);
        JSONArray jsonArray = response.getJSONArray(ZABBIX_RESPONSE_RESULT);
        List<Item> items = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Set<String> keySet = jsonObject.keySet();
            JSONObject jsonObjectNew = new JSONObject();
            for (String s : keySet) {
                String f = com.baomidou.mybatisplus.core.toolkit.StringUtils.underlineToCamel(s);
                jsonObjectNew.put(f, jsonObject.get(s));
            }
            Item item = jsonObjectNew.toJavaObject(Item.class);
            items.add(item);
        }
        return items;
    }

    @Override
    public ItemValue hostMonitorItemLastValue(String itemId, Integer history) {
        int limit = 1;
        Request request = RequestBuilder.newBuilder()
                .method(HOST_MONITOR_ITEM_VALUE_GET_URL)
                .paramEntry(ZABBIX_QUERY_OUTPUT, ZABBIX_QUERY_EXTEND)
                .paramEntry(ZABBIX_QUERY_ITEMIDS, itemId)
                .paramEntry(ZABBIX_QUERY_SORTORDER, ZABBIX_QUERY_DESC)
                .paramEntry(ZABBIX_QUERY_HISTORY, String.valueOf(history.intValue()))
                .paramEntry(ZABBIX_QUERY_SORTFIELD, ZABBIX_QUERY_CLOCK)
                .paramEntry(ZABBIX_QUERY_LIMIT, limit)
                .build();
        /** md history==1==limit时会报这个错误，解决方案： 将history置为String类型
         * {
         *     "auth": "30d4a1696e51e43c2e587da46169c638",
         *     "id": 335,
         *     "jsonrpc": "2.0",
         *     "method": "history.get",
         *     "params": {
         *         "history": {
         *             "$ref": "limit"
         *         },
         *         "itemids": "802549",
         *         "limit": 1,
         *         "output": "extend",
         *         "sortfield": "clock",
         *         "sortorder": "DESC"
         *     }
         * }
         */
        JSONObject response = call(request, true);
        try{
            JSONArray jsonArray = response.getJSONArray(ZABBIX_RESPONSE_RESULT);

            if(CollectionUtil.isNotEmpty(jsonArray)){
                JSONObject jsonObject = jsonArray.getJSONObject(0);
                Set<String> keySet = jsonObject.keySet();
                JSONObject jsonObjectNew = new JSONObject();
                for (String s : keySet) {
                    String f =  com.baomidou.mybatisplus.core.toolkit.StringUtils.underlineToCamel(s);
                    jsonObjectNew.put(f,jsonObject.get(s));
                }
                ItemValue itemValue = jsonObjectNew.toJavaObject(ItemValue.class);
                return itemValue;
            }
        }catch (Exception e){
            logger.error(e.getMessage(),e);
        }
        return new ItemValue();
    }

    @Override
    public JSONArray getAlarmDataObtaining(String  hostId) {
        Request request = RequestBuilder.newBuilder()
                .method(ALARM_RUL)
                .jsonrpc("2.0")
                .paramEntry(ZABBIX_QUERY_OUTPUT, "extend")
                .paramEntry(ZABBIX_QUERY_HOSTIDS, hostId)
                .id(1)
                .build();
        JSONObject response = call(request, true);
        return response.getJSONArray(ZABBIX_RESPONSE_RESULT);
    }

    @Override
    public JSONArray getProblemList(String hostid) {
        Request request = RequestBuilder.newBuilder()
                .method("problem.get")
                .jsonrpc("2.0")
                .paramEntry(ZABBIX_QUERY_OUTPUT, "extend")
                .paramEntry(ZABBIX_QUERY_HOSTIDS, hostid)
                .id(1)
                .build();
        JSONObject response = call(request, true);
        return response.getJSONArray(ZABBIX_RESPONSE_RESULT);
    }

    @Override
    public JSONArray getActionList(Integer actionsId, String timeFrom) {
        JSONObject filter = new JSONObject();
        filter.put(ZABBIX_EVENTSOURCE, "0");

        Request request = RequestBuilder.newBuilder()
                .method(ACTION_URL)
                .jsonrpc("2.0")
                .paramEntry(ZABBIX_QUERY_OUTPUT, "extend")
                .paramEntry(ZABBIX_SELECTOPERATIONS, "extend")
                .paramEntry(ZABBIX_SELECTRECOVERYOPERATIONS, "extend")
                .paramEntry(ZABBIX_SELECTFILTER, "extend")
                .paramEntry(ZABBIX_SELECTACKNOWLEDGEOPERATIONS, "extend")
                .paramEntry(ZABBIX_QUERY_FILTER, filter)
                .id(1)
                .build();
        JSONObject response = call(request, true);
        return response.getJSONArray(ZABBIX_RESPONSE_RESULT);
    }

    @Override
    public cn.hutool.json.JSONArray getEventAlarm(String timeFrom, String timeTill) {
        List<HostGroupDTO> hostGroupDTOList = JSONUtil.toList(getHostGroup(), HostGroupDTO.class);
        List<String> groupList = hostGroupDTOList.stream().filter(x -> x.getName().contains("-政务云")).map(x -> x.getGroupid()).collect(Collectors.toList());
        Request request = RequestBuilder.newBuilder()
                .method(EVENT_URL)
                .jsonrpc("2.0")
                .paramEntry(ZABBIX_QUERY_OUTPUT, "extend")
                .paramEntry(ZABBIX_QUERY_SORTFIELD, "clock")
                .paramEntry(ZABBIX_QUERY_SORTORDER, "DESC")
                .paramEntry(ZABBIX_ALARM_TIME_FROM, timeFrom)
                .paramEntry(ZABBIX_ALARM_TIME_Till, timeTill)
                .paramEntry(ZABBIX_ALARM_GROUPID, (groupList.size() > 0 ? groupList.stream().toArray(String[]::new) : null))
                .paramEntry(ZABBIX_ALARM_SELECT_HOSTS, new String[]{"host"})
                .id(1)
                .build();
        JSONObject response = call(request, true);
        return JSONUtil.parseArray(response.getString(ZABBIX_RESPONSE_RESULT));
    }

    @Override
    public boolean checkAuthExpired() {
        if (StringUtils.isEmpty(this.auth)) {
            return true;
        }
        Request request = RequestBuilder.newBuilder()
                .paramEntry("sessionid", this.auth)
                .method(AUTH_CHECK_URL)
                .id((int) (Math.random() * 1000))
                .auth(this.auth)
                .jsonrpc("2.0").build();
        JSONObject result = call(request, false);
        if (null != result.get("result")) {
            return false;
        }
        return true;
    }

    @Override
    public List<ItemValue> getHostSpecItemsLastValueCollection(String hostId, Set<String> itemIds, String valueType) {
        return null;
    }

    @Override
    public String createZabbixWeb(String webName,String hostName,String hostId,String hostIp,cn.hutool.json.JSONArray sub_qzsub_jkxz) {
        List<Map<String,Object>> paramList=new ArrayList<>();
        for(int i=0;i<sub_qzsub_jkxz.size();i++){
            String ztm= (String) sub_qzsub_jkxz.getJSONObject(i).get("ztm");//状态码
            String jkmc= (String) sub_qzsub_jkxz.getJSONObject(i).get("jkmc");//名称
            String jkdz= (String) sub_qzsub_jkxz.getJSONObject(i).get("jkdz");//地址
            String jklx= (String) sub_qzsub_jkxz.getJSONObject(i).get("jklx");//类型 wy=网页 接口=jk
            Map<String,Object> map=new HashMap<>();
            map.put(ZABBIX_QUERY_NAME,jkmc);
            map.put(ZABBIX_URL,jkdz);
            map.put(ZABBIX_STATUS_CODE,ztm);
            map.put(ZABBIX_NO,i+1);
            paramList.add(map);
        }
        Request request = RequestBuilder.newBuilder()
                .method(HTTP_TEST_CREATE_URL)
                .jsonrpc("2.0")
                .paramEntry(ZABBIX_QUERY_NAME, webName)
                .paramEntry(ZABBIX_QUERY_HOSTID, hostId)
                .paramEntry(ZABBIX_STEPS, paramList)
                .id(1)
                .build();
        JSONObject response = call(request, true);
        System.out.println("============================="+response.toJSONString());
        JSONObject result= response.getJSONObject(ZABBIX_RESPONSE_RESULT);
        // {"httptestids":["6"]}
        JSONArray array=JSONArray.parseArray(result.getString("httptestids"));
        String id= (String) array.get(0);
        createZabbixTrigger(sub_qzsub_jkxz,webName,hostId,hostIp,"3");
        return id;

    }

    @Override
    public String createZabbixTrigger(cn.hutool.json.JSONArray sub_qzsub_jkxz,String hostName,String hostId,String hostIp,String proortiy) {
        List<Map<String,Object>> list=new ArrayList<>();
        List<String> triggerList=new ArrayList<>();
        for(int i=0;i<sub_qzsub_jkxz.size();i++){
            String jkmc= (String) sub_qzsub_jkxz.getJSONObject(i).get("jkmc");//名称
            String jklx= (String) sub_qzsub_jkxz.getJSONObject(i).get("jklx");//类型 wy=网页 接口=jk
            Map<String,Object> map=new HashMap<>();
            map.put("description",hostName+"-"+jkmc);
            triggerList.add(hostName+"-"+jkmc);
            String filter="";
            if(jklx.equals("wy")){
                filter="{"+hostIp+":web.test.fail["+hostName+"].last()}<>200";
            }else{
                filter="{"+hostIp+":web.test.rspcode["+hostName+","+jkmc+"].last()}<>200";
            }
            map.put("expression",filter);
            map.put("priority",proortiy);
            list.add(map);
        }

        Request request = RequestBuilder.newBuilder()
                .method(TRIGGER_CREATE_URL)
                .jsonrpc("2.0")
                .paramEntryList(list)
                .id(1)
                .build();
        JSONObject response = call(request, true);
        JSONObject result= response.getJSONObject(ZABBIX_RESPONSE_RESULT);

        createActionFun(triggerList,hostName);
        return null;
    }

    @Override
    public JSONArray getTriggerList(String hostid) {

        Request request = RequestBuilder.newBuilder()
                .method("trigger.get")
                .jsonrpc("2.0")
                .id(1)
                .build();
        JSONObject response = call(request, true);
        return response.getJSONArray(ZABBIX_RESPONSE_RESULT);
    }

    @Override
    public String createActionFun(List<String> triggerName,String actionName) {
        //动作过滤条件
        List<Map<String,Object>> conditionsList=new ArrayList<>();
        for(int i=0;i<triggerName.size();i++){
            Map<String,Object> conditionsMap=new HashMap<>();
            conditionsMap.put("conditiontype","3");//按照触发器名称
            conditionsMap.put("operator",2);//0=等于
            conditionsMap.put("value",triggerName.get(i));//触发器名称
            conditionsList.add(conditionsMap);
        }



        Map<String,Object> mapFilter=new HashMap<>();
        mapFilter.put("evaltype",0);
        mapFilter.put("conditions",conditionsList);
        //操作内容
        List<Map<String,Object>> operationsList=new ArrayList<>();
        Map<String,Object> opmessageMap=new HashMap<>();
        opmessageMap.put("message","告警主机:{HOSTNAME1}\n" +
                "告警日期:{EVENT.DATE}\n" +
                "告警时间:{EVENT.TIME}\n" +
                "告警等级:{TRIGGER.SEVERITY}\n" +
                "告警信息:{TRIGGER.NAME}\n" +
                "告警项目:{TRIGGER.KEY1}\n" +
                "当前状态:{TRIGGER.STATUS}\n" +
                "返 回 码:{ITEM.VALUE1}\n" +
                "事件ID:{EVENT.ID}");//内容
        opmessageMap.put("subject","{TRIGGER.NAME}");//标题
        opmessageMap.put("default_msg","0");

        Map<String,Object> userMap=new HashMap<>();
        userMap.put("userid","1");

        Map<String,Object> operationsMap=new HashMap<>();
        operationsMap.put("operationtype","0");//发送消息
        operationsMap.put("esc_period","0s");//时间
        operationsMap.put("evaltype","0");//and/or
        operationsMap.put("opmessage",opmessageMap);//and/or
        operationsMap.put("opmessage_usr",userMap);//and/or
        operationsList.add(operationsMap);

        Request request = RequestBuilder.newBuilder()
                .method("action.create")
                .jsonrpc("2.0")
                .paramEntry("name",actionName)
                .paramEntry("eventsource",0)
                .paramEntry("status",0)
                .paramEntry("esc_period","1m")
                .paramEntry("filter",mapFilter)
                .paramEntry("operations",operationsList)
                .id(1)
                .build();
        JSONObject response = call(request, true);
        return response.getString(ZABBIX_RESPONSE_RESULT);
    }

    @Override
    public String productZabbixAlertData() {
//        dIngApiDao=ApplicationContextAwareGetBean.getBean(DIngApiDao.class);
        List<Map<String,Object>> webList=dIngApiDao.getZabbixIndexData(null);//获取所有的监控
//
//        zabbixAlertLogManager=ApplicationContextAwareGetBean.getBean(ZabbixAlertLogManager.class);
        webList.forEach(item->{
            String hostId= (String) item.get("F_hostId");
            String webName= (String) item.get("F_webName");
            String alertType= (String) item.get("F_gjtxfs");
            String alertPeopleId= (String) item.get("F_gjtxrid");
            String id= (String) item.get("ID_");


            JSONArray alertArray=getAlarmDataObtaining(hostId);
            for(int i=0;i<alertArray.size();i++){
                String subject=alertArray.getJSONObject(i).getString("subject");
                String message=alertArray.getJSONObject(i).getString("message");
                String alertid=alertArray.getJSONObject(i).getString("alertid");
                if(subject.contains(webName)){
                     if(queryZabbixAlertData(alertid)){//如果存在记录的告警直接跳过
                         continue;
                     }
                    ZabbixAlertLog zabbixAlertLog=new ZabbixAlertLog();
                    zabbixAlertLog.setAlertId(alertid);
                    zabbixAlertLog.setSubject(subject);
                    zabbixAlertLog.setMessage(message);
                    zabbixAlertLog.setAlertType(alertType);
                    zabbixAlertLog.setAlertUserId(alertPeopleId);
                    zabbixAlertLog.setBusinessId(id);
                    zabbixAlertLog.setCreateTime(LocalDateTime.now());
                    zabbixAlertLog.setHostId(hostId);
                    zabbixAlertLogManager.save(zabbixAlertLog);
                }
            }
        });

        List<ZabbixAlertLog> alertList=zabbixAlertLogManager.getAll();
//        dingApiManager=ApplicationContextAwareGetBean.getBean(DingApiManager.class);
//        userManager=ApplicationContextAwareGetBean.getBean(UserManager.class);
//        shortMsgLogManager=ApplicationContextAwareGetBean.getBean(ShortMsgLogManager.class);
        alertList.forEach(item->{
            String isFlag=item.getIsFlag();//是否发送
            String userId=item.getAlertUserId();//是否发送
            String message=item.getMessage();//是否发送
            String alertType=item.getAlertType();//是否发送
            if(StringUtils.isEmpty(isFlag)&&StringUtils.isNotEmpty(userId)){
                if(StringUtils.isNotEmpty(alertType)&&alertType.contains("2")){//钉钉
                    dingApiManager.sendDingMessageByZabbix(userId,message);
                }
                if(StringUtils.isNotEmpty(alertType)&&alertType.contains("1")&&StringUtils.isNotEmpty(userId)){//短信
                     User user=userManager.get(userId);
                     if(user.getMobile()!=null){
                         shortMsgLogManager.sendMsg(user.getMobile(),"",message);
                     }

                }
                item.setIsFlag("0");
                zabbixAlertLogManager.update(item);
            }
        });
        return null;
    }

    private boolean  queryZabbixAlertData(String alertId){
//        zabbixAlertLogDao=ApplicationContextAwareGetBean.getBean(ZabbixAlertLogDao.class);
//        LambdaQueryWrapper<ZabbixAlertLog> zabbixAlertQw=new LambdaQueryWrapper<>();
//        zabbixAlertQw.eq(ZabbixAlertLog::getAlertId,alertId);
//        List<ZabbixAlertLog> zabbixAlertLogsList=zabbixAlertLogDao.selectList(zabbixAlertQw);
//        if(zabbixAlertLogsList.size()>0){
//            return true;
//        }
        return false;
    }
    /**
     * 组装我们定义的实体类
     * @param response
     * @return
     */
    private static List<Host> getHosts(JSONObject response) {
        JSONArray jsonArray = response.getJSONArray(ZABBIX_RESPONSE_RESULT);
        List<Host> hosts = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Set<String> keySet = jsonObject.keySet();
            JSONObject jsonObjectNew = new JSONObject();
            for (String s : keySet) {
                String f = com.baomidou.mybatisplus.core.toolkit.StringUtils.underlineToCamel(s);
                jsonObjectNew.put(f, jsonObject.get(s));
            }
            Host host = jsonObjectNew.toJavaObject(Host.class);
            hosts.add(host);
        }
        return hosts;
    }

    /**
     * 获取主机群组全部信息
     *
     * @return
     */
    private cn.hutool.json.JSONArray getHostGroup() {
        Request request = RequestBuilder.newBuilder()
                .method(HOST_GROUP)
                .jsonrpc("2.0")
                .paramEntry(ZABBIX_QUERY_OUTPUT, "extend")
                .id(1)
                .build();
        JSONObject response = call(request, true);
//        String jsonArray = (String) response.get(ZABBIX_RESPONSE_RESULT);
        cn.hutool.json.JSONArray array = JSONUtil.parseArray(response.get(ZABBIX_RESPONSE_RESULT));
        return array;

    }


}
