package com.hr.externelSystem;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.hr.config.aiwen.AiwenAlertConfig;
import com.hr.dto.AiwenDto;
import com.hr.dto.ApiLogDto;
import com.hr.param.AiwenParam;
import com.hr.repository.domain.IpInterfacePO;
import com.hr.repository.domain.IpOrderPO;
import com.hr.service.FeishuMsgSendService;
import com.hr.vo.AiwenParseIpInfoVO;
import com.hr.vo.CallbackResponseVO;
import com.hr.vo.ServiceTypeVO;
import com.yy.basedevelop.common.http.config.RedisService;
import com.yy.basedevelop.common.util.HttpClientUtils;
import com.yy.basedevelop.common.util.RedisUtil;
import com.yy.basedevelop.common.util.ruoyi.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 埃文 ip解析加预警工具
 */
@Service
@Slf4j
public class AiwenIpService implements BizHandler<AiwenParam,AiwenParseIpInfoVO>{

    @Autowired
    private RedisService redisService;

    @Autowired
    private AiwenAlertConfig aiwenAlertConfig;

    private Long callExceptionCount=0L;

    @Autowired
    private FeishuMsgSendService feishuMsgSendService;
    @Autowired
    private RedisUtil redisUtil;

    private Boolean cansendmsg=true;
    private Boolean cansendmaxmsg=true;



    private Long callIpEmptyExceptionCount=0L;

    private Integer limitFlag=0;

    private static final String AiwenCallRedisKey = "Redis:Aiwen:CallCount:IpParseCall";
    private static final String AiwenCallRedisKeyIpEmpty = "Redis:Aiwen:CallCount:IpParseCallEmpty";
    private static final String AiwenCallRedisKeyNetWork = "Redis:Aiwen:CallCount:IpParseCallNetWork";

    @Override
    public ServiceTypeVO getType() {
        return new ServiceTypeVO("aiwen","埃文IP解析");
    }

