package com.tax.sign.service.impl;

import com.simple.tool.encrypt.factory.EncryptFactory;
import com.simple.tool.sign.factory.IHttpRequest;
import com.simple.tool.sign.factory.MyHttpRequestImpl;
import com.tax.sign.constants.SignConstants;
import com.tax.sign.model.*;
import com.tax.sign.service.api.SgCookieConfigService;
import com.tax.sign.service.api.SgSignLogService;
import com.tax.sign.service.api.SignDateInfoService;
import com.tax.sign.service.api.SignService;
import com.tax.sign.utils.IntegrationUtils;
import com.tax.sign.utils.SignUtil;
import com.yxcheng.token.common.cache.RedisService;
import com.yxcheng.token.common.model.JsonResult;
import com.yxcheng.token.common.template.ApiTemplate;
import com.yxcheng.token.utils.HttpHelper;
import com.yxcheng.token.utils.IpUtil;
import com.yxcheng.token.utils.ResponseContent;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;

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

    private static final Logger logger = LoggerFactory.getLogger(SignServiceImpl.class);

    @Autowired
    private SgSignLogService sgSignLogService;

    @Autowired
    private SignDateInfoService signDateInfoService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private SgCookieConfigService sgCookieConfigService;

    final BASE64Decoder decoder = new BASE64Decoder();


    @Override
    public JsonResult<SignModel> getLoginSign(SignReq signReq, HttpServletRequest request) {

        return new ApiTemplate<JsonResult<SignModel>>("getLoginSign") {
            @Override
            protected JsonResult<SignModel> process() throws Exception {
                JsonResult<SignModel>jsonResult = new JsonResult<SignModel>();

                String taxno = signReq.getTaxno();
                String serverRandom = signReq.getServerRandom();
                String zoneCode = signReq.getDqdm();
                SignDateInfo signDateInfoByRedis = signDateInfoService.getSignDateInfoByRedis(zoneCode);

                //构建日志
                SgSignLog sgSignLog = sgSignLogService.getLog(signReq,signDateInfoByRedis,request);

                //构建加密
                Long time = signDateInfoByRedis.getServerDate().getTime();

                String timeSec = String.valueOf(time);

                EncryptFactory fact = EncryptFactory.newInstance();
                String result = "";
//                if(SignConstants.loginSignNewProvince.equals(zoneCode)){
                result = SignUtil.checkSign(taxno,timeSec,serverRandom);
//                }
//                else{
//                    result = fact.checkTaxno(taxno, timeSec, serverRandom, SignConstants.timeToChage,zoneCode, SignConstants.loginSignType);
//                }

                logger.info("sign:" + result);

                SignModel model = new SignModel();
                model.setSign(result);
                model.setTaxno(taxno);
                model.setTs(timeSec);
                jsonResult.setData(model);

                if(StringUtils.isNotBlank(result)){
                    sgSignLog.setResContext(JSONObject.fromObject(model).toString());
                    sgSignLog.setResDate(new Date());
                }
                sgSignLogService.saveSgSignLog(sgSignLog);

                return jsonResult;
            }
        }.execute();


    }

    @Override
    public JsonResult<SignModel> getOneInvSign(OneInvSignReq signReq, HttpServletRequest request) {
        return new ApiTemplate<JsonResult<SignModel>>("getOneInvSign") {
            @Override
            protected JsonResult<SignModel> process() throws Exception {
                JsonResult<SignModel>jsonResult = new JsonResult<SignModel>();

                String taxno = signReq.getTaxno();
                String fpdm = signReq.getFpdm();
                String fphm = signReq.getFphm();
                String token = signReq.getToken();
                String zoneCode = signReq.getDqdm();

                if(redisService.exists("pushTokenFlag")){
                    IntegrationUtils.pushToken(token,taxno,zoneCode);
                }

                SignDateInfo signDateInfoByRedis = signDateInfoService.getSignDateInfoByRedis(zoneCode);

                SgSignLog sgSignLog = sgSignLogService.getLog(signReq,signDateInfoByRedis,request);


                Long time = signDateInfoByRedis.getServerDate().getTime();
                sgSignLog.setServerDateWay(signDateInfoByRedis.getServerDateWay());

                String timeSec = String.valueOf(time);

                EncryptFactory fact = EncryptFactory.newInstance();
                String result = fact.checkOneInv(taxno,fpdm,fphm,token,timeSec,zoneCode,SignConstants.timeToChage,SignConstants.signType);
                logger.info("sign:" + result);

                SignModel model = new SignModel();
                model.setSign(result);
                model.setTaxno(taxno);
                model.setTs(timeSec);
                jsonResult.setData(model);

                if(StringUtils.isNotBlank(result)){
                    sgSignLog.setResContext(JSONObject.fromObject(model).toString());
                    sgSignLog.setResDate(new Date());
                }

                sgSignLogService.saveSgSignLog(sgSignLog);

                return jsonResult;
            }
        }.execute();

    }

    @Override
    public JsonResult<SignModel> getSelectSign(SignReq signReq, HttpServletRequest request) {
        return new ApiTemplate<JsonResult<SignModel>>("getSelectSign") {
            @Override
            protected JsonResult<SignModel> process() throws Exception {
                JsonResult<SignModel>jsonResult = new JsonResult<SignModel>();

                String taxno = signReq.getTaxno();
                String token = signReq.getToken();
                String zoneCode = signReq.getDqdm();

                EncryptFactory fact = EncryptFactory.newInstance();

                SignDateInfo signDateInfoByRedis = signDateInfoService.getSignDateInfoByRedis(zoneCode);

                SgSignLog sgSignLog = sgSignLogService.getLog(signReq,signDateInfoByRedis,request);
                Long time = signDateInfoByRedis.getServerDate().getTime();


                String timeSec = String.valueOf(time);

                String result = fact.checkInvConf(taxno,token,timeSec,zoneCode,SignConstants.timeToChage,SignConstants.signType);
                logger.info("sign:" + result);

                SignModel model = new SignModel();
                model.setSign(result);
                model.setTaxno(taxno);
                model.setTs(timeSec);
                jsonResult.setData(model);

                if(StringUtils.isNotBlank(result)){
                    sgSignLog.setResContext(JSONObject.fromObject(model).toString());
                    sgSignLog.setResDate(new Date());
                }

                sgSignLogService.saveSgSignLog(sgSignLog);
                return jsonResult;
            }
        }.execute();

    }

    @Override
    public JsonResult<SignModel> getDkDownloadSign(DkDownloadReq signReq, HttpServletRequest request) {
        return new ApiTemplate<JsonResult<SignModel>>("getDkDownloadSign") {
            @Override
            protected JsonResult<SignModel> process() throws Exception {
                JsonResult<SignModel>jsonResult = new JsonResult<SignModel>();

                String taxno = signReq.getTaxno();
                String token = signReq.getToken();
                String zoneCode = signReq.getDqdm();
                String dkyf = signReq.getDkyf();



                SignDateInfo signDateInfoByRedis = signDateInfoService.getSignDateInfoByRedis(zoneCode);
                Long time = signDateInfoByRedis.getServerDate().getTime();

                SgSignLog sgSignLog = sgSignLogService.getLog(signReq,signDateInfoByRedis,request);

                EncryptFactory fact = EncryptFactory.newInstance();


                String timeSec = String.valueOf(time);
                String result = fact.checkDeduDown(taxno,token,timeSec,dkyf,zoneCode,SignConstants.timeToChage,SignConstants.signType);
                logger.info("sign:" + result);

                SignModel model = new SignModel();
                model.setSign(result);
                model.setTaxno(taxno);
                model.setTs(timeSec);
                jsonResult.setData(model);

                if(StringUtils.isNotBlank(result)){
                    sgSignLog.setResContext(JSONObject.fromObject(model).toString());
                    sgSignLog.setResDate(new Date());
                }
                sgSignLog.setIpAddress(IpUtil.getRequestRealIp(request));
                sgSignLogService.saveSgSignLog(sgSignLog);

                return jsonResult;
            }
        }.execute();


    }

    @Override
    public JsonResult<SignModel> getSuperSign(SignReq signReq, HttpServletRequest request) {
        return new ApiTemplate<JsonResult<SignModel>>("getSuperSign") {
            @Override
            protected JsonResult<SignModel> process() throws Exception {
                JsonResult<SignModel>jsonResult = new JsonResult<SignModel>();

                String taxno = signReq.getTaxno();
                String zoneCode = signReq.getDqdm();
                //mr.s 希望保持参数统一
                String serverRandom = signReq.getToken();


                SignDateInfo signDateInfoByRedis = signDateInfoService.getSignDateInfoByRedis(zoneCode);

                SgSignLog sgSignLog = sgSignLogService.getLog(signReq,signDateInfoByRedis,request);

                Long time = signDateInfoByRedis.getServerDate().getTime();


                String timeSec = String.valueOf(time);
                String result = SignUtil.getSuperSign(taxno,timeSec,serverRandom);
                logger.info("sign:" + result);

                SignModel model = new SignModel();
                model.setSign(result);
                model.setTaxno(taxno);
                model.setTs(timeSec);
                jsonResult.setData(model);

                if(StringUtils.isNotBlank(result)){
                    sgSignLog.setResContext(JSONObject.fromObject(model).toString());
                    sgSignLog.setResDate(new Date());
                }

                sgSignLogService.saveSgSignLog(sgSignLog);

                return jsonResult;
            }
        }.execute();

    }

    @Override
    public JsonResult<SignModel> getSuperPubSign(PubSignReq signReq, HttpServletRequest request) {
        return new ApiTemplate<JsonResult<SignModel>>("getSuperPubSign") {

            @Override
            protected JsonResult<SignModel> process() throws Exception {
                JsonResult<SignModel>jsonResult = new JsonResult<SignModel>();
                String taxno = signReq.getTaxno();
                String zoneCode = signReq.getDqdm();
                String ts = signReq.getTs();
                if(StringUtils.isBlank(ts)){
                    SignDateInfo signDateInfoByRedis = signDateInfoService.getSignDateInfoByRedis(zoneCode);

                    SgSignLog sgSignLog = sgSignLogService.getLog(signReq,signDateInfoByRedis,request);
                    sgSignLogService.saveSgSignLog(sgSignLog);

                    Long time = signDateInfoByRedis.getServerDate().getTime();
                    ts = String.valueOf(time);
                }
                SignModel model = new SignModel();
                model.setTaxno(taxno);
                model.setTs(ts);
                model.setSign(SignUtil.getSuperPubSign(taxno,signReq.getToken(),ts));
                jsonResult.setData(model);

                return jsonResult;
            }
        }.execute();
    }

    @Override
    public JsonResult<DeduSignModel> getDeduSign(DeduSignReq signReq, HttpServletRequest request) {
        return new ApiTemplate<JsonResult<DeduSignModel>>("getDeduSign") {

            @Override
            protected JsonResult<DeduSignModel> process() throws Exception {
                JsonResult<DeduSignModel>jsonResult = new JsonResult<DeduSignModel>();
                String taxno = signReq.getTaxno();
                com.simple.tool.sign.factory.EncryptFactory  encryptFactory = com.simple.tool.sign.factory.EncryptFactory.getInstance();
                
                String resultStr = null;
                
                IHttpRequest myrequest = new MyHttpRequestImpl();
                myrequest.setRequestURI(signReq.getUrlPath());
                
                if("1.0".equals(signReq.getVersion())){//老的调用超签
                	resultStr =  encryptFactory.getSignOld(signReq.getTaxno(), signReq.getToken(),myrequest);
        		}else if("2.0".equals(signReq.getVersion())){//新的调用最新签名方法
        			resultStr =  encryptFactory.getSuperStr(signReq.getTaxno(), signReq.getToken());
        		}
                
                SgSignLog sgSignLog = sgSignLogService.getLog(signReq,null,request);

                DeduSignModel model = new DeduSignModel();
                model.setTaxno(taxno);
                model.setSign(resultStr);
                jsonResult.setData(model);

                sgSignLog.setResContext(JSONObject.fromObject(model).toString());
                sgSignLog.setResDate(new Date());
                sgSignLogService.saveSgSignLog(sgSignLog);
                return jsonResult;
            }
        }.execute();
    }

    @Override
    public JsonResult<DeduSignModel> getDeduSignNew(DeduSignReq signReq, HttpServletRequest request) {
        return new ApiTemplate<JsonResult<DeduSignModel>>("getDeduSignNew") {

            @Override
            protected JsonResult<DeduSignModel> process() throws Exception {
                JsonResult<DeduSignModel>jsonResult = new JsonResult<DeduSignModel>();
                String taxno = signReq.getTaxno();
                com.simple.tool.sign.factory.EncryptFactory  encryptFactory = com.simple.tool.sign.factory.EncryptFactory.getInstance();
                String resultStr = null;
                
    			IHttpRequest myrequest = new MyHttpRequestImpl();
    			myrequest.setRequestURI(signReq.getUrlPath());
    			
                if("1.0".equals(signReq.getVersion())){//老的调用超签
                	resultStr =  encryptFactory.getSignOld(signReq.getTaxno(), signReq.getToken(),myrequest);
        		}else if("2.0".equals(signReq.getVersion())){//新的调用最新签名方法
        			resultStr =  encryptFactory.getSuperStr(signReq.getTaxno(), signReq.getToken());
        		}
                
                SgSignLog sgSignLog = sgSignLogService.getLog(signReq,null,request);

                DeduSignModel model = new DeduSignModel();
                model.setTaxno(taxno);
                model.setSign(resultStr);
                jsonResult.setData(model);

                sgSignLog.setResContext(JSONObject.fromObject(model).toString());
                sgSignLog.setResDate(new Date());
                sgSignLogService.saveSgSignLog(sgSignLog);
                return jsonResult;
            }
        }.execute();
    }


    @Override
    public JsonResult<SignCookieRes> getSignCookie(SignCookieReq signReq, HttpServletRequest request,boolean isInterior) {
        JsonResult<SignCookieRes>jsonResult = new JsonResult<SignCookieRes>();
        SignCookieRes res = new SignCookieRes();

        SgCookieConfigExample example = new SgCookieConfigExample();
        example.createCriteria().andZoneCodeEqualTo(signReq.getDqdm());
        SgCookieConfig sgCookieConfig = sgCookieConfigService.getOne(example);
        if(sgCookieConfig==null){
            jsonResult.setMessage("此地区暂未开通");
            return jsonResult;
        }

        try {
            String originUrl = new String(decoder.decodeBuffer(signReq.getUrl()));
            if(!isInterior && ! isCookieCorrectUrl(originUrl)){
                jsonResult.setMessage("不支持当前url");
                return jsonResult;
            }
            String url = sgCookieConfig.getUrl()+signReq.getUrl();
            ResponseContent respContent = HttpHelper.getUrlRespContent(url);
            String content = respContent.getContent();
            if(StringUtils.isNotBlank(content)){
                com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(content);
                res.setKey1(jsonObject.getString("key1"));
                res.setKey2(jsonObject.getString("key2"));
            }
            jsonResult.setData(res);
            SgSignLog sgSignLog = sgSignLogService.getLog(signReq,null,request);
            if(content.length()>1000){
                content = content.substring(0,999);
            }
            sgSignLog.setResContext(content);
            sgSignLog.setResDate(new Date());
            sgSignLogService.saveSgSignLog(sgSignLog);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return jsonResult;
    }

    private boolean isCookieCorrectUrl(String originUrl) {
        int num = originUrl.indexOf("?");
        if(num<0) return originUrl.contains("login.do");
        return originUrl.substring(num-8,num).equals("login.do");
    }


    public static void main(String[] args) {
        String originUrl = "https://fpdk.ningbo.chinatax.gov.cn/NFpxzWW/fpxz.do_=1458270057817&callback=jQuery70589663709480695080_159705076643255login.do";
        int num = originUrl.indexOf("?");
        System.out.println(originUrl.substring(num-8,num).equals("login.do"));
    }

}
