package com.tax.sign.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tax.sign.constants.SignConstants;
import com.tax.sign.mapper.SignDateInfoMapper;
import com.tax.sign.model.SignDateInfo;
import com.tax.sign.model.SignDateInfoExample;
import com.tax.sign.service.api.SignDateInfoService;

import com.yxcheng.token.common.cache.RedisService;
import com.yxcheng.token.constants.RedisContants;
import com.yxcheng.token.utils.*;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;


@Transactional
@Component
@ComponentScan(basePackages = {"com.tax.sign.dao"})
public class SignDateInfoServiceImpl implements SignDateInfoService{

    @Autowired
    private SignDateInfoMapper signDateInfoMapper;
    @Autowired
    private RedisService redisService;

    @Override
    public List<SignDateInfo> selectByExample(SignDateInfoExample example) {
        return signDateInfoMapper.selectByExample(example);
    }

    @Override
    public int updateByPrimaryKey(SignDateInfo record) {
        return signDateInfoMapper.updateByPrimaryKey(record);
    }

    @Override
    public void setSignDateInfoToRedis(SignDateInfo signDateInfo) {
        redisService.set(RedisContants.SIGN_DATE_LIST + signDateInfo.getZoneCode(), signDateInfo,  SignDateInfo.class);
    }

    @Override
    public SignDateInfo getSignDateInfoByRedis(String zoneCode) {
        SignDateInfo signDateInfo = redisService.get(RedisContants.SIGN_DATE_LIST + zoneCode, SignDateInfo.class);
        if(null == signDateInfo) {
            SignDateInfoExample example = new SignDateInfoExample();
            example.createCriteria().andZoneCodeEqualTo(zoneCode);
            List<SignDateInfo> signDateInfoList = signDateInfoMapper.selectByExample(example);
            if(null!=signDateInfoList && signDateInfoList.size()>0) {
                signDateInfo = signDateInfoList.get(0);
                setSignDateInfoToRedis(signDateInfo);
            }
        }else{
            //serverdate增加容错机制
            setFaultTolerantServerDate(signDateInfo);
        }
        return signDateInfo;
    }

    @Override
    public void synDateInfo() {
        try {
            ResponseContent content = HttpHelper.getUrlRespContent(SignConstants.dateInfoUrl);
            String data = content.getContent("utf-8");
            if(StringUtils.isNotBlank(data)){
                Map<String,String> map = (Map)JSON.parseObject(data).get("urlMap");
                for(Map.Entry<String,String> entry : map.entrySet()){
                    SignDateInfoExample example = new SignDateInfoExample();
                    example.createCriteria().andZoneCodeEqualTo(entry.getKey());
                    List<SignDateInfo> signDateInfos = this.selectByExample(example);
                    if(signDateInfos!=null && signDateInfos.size()>0){
                        SignDateInfo signDateInfo = signDateInfos.get(0);
                        signDateInfo.setReqUrl(entry.getValue() + SignConstants.dateInfoUrlSuffix);
                        signDateInfoMapper.updateByPrimaryKeySelective(signDateInfo);
                        redisService.set(RedisContants.SIGN_DATE_LIST + signDateInfo.getZoneCode(), signDateInfo,  SignDateInfo.class);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setFaultTolerantServerDate(SignDateInfo signDateInfo) {
        //如果时间差不存在  这套算法作废
        if(signDateInfo.getTimeDiff()!=null){
           // long currentDateLong = redisService.getDate().getTime();
            long currentDateLong = System.currentTimeMillis();
            //当前时间加上差值时间等于预期税局时间
            long curSerDateLong = currentDateLong  + signDateInfo.getTimeDiff();
            Date resultDate = DateUtils.getDate(curSerDateLong);

            //预期时间与服务器时间如果相差4分钟，就认为缓存的serverDate是错误的
            long diff = DateUtils.getDiff(resultDate, signDateInfo.getServerDate());
            if(diff > SignConstants.SERVER_LOCAL_EXPECT_TIME_DIFF){
                signDateInfo.setServerDate(resultDate);
                signDateInfo.setServerDateWay(SignConstants.LOCAL_EXE_SERVER_DATE_WAY);
            }
        }
    }
}