    @Override
    public AiwenParseIpInfoVO handle(AiwenParam aiwenIpParam, IpInterfacePO ipInterfacePO, ApiLogDto logDto) {
        {
            String interfaceConfig = ipInterfacePO.getInterfaceConfig();
            AiwenDto aiwenDto = JSON.parseObject(interfaceConfig, AiwenDto.class);
            log.info("埃文解析的ip地址: {}", aiwenIpParam.getIp());
            String curday=getCurrentDate();
            AiwenParseIpInfoVO ipInfoDTO = new AiwenParseIpInfoVO();
            //这里代码看着多，实际上只有ip为空才调用
            if(StringUtils.isEmpty(aiwenIpParam.getIp())){
                StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
                if(stackTraceElements!=null && stackTraceElements.length>2){
//                System.out.println(stackTraceElements[1]);
                    Map<String,String> map=null;
                    String errdetailname=stackTraceElements[2].toString();
                    Long errcount=0L;
                    String curerremptykey=AiwenCallRedisKeyIpEmpty+":"+curday;
                    if(redisService.hasKey(curerremptykey)){
                        map=redisService.getCacheMap(curerremptykey);
                    }else {
                        map = new HashMap<>();
                        redisService.setCacheMap(curerremptykey, map);
                    }
                    if(map!=null){
                        if(map.containsKey(errdetailname)){
                            errcount=Long.valueOf(map.get(errdetailname).toString());
                            errcount++;
                            map.put(errdetailname,errcount.toString());
                        }else{
                            errcount++;
                            map.put(errdetailname,errcount.toString());
                        }
                        redisService.setCacheMap(curerremptykey, map);
                    }
                    callIpEmptyExceptionCount++;
                    if(callIpEmptyExceptionCount%10==0) {
                        feishuMsgSendService.dealFeishuMsgSendIpGroup("[异常]" + curday + ",埃文IP解析传入的Ip为空,调用函数为:"+errdetailname+",该函数已异常["+errcount+"]次");
                    }
                }
            }
            String yesterday=getYesterday();
            String yesternetkey=AiwenCallRedisKeyNetWork+":"+yesterday;
            String curnetkey=AiwenCallRedisKeyNetWork+":"+curday;
            try {

                ValueOperations<String, Object> valueOps = redisService.redisTemplate.opsForValue();


                Date now = new Date();
                // 定义时间格式
                DateTimeFormatter formattertime = DateTimeFormatter.ofPattern("HH:mm:ss");
                // 格式化当前时间
                String formattedTime = DateUtils.parseDateToStr("HH:mm:ss", now);
                String curCallIpKey=AiwenCallRedisKey+":"+curday;
                String yestCallIpKey=AiwenCallRedisKey+":"+yesterday;

                //原子加1
                // 使用increment方法进行原子加操作，delta为增加的值，默认为1
                if(valueOps.get(curCallIpKey) == null){
                    cansendmsg=true;
                    cansendmaxmsg=true;
                    callIpEmptyExceptionCount=0L;
                    callExceptionCount=0L;
                    //删除昨天的key避免浪费
                    if(redisService.hasKey(yestCallIpKey) ){
                        redisService.deleteObject(yestCallIpKey);
                    }
                    String yesterremptykey=AiwenCallRedisKeyIpEmpty+":"+yesterday;

                    if(redisService.hasKey(yesterremptykey) ){
                        redisService.deleteObject(yesterremptykey);
                    }

                    if(redisService.hasKey(yesternetkey) ){
                        redisService.deleteObject(yesternetkey);
                    }
                }else{
                    Long _count = Long.valueOf(valueOps.get(curCallIpKey).toString());
                    //如果当前是0则说明是重新设置了redis那么重新初始化
                    if(_count==0L){
                        cansendmsg=true;
                        cansendmaxmsg=true;
                        callIpEmptyExceptionCount=0L;
                        callExceptionCount=0L;
                    }
                }
                //原子加
                Long count = valueOps.increment(curCallIpKey, 1L);

                if(count<=aiwenAlertConfig.getIpmaxcallstart()  ){
                    if(count%aiwenAlertConfig.getIpstepcount()==0) {
                        //触发消息
                        feishuMsgSendService.dealFeishuMsgSendIpGroup("[预警]," + curday + "埃文IP已调用[" + count.toString() + "]次," + formattedTime);
                    }
                }

                String url = aiwenDto.getUrl() + "/?key=" + aiwenDto.getKey() + "&ip=" + aiwenIpParam.getIp() + "&coordsys=WGS84";
                Map<String,String> requestMap = new HashMap();
                requestMap.put("key", aiwenDto.getKey());
                requestMap.put("ip", aiwenIpParam.getIp());
                logDto.setRequestParam(JSON.toJSONString(requestMap));
                logDto.setUrl(url);
                // 调用接口解析ip地址信息
                String response = HttpClientUtils.get(url, new HashMap());
                logDto.setResponseParam(response);
                JSONObject ipParseJson = JSONObject.parseObject(response);
                logDto.setHttpStatus(ipParseJson.getString("code"));
                // 解析ip地址解析后的数据
                if ("Success".equals(ipParseJson.getString("code"))) {
                    JSONObject data = ipParseJson.getJSONObject("data");

                    String province = data.getString("prov");
                    String city = data.getString("city");
                    if (province != null) {
                        ipInfoDTO.setProvince(province.replace("省",""));
                    }
                    if(city != null){
                        ipInfoDTO.setCity(city);
                    } else {
                        // city字段为空时, 默认采用省份填充
                        ipInfoDTO.setCity(province);
                    }

                    ipInfoDTO.setCountry(data.getString("country"));
                    ipInfoDTO.setIp(ipParseJson.getString("ip"));
                    ipInfoDTO.setSub(data.getString("isp"));
                    ipInfoDTO.setInfo("");
                    ipInfoDTO.setCityCode(data.getString("adcode"));
                    ipInfoDTO.setLat(data.getString("lat"));
                    ipInfoDTO.setLng(data.getString("lng"));
                    log.info("埃文科技解析isp:{}", ipInfoDTO.getSub());
                }else{
                    if ("DailyLimited".equals(ipParseJson.getString("code")) ){
                        log.error("埃文科技解析ip调用超量了");
                        logDto.setErrorMessage("埃文科技解析ip调用超量了");
                        if (null != redisUtil) {
                            limitFlag=1;
                            if(count%aiwenAlertConfig.getAiwenoverlimitstep()==1){
                                feishuMsgSendService.dealFeishuMsgSendIpGroup("[异常]" + curday + ",埃文IP调用返回值为已超量,现已达到了redis值["+count.toString()+"]次,"+formattedTime);
                            }
                        }
                    }
                    log.error("埃文ip地址请求失败:{},接口返回数据格式不正确", aiwenIpParam.getIp());
                }
            } catch (Exception e) {
                log.error("埃文ip地址解析异常, {},{}", aiwenIpParam.getIp(),e.getMessage());
                logDto.setErrorMessage("埃文ip地址解析异常");
                Long counterr = redisService.redisTemplate.opsForValue().increment(curnetkey, 1L);
                if(counterr%aiwenAlertConfig.getAiwennetworklimitstep()==1) {
                    feishuMsgSendService.dealFeishuMsgSendIpGroup("[异常]" + curday + ",埃文IP调用异常["+counterr+"]次,请检查服务是否正常");
                }
                callExceptionCount++;
            }

            return ipInfoDTO;
        }
    }

    @Override
    public Class<AiwenParam> getRequestClass() {
        return AiwenParam.class;
    }

    @Override
    public CallbackResponseVO doCallBack(IpOrderPO ipOrderPO, JSONObject callbackParam) {
        log.info("开始处理回调");
        CallbackResponseVO vo = new CallbackResponseVO();
        String callbackUrl = ipOrderPO.getCallbackUrl();
        Map<String,String> javaObject = JSONObject.toJavaObject(callbackParam, Map.class);
        String post = HttpClientUtils.post(callbackUrl, javaObject);
        vo.setStatus(true);
        vo.setResponseParam(post);
        System.out.println(post);
        return vo;
    }


    /**
     * 获取昨天日期字符串，格式为 yyyyMMdd
     * @return 昨天日期字符串
     */
    public static String getYesterday() {
        Date date = DateUtils.addDays(new Date(),-1);
        return DateUtils.parseDateToStr("yyyyMMdd", date);
    }

    /**
     * 获取当前日期字符串，格式为 yyyyMMdd
     * @return 当前日期字符串
     */
    public static String getCurrentDate() {
        return DateUtils.parseDateToStr("yyyyMMdd", new Date());
    }
}
