package com.tax.file.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.tax.file.constants.FileConstants;
import com.tax.file.integration.token.TokenClient;
import com.tax.file.model.*;
import com.tax.file.model.fileManage.*;
import com.tax.file.service.api.*;
import com.tax.file.service.util.UserUtils;
import com.tax.file.utils.CommonUtil;
import com.tax.file.utils.ExpCacheUtils;
import com.yxcheng.token.common.cache.RedisService;
import com.yxcheng.token.common.enumutil.ResultEnum;
import com.yxcheng.token.common.model.InvoiceFileTaxBatchManageReq;
import com.yxcheng.token.common.model.JsonResult;
import com.yxcheng.token.common.model.TokenInfo;
import com.yxcheng.token.constants.HttpRedisContants;
import com.yxcheng.token.constants.RedisContants;
import com.yxcheng.token.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;


@Transactional
@Component
@ComponentScan(basePackages = {"com.tax.file.dao", "com.tax.file.integration"})
@Slf4j
public class InvoiceFileServiceImpl implements InvoiceFileService {

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

    @Autowired
    TkTaxUserService tkTaxUserService;
    @Autowired
    FileServerService fileServerService;
    @Autowired
    TkFileService tkFileService;
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    TkUserUrlService tkUserUrlService;
    @Autowired
    FileUserService fileUserService;

    @Autowired
    RedisService redisService;
    @Autowired
    private FileSyncService fileSyncService;
    @Autowired
    private FileUserLogService fileUserLogService;
    @Autowired
    private FileApplyLogServiceImpl fileApplyLogServiceImpl;
    @Autowired
    private TokenClient tokenClient;

    /**
     * 发票文件下载
     *
     * @param invoiceFileReq
     * @return
     */
    @Override
    public JsonResult<Map> download(String timeFlag, InvoiceFileReq invoiceFileReq) {
        JsonResult jsonResult = new JsonResult();
        Instant start = Instant.now();
        String taskno = UUIDGenerator.generate();
        String userName = invoiceFileReq.getAccessKeyID();

        Map map = new HashMap();
        map.put("username", userName);
        map.put("pageSize", FileConstants.pageSize);
        List<TkFile> tkFiles = tkFileService.getTkFilePage(map);

        Map invListMap = createResponseJson(taskno, tkFiles, "0");
        if (null != tkFiles && tkFiles.size() > 0) {
            ExpCacheUtils.setDownloadTaskNoByTaxno(userName, taskno);
            fileSyncService.saveSyncList(tkFiles, taskno, "0", timeFlag);
        }

        Instant end = Instant.now();
        long duration = end.toEpochMilli() - start.toEpochMilli();
        log.info(timeFlag + " 发票文件下载，查询到发票数量："+tkFiles.size()+",用户名:"+invoiceFileReq.getAccessKeyID() + ",任务号：" + taskno + "，耗时：" + duration + "ms");
        jsonResult.setData(invListMap);
        return jsonResult;
    }

    @Override
    public JsonResult<Map> downloadRes(String timeFlag, InvoiceFileReq invoiceFileReq) {
        Instant start = Instant.now();
        int syncNum = 0;
        JsonResult jsonResult = new JsonResult();
        String curTaskno = ExpCacheUtils.getDownloadTaskNoByTaxno(invoiceFileReq.getAccessKeyID());
        if (curTaskno.equals(invoiceFileReq.getTaskno())) {
            List<FileSync> fileSyncList = fileSyncService.findFileSyncList(invoiceFileReq.getAccessKeyID(), null, curTaskno);
            if (fileSyncList.size() > 0) {
                fileSyncService.updateFileExpSyncList(fileSyncList, "0");
                syncNum = fileSyncList.size();
                ExpCacheUtils.delDownloadTaskNoByTaxno(invoiceFileReq.getAccessKeyID());
            } else {
                jsonResult.errorResponse(ResultEnum.file_taskno_error);
            }
        } else {
            jsonResult.errorResponse(ResultEnum.file_taskno_error);
        }
        Instant end = Instant.now();
        long duration = end.toEpochMilli() - start.toEpochMilli();
        log.info(timeFlag + " 发票文件下载反馈，任务编号：" + invoiceFileReq.getTaskno() + ",用户名:" + invoiceFileReq.getAccessKeyID() + ",更新记录数量：" + syncNum+ "，耗时：" + duration + "ms");
        return jsonResult;
    }

    /**
     * 发票文件下载
     *
     * @param invoiceFileReq
     * @return
     */
    @Override
    public JsonResult<Map> downloadList(String timeFlag, InvoiceFileReq invoiceFileReq) {
        JsonResult jsonResult = new JsonResult();
        Instant start = Instant.now();
        String taskno = UUIDGenerator.generate();
        String userName = invoiceFileReq.getAccessKeyID();
        String taxno = invoiceFileReq.getTaxno();

        List<TkFile> tkFiles = Lists.newArrayList();
        String expName = HttpRedisContants.getInvoiceExpListGroupName(userName, taxno, HttpRedisContants.COLLECT_LIST_TYPE_FILE);
        if (isExsitExpNameList(expName)) {
            Map map = new HashMap();
            map.put("username", userName);
            map.put("taxno", taxno);
            map.put("pageSize", FileConstants.pageSize);
            tkFiles = tkFileService.getTkFilePage(map);
        }
        Map invListMap = createResponseJson(taskno, tkFiles, "1");
        if (null != tkFiles && tkFiles.size() > 0) {
            ExpCacheUtils.setDownloadListTaskNoByTaxno(userName, taxno, taskno);
            fileSyncService.saveSyncList(tkFiles, taskno, "0", timeFlag);
        } else {
            delExpNameList(expName);
        }
        Instant end = Instant.now();
        long duration = end.toEpochMilli() - start.toEpochMilli();
        log.info(timeFlag + " 发票文件下载，查询到发票数量：" + tkFiles.size() + ",用户名:" + invoiceFileReq.getAccessKeyID() + "，税号:" + taxno+ "，耗时：" + duration + "ms");
        jsonResult.setData(invListMap);
        return jsonResult;
    }

    public Map createResponseJson(String taskno, List<TkFile> invFileList, String hasTaxno) {
        Map result = new HashMap();
        List<InvoiceFileRes> invoiceFiles = getFileModel(invFileList, hasTaxno);
        int quantity = invoiceFiles.size();
        result.put("taskno", taskno);
        result.put("quantity", quantity);
        result.put("invoiceFileList", invoiceFiles);
        result.put("followTask", quantity < FileConstants.pageSize ? false : true);
        return result;
    }

    //模型转换
    private List<InvoiceFileRes> getFileModel(List<TkFile> tkFiles, String hasTaxno) {
        List<InvoiceFileRes> invoiceFiles = new ArrayList<InvoiceFileRes>();
        if (tkFiles != null && tkFiles.size() > 0) {
            Iterator<TkFile> iter = tkFiles.iterator();
            while (iter.hasNext()) {
                TkFile tkFile = iter.next();
                InvoiceFileRes iFile = new InvoiceFileRes();
                iFile.setInvSpec(tkFile.getInvSpec());
                iFile.setInvType(tkFile.getInvType());
                iFile.setTaxno(tkFile.getTaxno());
                if(hasTaxno.equals("1")) {
                    iFile.setUrl(StringUtils.defaultIfEmpty(tkFile.getUrl(), tkFile.getFileName()));
                } else {
                    if(tkFile.getUserName().equals("bwgf-limit") || tkFile.getUserName().equals("qixiangyun")) {
                        iFile.setUrl(StringUtils.defaultIfEmpty(tkFile.getUrl(), tkFile.getFileName()));
                    } else {
                        iFile.setUrl(tkFile.getUrl());
                    }
                }
                iFile.setErrorCode(StringUtils.defaultIfEmpty(tkFile.getErrorCode(), ""));
                iFile.setApplyDate(tkFile.getApplyDate() != null ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(tkFile.getApplyDate()) : "");
                iFile.setInvDate_start(tkFile.getInvDateStart() != null ? new SimpleDateFormat("yyyy-MM-dd").format(tkFile.getInvDateStart()) : "");
                iFile.setInv_date_end(tkFile.getInvDateEnd() != null ? new SimpleDateFormat("yyyy-MM-dd").format(tkFile.getInvDateEnd()) : "");
                invoiceFiles.add(iFile);
            }
        }
        return invoiceFiles;
    }

    /**
     * 发票文件下载反馈
     *
     * @param invoiceFileReq
     * @return
     */
    @Override
    public JsonResult<Map> downloadListRes(String timeFlag, InvoiceFileReq invoiceFileReq) {
        int syncNum = 0;
        Instant start = Instant.now();
        JsonResult jsonResult = new JsonResult();
        String curTaskno = ExpCacheUtils.getDownloadListTaskNoByTaxno(invoiceFileReq.getAccessKeyID(), invoiceFileReq.getTaxno());
        if (curTaskno.equals(invoiceFileReq.getTaskno())) {
            List<FileSync> fileSyncList = fileSyncService.findFileSyncList(invoiceFileReq.getAccessKeyID(), invoiceFileReq.getTaxno(), curTaskno);
            if (fileSyncList.size() > 0) {
                fileSyncService.updateFileExpSyncList(fileSyncList, "0");
                syncNum = fileSyncList.size();
                ExpCacheUtils.delDownloadListTaskNoByTaxno(invoiceFileReq.getAccessKeyID(), invoiceFileReq.getTaxno());
            } else {
                jsonResult.errorResponse(ResultEnum.file_taskno_error);
            }
        } else {
            jsonResult.errorResponse(ResultEnum.file_taskno_error);
        }
        Instant end = Instant.now();
        long duration = end.toEpochMilli() - start.toEpochMilli();
        log.info(timeFlag + " 发票文件下载反馈，任务编号：" + invoiceFileReq.getTaskno() + ",用户名:" + invoiceFileReq.getAccessKeyID()
                + "，税号：" + invoiceFileReq.getTaxno() + "，任务号：" + invoiceFileReq.getTaskno() + ",更新记录数量：" + syncNum+ "，耗时：" + duration + "ms");
        return jsonResult;
    }

    /**
     * 获取税号信息
     *
     * @param invoiceFileReq
     * @return
     */
    @Override
    public JsonResult<Map> taxInfo(InvoiceFileReq invoiceFileReq) {
        if (StringUtil.isEmpty(invoiceFileReq.getTaxno())) {
            return new JsonResult().errorResponse(ResultEnum.param_error);
        }

        TkTaxUser taxUser = tkTaxUserService.queryTaxUser(invoiceFileReq.getAccessKeyID(), invoiceFileReq.getTaxno());
        if (null == taxUser) {
            return new JsonResult().errorResponse(ResultEnum.notfound);
        }

        Map map = new HashMap();
        if (!"1".equals(taxUser.getInit()) || taxUser.getApplyDownDate() == null) {//如果税号未初始化或申请日期为空，直接返回信息
            map.put("username", invoiceFileReq.getAccessKeyID());
            map.put("taxno", invoiceFileReq.getTaxno());
            map.put("invDateStart", "");//开票日期起
            map.put("invDateEnd", "");//开票日期止
            map.put("downStatus", "0");//下载状态 '0'未下载 '1'已下载
            return new JsonResult(map);
        }

        Date[] nationDates = DateUtils.getNationDates(FileConstants.applyCycle);
        Date preDateEnd = null;
        Date preDateStart = null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        if (nationDates == null || nationDates.length == 0) {
            preDateEnd = DateUtils.getPreLastDay(new Date(), 1);
            preDateStart = DateUtils.getApplyStartDate(preDateEnd, FileConstants.applyCycle);
        } else {
            preDateStart = nationDates[0];
            preDateEnd = nationDates[1];
        }

        boolean flag = false;
        if (preDateEnd != null) {
            flag = taxUser.getApplyDownDate().after(preDateEnd);//申请下载时间是否在结束日期之后
        }

        map.put("username", invoiceFileReq.getAccessKeyID());
        map.put("taxno", invoiceFileReq.getTaxno());
        map.put("invDateStart", sdf.format(preDateStart));//开票日期起
        map.put("invDateEnd", sdf.format(preDateEnd));//开票日期止
        //map.put("applyStatus", flag?"1":"0");//申请状态 '0' 未申请  '1'已申请
        map.put("downStatus", flag && "2".equals(taxUser.getApplyStatus()) ? "1" : "0");//下载状态 '0'未下载 '1'已下载
        map.put("runStatus", taxUser.getDelFlag());

        return new JsonResult(map);
    }

    /**
     * 税号初始化
     *
     * @param invoiceFileReq
     * @return
     */
    @Override
    public JsonResult<String> taxInit(InvoiceFileReq invoiceFileReq) {
        JsonResult result = new JsonResult();
        String optType = invoiceFileReq.getOptType();
        String uuidFlag = invoiceFileReq.getSignatureNonce();
        //1.查询server
        FileServerExample fileServerExample = new FileServerExample();
        fileServerExample.createCriteria().andServerNoEqualTo(FileConstants.taxInitServerNo);
        List<FileServer> fileServers = fileServerService.selectByExample(fileServerExample);

        if (fileServers == null || fileServers.size() == 0) {
            return JsonResult.errorResult("-1", "未查询到服务");
        }

        FileServer server = fileServers.get(0);

        //2.查询taxUser
        TkTaxUserExample userExample = new TkTaxUserExample();
        userExample.createCriteria().andTaxnoEqualTo(invoiceFileReq.getTaxno())
                .andUserNameEqualTo(invoiceFileReq.getAccessKeyID());
        List<TkTaxUser> taxUsers = tkTaxUserService.selectByExample(userExample);

        //3.业务处理
        boolean flag = false;
        if ("0".equals(optType)) {//增加
            if (taxUsers != null && taxUsers.size() > 0) {
                return JsonResult.errorResult("-1", "此税号已注册");
            }
            JSONObject resultJson1 = callWh(invoiceFileReq, server);//调用内部服务1，文豪
            if (resultJson1 != null && !"0".equals(resultJson1.getString("errorCode"))) {
                return JsonResult.errorResult("-1", resultJson1.getString("message") + ",用户名" + invoiceFileReq.getAccessKeyID());
            }
            if (taxUsers == null || taxUsers.size() == 0) {
                TkTaxUser record = new TkTaxUser();
                record.setTaxno(invoiceFileReq.getTaxno());
                record.setUserName(invoiceFileReq.getAccessKeyID());
                record.setDelFlag(getDelFlag(optType));
                record.setZoneCode(invoiceFileReq.getZoneCode());
                record.setCreateDate(new Date());
                tkTaxUserService.insertSelective(record);
            }
        } else if ("2".equals(optType) || "3".equals(optType)) {//开启或停用
            if (taxUsers == null || taxUsers.size() == 0) {
                return JsonResult.errorResult("-1", "此税号未注册");
            }

            if (taxUsers != null && taxUsers.size() > 0) {
                TkTaxUser record = taxUsers.get(0);
                record.setDelFlag(getDelFlag(optType));
                tkTaxUserService.updateByPrimaryKey(record);
            }
        } else {
            return JsonResult.errorResult("-1", "optType操作类型不正确");
        }

        if ("0".equals(optType) && flag == true) {
            log.info("taxInit " + invoiceFileReq.getTaxno() + ",ku is zhuce，not zai hongge na zhuce");
            return result;
        }

        JSONObject resultJson2 = callTax(uuidFlag, invoiceFileReq);//调用内部服务2，红哥
        if (resultJson2 != null && !"0".equals(resultJson2.getString("CODE"))) {
            return JsonResult.errorResult("-1", resultJson2.getString("MESSAGE") + ",用户名" + invoiceFileReq.getAccessKeyID());
        }

        return result;
    }

    /**
     * 获取发票下载的税号信息
     *
     * @param invoiceFileReq
     * @return
     */
    @Override
    public JsonResult<String> getTaxInfo(InvoiceFileReq invoiceFileReq) {

        String uuidFlag = invoiceFileReq.getSignatureNonce();
        String userName = invoiceFileReq.getAccessKeyID();

        log.info(uuidFlag + " taxno is " + invoiceFileReq.getTaxno() +" getTaxInfo is start ," + invoiceFileReq.toString());
        Map map = new HashMap();
        map.put("taxno", invoiceFileReq.getTaxno());
        List<Map> functionList = new ArrayList();

        if(tkUserUrlService.checkUserUrlExist(userName, TkUserUrl.FUNCTION_NO_INVOICE_TOKEN)) {
            addTokenErrorMessage(uuidFlag, invoiceFileReq, map);
        }
        if(invoiceFileReq.getTaxType().equals("1")) {
            if(tkUserUrlService.checkUserUrlExist(userName, TkUserUrl.FUNCTION_NO_CLOUD_INVOICE_COLLECT)) {
                addTaxnoUserQuery(uuidFlag, invoiceFileReq, functionList, TkUserUrl.FUNCTION_NO_CLOUD_INVOICE_COLLECT);
            }
            if(tkUserUrlService.checkUserUrlExist(userName, TkUserUrl.FUNCTION_NO_CLOUD_INVOICE_NUMBER_COLLECT)) {
                addNumberUserQuery(uuidFlag, invoiceFileReq, functionList, TkUserUrl.FUNCTION_NO_CLOUD_INVOICE_NUMBER_COLLECT);
            }
        } else {
            if(tkUserUrlService.checkUserUrlExist(userName, TkUserUrl.FUNCTION_NO_INVOICE_DOWNLOAD)) {
                addInvoiceDownloadQuery(invoiceFileReq, functionList, map, TkUserUrl.FUNCTION_NO_INVOICE_DOWNLOAD);
            }
            if(tkUserUrlService.checkUserUrlExist(userName, TkUserUrl.FUNCTION_NO_INVOICE_COLLECT)) {
                addTaxnoUserQuery(uuidFlag, invoiceFileReq, functionList, TkUserUrl.FUNCTION_NO_INVOICE_COLLECT);
            }
            if(tkUserUrlService.checkUserUrlExist(userName, TkUserUrl.FUNCTION_NO_INVOICE_NUMBER_COLLECT)) {
                addNumberUserQuery(uuidFlag, invoiceFileReq, functionList, TkUserUrl.FUNCTION_NO_INVOICE_NUMBER_COLLECT);
            }
        }

        map.put("functionList", functionList);
        log.info(uuidFlag + " taxno is " + invoiceFileReq.getTaxno() +" getTaxInfo is end ," + JSONObject.toJSONString(map));
        return new JsonResult(map);
    }

    private void addTokenErrorMessage(String uuidFlag, InvoiceFileReq invoiceFileReq, Map map) {
        JSONObject reqJson = queryTokenInfo(uuidFlag, invoiceFileReq);
        if (null != reqJson && null!=reqJson.get("data")) {
            Map dateObj = (Map)reqJson.get("data");
            map.put("tokenErrorDate", dateObj.get("tokenDate"));
            map.put("tokenErrorCode", dateObj.get("tokenCode"));
            map.put("tokenErrorMessage", dateObj.get("remarks"));
            map.put("tokenFlag", dateObj.get("tokenFlag"));
        } else {
            map.put("tokenErrorDate", null);
            map.put("tokenErrorCode", null);
            map.put("tokenErrorMessage", null);
            map.put("tokenFlag", null);
        }
    }

    private void addInvoiceDownloadQuery(InvoiceFileReq invoiceFileReq, List<Map> functionList, Map map, String functionNo) {
        //1.处理功能编号01(发票下载)
        TkTaxUser taxUser = UserUtils.flushTaxUserBytaxno(invoiceFileReq.getAccessKeyID(), invoiceFileReq.getTaxno());
        if (null == taxUser) {
            functionList.add(getFunction(functionNo, "", "", "", "", "", "", "",""));
        } else {
            map.put("taxno", invoiceFileReq.getTaxno());
            Date[] nationDates = DateUtils.getNationDates(FileConstants.applyCycle);
            Date preDateEnd = null;
            Date preDateStart = null;
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            if (nationDates == null || nationDates.length == 0) {
                preDateEnd = DateUtils.getPreLastDay(new Date(), 1);
                preDateStart = DateUtils.getApplyStartDate(preDateEnd, FileConstants.applyCycle);
            } else {
                preDateStart = nationDates[0];
                preDateEnd = nationDates[1];
            }
            String tokenStatusMsg = redisService.get(RedisContants.FILE_TOKEN_STATUS + taxUser.getTaxno());
            functionList.add(getFunction(
                    functionNo, taxUser.getUserStatus(),
                    taxUser.getOverFlag(),
                    taxUser.getOverDate() != null ? sdf.format(taxUser.getOverDate()) : "",
                    sdf.format(preDateStart), sdf.format(preDateEnd), tokenStatusMsg, String.valueOf(taxUser.getInitMonth()), taxUser.getIsOnce()));
        }
    }

    private void addTaxnoUserQuery(String uuidFlag, InvoiceFileReq invoiceFileReq, List<Map> functionList, String functionNo) {
        //处理功能编号02(异步采集) 05（发票云采集）
        String userName = invoiceFileReq.getAccessKeyID();
        TkUserUrl userUrl = tkUserUrlService.getUserUrl(userName, functionNo);
        if (userUrl == null) {
        } else {
            String hgResult = queryCollectTaxInfo(uuidFlag, invoiceFileReq, userUrl);
            if (StringUtil.isEmpty(hgResult)) {
                functionList.add(getFunction01(functionNo, "", "", "", "", "", "", "", ""));
            } else {
                JSONObject jsonStr = JSONObject.parseObject(hgResult);
                if (jsonStr != null && !"0".equals(jsonStr.getString("CODE"))) {
                    functionList.add(getFunction01(functionNo, "", "", "", "", "", "", "", ""));
                } else {
                    JSONObject dataJson = jsonStr.getJSONObject("DATA");
                    if (dataJson != null) {
                        functionList.add(getFunction01(functionNo, dataJson.getString("userStatus"), dataJson.getString("curCollectFlag")
                                , dataJson.getString("lastCollectDate"), dataJson.getString("zone"), dataJson.getString("errorMessage")
                                , dataJson.getString("initMonth"), dataJson.getString("validType"), dataJson.getString("invSpec")));
                    } else {
                        functionList.add(getFunction01(functionNo, "", "", "", "", "", "", "", ""));
                    }
                }
            }
        }
    }

    private void addNumberUserQuery(String uuidFlag, InvoiceFileReq invoiceFileReq, List<Map> functionList, String functionNo) {
        //处理功能编号03(数字账户) 06（发票云全量采集）
        String userName = invoiceFileReq.getAccessKeyID();
        TkUserUrl userUrl = tkUserUrlService.getUserUrl(userName, functionNo);
        if (userUrl == null) {
        } else {
            String hgResult = queryNumberCollectTaxInfo(uuidFlag, invoiceFileReq, userUrl);
            if (StringUtil.isEmpty(hgResult)) {
                functionList.add(getFunction01(functionNo, "", "", "", "", "", "", "", ""));
            } else {
                JSONObject jsonStr = JSONObject.parseObject(hgResult);
                if (jsonStr != null && !"0".equals(jsonStr.getString("CODE"))) {
                    functionList.add(getFunction01(functionNo, "", "", "", "", "", "", "", ""));
                } else {
                    JSONObject dataJson = jsonStr.getJSONObject("DATA");
                    if (dataJson != null) {
                        functionList.add(getFunction01(functionNo, dataJson.getString("userStatus"), dataJson.getString("curCollectFlag")
                                , dataJson.getString("lastCollectDate"), dataJson.getString("zone"), dataJson.getString("errorMessage")
                                , dataJson.getString("initMonth"), dataJson.getString("validType"), dataJson.getString("invSpec")));
                    } else {
                        functionList.add(getFunction01(functionNo, "", "", "", "", "", "", "", ""));
                    }
                }
            }
        }
    }

    private Map getFunction(String functionNo, String taxnoStatus, String curOverFlag, String lastOverDate
            , String invDateStart, String invDateEnd, String tokenStatusMsg, String initMonth, String validType) {
        Map function = new HashMap();
        function.put("functionNo", functionNo);
        function.put("taxnoStatus", taxnoStatus);
        function.put("curOverFlag", curOverFlag);
        function.put("lastOverDate", lastOverDate);
        function.put("invDateStart", invDateStart);
        function.put("invDateEnd", invDateEnd);
        function.put("tokenStatusMsg", tokenStatusMsg);
        function.put("initMonth", initMonth);
        function.put("validType", validType);
        return function;
    }

    private Map getFunction01(String functionNo, String taxnoStatus, String curOverFlag, String lastOverDate, String zoneCode, String errorMessage, String initMonth, String validType, String invSpec) {
        Map function = new HashMap();
        function.put("functionNo", functionNo);
        function.put("taxnoStatus", taxnoStatus);
        function.put("curOverFlag", curOverFlag);
        function.put("lastOverDate", lastOverDate);
        function.put("zoneCode", zoneCode);
        function.put("initMonth", initMonth);
        function.put("errorMessage", errorMessage);
        function.put("validType", validType);
        function.put("invSpec", invSpec);
        return function;
    }

    public String queryCollectTaxInfo(String uuidFlag, InvoiceFileReq invoiceFileReq, TkUserUrl userUrl) {
        String taxno = invoiceFileReq.getTaxno();
        log.info(uuidFlag + " taxno is " + taxno + " queryCollectTaxInfo is start ...");
        String result = null;
        try {
            String url = userUrl.getRequestUrl() + "/client/getTaxnoInfo.do?";
            String signStr = "AccessKeyID=%s&SignatureNonce=%s&TaxNo=%s&TimeStamp=%s&Version=1.0";

            String signatureNonce = UUIDGenerator.generate();
            String timeStamp = DateUtils.getDataString(DateUtils.yyyymmddthhmmssz);

            signStr = String.format(signStr, userUrl.getUsername(), signatureNonce, invoiceFileReq.getTaxno(), timeStamp);
            url += signStr + ("&Signature=" + getSign(signStr));

            log.info(uuidFlag + " taxno is " + taxno + " queryCollectTaxInfo request url:" + url);

            ResponseContent ret = HttpHelper.getUrlRespContent(url, 30000);
            log.info(uuidFlag + " taxno is " + taxno + " queryCollectTaxInfo request result:" + (ret == null ? "null" : ret.getContent()));
            if (ret != null) {
                result = ret.getContent();
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(uuidFlag + " taxno is " + taxno + " queryCollectTaxInfo is error!" + e.getMessage());
            return null;
        }
        log.info(uuidFlag + " taxno is " + taxno + " queryCollectTaxInfo is end ...");
        return result;
    }

    public String queryNumberCollectTaxInfo(String uuidFlag, InvoiceFileReq invoiceFileReq, TkUserUrl userUrl) {

        String taxno = invoiceFileReq.getTaxno();

        log.info(uuidFlag + " taxno is " + taxno + " queryNumberCollectTaxInfo is start ...");
        String result = null;
        try {
            String url = userUrl.getRequestUrl() + "/client/number/getNumberTaxnoInfo.do?";
            String signStr = "AccessKeyID=%s&SignatureNonce=%s&TaxNo=%s&TimeStamp=%s&Version=1.0";

            String signatureNonce = UUIDGenerator.generate();
            String timeStamp = DateUtils.getDataString(DateUtils.yyyymmddthhmmssz);

            signStr = String.format(signStr, userUrl.getUsername(), signatureNonce, invoiceFileReq.getTaxno(), timeStamp);
            url += signStr + ("&Signature=" + getSign(signStr));

            log.info(uuidFlag + " taxno is " + taxno + " queryNumberCollectTaxInfo request url:" + url);

            ResponseContent ret = HttpHelper.getUrlRespContent(url);
            log.info(uuidFlag + " taxno is " + taxno + " queryNumberCollectTaxInfo request result:" + (ret == null ? "null" : ret.getContent()));
            if (ret != null) {
                result = ret.getContent();
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(uuidFlag + " taxno is " + taxno + " is error!", e);
            return null;
        }

        log.info(uuidFlag + " taxno is " + taxno + " queryNumberCollectTaxInfo is end ...");
        return result;
    }

    /**
     * 税号管理
     *
     * @param invoiceFileReq
     * @return
     */
    @Override
    public JsonResult<String> taxManage(InvoiceFileTaxManageReq invoiceFileReq) {

        String uuidFlag = invoiceFileReq.getSignatureNonce();
        String userName = invoiceFileReq.getAccessKeyID();
        String taxno = invoiceFileReq.getTaxno();
        Date reqDate = DateUtils.getDate();
        log.info(uuidFlag + " taxno is " + taxno + " invoice user taxManage is start ," + invoiceFileReq.toString());

        //检测主参数
        List<InvoiceFileTaxManageFunctionReq> functionList = invoiceFileReq.getFunctionList();
        if (functionList == null || functionList.size() == 0) {
            log.info(uuidFlag + " taxno is " + taxno + " invoice user taxManage  functionList is null");
            return new JsonResult().errorResponse(ResultEnum.param_error);
        }
        if(StringUtil.isNotEmpty(invoiceFileReq.getZoneCode()) && !ZoneUtil.dqList.contains(invoiceFileReq.getZoneCode())) {
            log.info(uuidFlag + " taxno is " + taxno + " invoice user taxManage  zoneCode is error" + invoiceFileReq.getZoneCode());
            return new JsonResult().errorResponse(ResultEnum.zone_not_exist);
        }

        JsonResult result = new JsonResult();

        //04-token服务入库
        JSONObject resJson = saveTokenInfo(uuidFlag, invoiceFileReq);//调用内部服务1，插入token
        if(null == resJson || !resJson.getString("errorCode").equals("0")) {
            log.info(uuidFlag + " taxno is " + taxno + " invoice user taxManage  saveTokenInfo is error!");
            result.errorResponse(ResultEnum.system_error);
        } else {

            List<Map> functionResultList = new ArrayList();
            Map dataResult = new HashMap();
            dataResult.put("taxno", invoiceFileReq.getTaxno());

            for (InvoiceFileTaxManageFunctionReq function : functionList) {
                String functionNo = function.getFunctionNo();

                Map functionResult = new HashMap();
                functionResult.put("functionNo", functionNo);
                functionResult.put("optResult", "0");
                functionResult.put("optMessage", "操作成功");

                log.info(uuidFlag + " taxno is " + taxno + " invoice user taxManage function," + function.toString());

                //所有功能都需要验证部分
                if (!ObjectUtil.checkData(function.getOptType(), function.getFunctionNo()
                        , function.getValidType(), function.getBussinessType()
                        , function.getKeyType())) {
                    createViewInfo(functionResultList, functionResult, "-1", ResultEnum.param_error.getMessage());
                    continue;
                }
                if (!TkTaxUser.optTypeSet.contains(function.getOptType())) {
                    createViewInfo(functionResultList, functionResult, "-1", "optType操作类型不正确");
                    continue;
                }
                boolean userUrlFlag = tkUserUrlService.checkUserUrlExist(userName, functionNo);
                if (!userUrlFlag) {
                    createViewInfo(functionResultList, functionResult, "-1", "没有操作权限");
                    continue;
                }

                //1.校验
                if (TkUserUrl.FUNCTION_NO_INVOICE_DOWNLOAD.equals(function.getFunctionNo())) {
                    if(StringUtil.isEmpty(function.getInitMonth())) {
                        createViewInfo(functionResultList, functionResult, "-1", "initMonth不能为空");
                        continue;
                    }
                    if (StringUtil.isEmpty(function.getInvSpec())) {
                        createViewInfo(functionResultList, functionResult, "-1", "invSpec不能为空");
                        continue;
                    }
                    String initMonth = function.getInitMonth();
                    if (!CommonUtil.isInteger(initMonth)) {
                        createViewInfo(functionResultList, functionResult, "-1", "initMonth必须为数字");
                        continue;
                    }
                    int initMonthEnd = Integer.parseInt(initMonth);
                    if (!CommonUtil.isInteger(initMonth) || initMonthEnd>60) {
                        createViewInfo(functionResultList, functionResult, "-1", "initMonth超过60个月");
                        continue;
                    }
                }

                //04-token服务入库
                //移到外层

                //01-发票下载服务
                if (TkUserUrl.FUNCTION_NO_INVOICE_DOWNLOAD.equals(functionNo)) {//发票下载
                    boolean saveFlag = saveFunction01(uuidFlag, invoiceFileReq, functionResult, functionResultList, function);
                    if(!saveFlag) {
                        continue;
                    }
                } else if (TkUserUrl.FUNCTION_NO_INVOICE_COLLECT.equals(functionNo) || TkUserUrl.FUNCTION_NO_CLOUD_INVOICE_COLLECT.equals(functionNo)) {
                    // 实时认证，开通05勾选功能的同时开通勾选实时功能
                    TkUserUrl tkUser07Url = tkUserUrlService.getUserUrl(userName, TkUserUrl.FUNCTION_NO_CLOUD_INVOICE_REAL_COLLECT);
                    if (null != tkUser07Url && TkUserUrl.FUNCTION_NO_CLOUD_INVOICE_COLLECT.equals(functionNo)) {
                        logger.info("{} real verify for taxno:{} username:{}", uuidFlag, taxno, tkUser07Url.getUsername());
                        JSONObject addResult = addEnterprise(uuidFlag, tkUser07Url.getRequestUrl(), invoiceFileReq);
                        if (addResult != null) {
                            logger.info("{} add enterprise for taxno:{} response:{}", uuidFlag, taxno, addResult);
                        }
                    }
                    JSONObject taxInfoJson = callTaxInfo(uuidFlag, invoiceFileReq, function, tkUserUrlService.getUserUrl(userName, functionNo));//调用内部服务
                    if (null == taxInfoJson || !"0".equals(taxInfoJson.getString("CODE"))) {
                        String message = null==taxInfoJson?"未知异常":taxInfoJson.getString("MESSAGE");
                        createViewInfo(functionResultList, functionResult, "-1", message);
                        continue;
                    }
                } else if (TkUserUrl.FUNCTION_NO_INVOICE_NUMBER_COLLECT.equals(functionNo) || TkUserUrl.FUNCTION_NO_CLOUD_INVOICE_NUMBER_COLLECT.equals(functionNo)) {
                    JSONObject numberTaxInfoJson = callNumberTaxInfo(uuidFlag, invoiceFileReq, function, tkUserUrlService.getUserUrl(userName, functionNo));//调用内部服务
                    if (null == numberTaxInfoJson || !"0".equals(numberTaxInfoJson.getString("CODE"))) {
                        String message = null==numberTaxInfoJson?"未知异常":numberTaxInfoJson.getString("MESSAGE");
                        createViewInfo(functionResultList, functionResult, "-1", message);
                        continue;
                    }

                } else if (TkUserUrl.FUNCTION_NO_INVOICE_TOKEN.equals(functionNo)) {
                    //处理token数据
                } else {
                    createViewInfo(functionResultList, functionResult, "-1", "functionNo不正确");
                    continue;
                }
                functionResultList.add(functionResult);
            }

            dataResult.put("functionList", functionResultList);
            result.setData(dataResult);
        }
        fileUserLogService.saveLog(uuidFlag, userName, taxno, reqDate, invoiceFileReq.toString(), result.toString(), DateUtils.getDate(), "0");
        log.info(uuidFlag + " taxno is " + taxno + " invoicefile taxManage is end ," + result);
        return result;
    }

    public boolean saveFunction01(String uuidFlag, InvoiceFileTaxManageReq invoiceFileReq, Map functionResult, List<Map> functionResultList, InvoiceFileTaxManageFunctionReq function) {

        String optType = function.getOptType();
        String userName = invoiceFileReq.getAccessKeyID();

        TkTaxUserExample userExample = new TkTaxUserExample();
        userExample.createCriteria().andTaxnoEqualTo(invoiceFileReq.getTaxno())
                .andUserNameEqualTo(invoiceFileReq.getAccessKeyID());
        List<TkTaxUser> taxUsers = tkTaxUserService.selectByExample(userExample);

        if ("0".equals(optType)) {//增加
            if (taxUsers != null && taxUsers.size() > 0) {
                createViewInfo(functionResultList, functionResult, "-1", "此税号已注册");
                return false;
            }
            if (taxUsers == null || taxUsers.size() == 0) {
                TkTaxUser record = new TkTaxUser();
                record.setTaxno(invoiceFileReq.getTaxno());
                record.setUserName(invoiceFileReq.getAccessKeyID());
                if (invoiceFileReq.getAccessKeyID().equals("bwgf-limit")) {
                    record.setDelFlag("9");
                    record.setUserStatus("1");
                } else {
                    record.setDelFlag(getDelFlag(optType));
                    if ("2".equals(optType)) {
                        record.setUserStatus("5");
                    } else {
                        record.setUserStatus("3");
                    }
                }
                record.setZoneCode(invoiceFileReq.getZoneCode());
                record.setCreateDate(DateUtils.getDate());
                record.setInvSpec(function.getInvSpec());
                record.setIsOnce(function.getValidType());
                record.setInitMonth(Integer.parseInt(function.getInitMonth()));
                record.setKeyType(function.getKeyType());

                String resetDay = FileConstants.resetDay;
                TkUserUrl userUrl = tkUserUrlService.getUserUrl(userName, TkUserUrl.FUNCTION_NO_INVOICE_DOWNLOAD_DATE);
                if(null!=userUrl) {
                    resetDay = userUrl.getRequestUrl();
                }
                record.setResetDay(resetDay);
                tkTaxUserService.insertSelective(record);
            }
        } else if ("1".equals(optType) || "2".equals(optType)) {//开启或停用
            if (taxUsers == null || taxUsers.size() == 0) {
                createViewInfo(functionResultList, functionResult, "-1", "此税号未注册");
                return false;
            }

            if (taxUsers != null && taxUsers.size() > 0) {
                TkTaxUser record = taxUsers.get(0);
                boolean updFlag = false;
                if (record.getUserStatus().equals("4") || record.getUserStatus().equals("1")) {
                    //不允许修改
                } else {
                    record.setDelFlag(getDelFlag(optType));
                    if ("2".equals(optType)) {
                        record.setUserStatus("5");
                        updFlag = true;
                    } else {
                        if(!record.getUserStatus().equals("3")) {
                            record.setUserStatus("3");
                            record.setApplyStatus("1");
                            record.setDownStatus("1");
                            record.setOverFlag("0");
                            record.setInit("0");
                            record.setDelFlag("0");
                            updFlag = true;
                        }
                        if (StringUtils.isNotBlank(invoiceFileReq.getZoneCode())) {
                            record.setZoneCode(invoiceFileReq.getZoneCode());
                            updFlag = true;
                        }
                    }
                    if(!record.getIsOnce().equals(function.getValidType())) {
                        record.setIsOnce(function.getValidType());
                        updFlag = true;
                    }
                }

                if(updFlag) {
                    record.setUpdateDate(DateUtils.getDate());
                    tkTaxUserService.updateByPrimaryKey(record);
                    //刷新缓存
                    UserUtils.flushTaxUserBytaxno(record.getUserName(), record.getTaxno());
                }
            }
        }
        return true;
    }


    public String getDelFlag(String optType) {
        String delFlag = null;
        if ("0".equals(optType) || "1".equals(optType)) {
            delFlag = "0";
        } else if ("2".equals(optType)) {
            delFlag = "1";
        }
        return delFlag;
    }

    public JSONObject callTaxInfo(String uuidFlag, InvoiceFileTaxManageReq invoiceFileReq, InvoiceFileTaxManageFunctionReq function
            , TkUserUrl userUrl) {
        String requestUrl = userUrl.getRequestUrl() + "/client/optTaxnoInfo.do?";
        String signStr = "AccessKeyID=%s&SignatureNonce=%s&TaxNo=%s&TimeStamp=%s&Version=1.0";
        String signatureNonce = UUIDGenerator.generate();
        String timeStamp = DateUtils.getDataString(DateUtils.yyyymmddthhmmssz);
        signStr = String.format(signStr, userUrl.getUsername(), signatureNonce, invoiceFileReq.getTaxno(), timeStamp);
        requestUrl += signStr + ("&Signature=" + getSign(signStr));

        String taxno = invoiceFileReq.getTaxno();
        JSONObject json = new JSONObject();
        json.put("taxno", invoiceFileReq.getTaxno());
        json.put("zoneCode", invoiceFileReq.getZoneCode());
        json.put("optType", function.getOptType());
        json.put("validType", function.getValidType());
        json.put("bussinessType", function.getBussinessType());
        json.put("keyType", function.getKeyType());
        json.put("initMonth", function.getInitMonth());

        log.info(uuidFlag + " taxno is " + taxno + " callTaxInfo request url:" + requestUrl + ",param:" + json.toJSONString());

        JSONObject resultJson = null;
        try {
            ResponseContent ret = HttpHelper.postJsonEntity(requestUrl, json.toString());
            resultJson = JSONObject.parseObject(ret.getContent());
        } catch (Exception e) {
            e.printStackTrace();
            log.info(uuidFlag + " taxno is " + taxno + " callTaxInfo is error! ", e);
        }
        log.info(uuidFlag + " taxno is " + taxno + " callTaxInfo request result:" + (resultJson == null ? "null" : resultJson.toJSONString()));
        return resultJson;
    }

    public JSONObject callNumberTaxInfo(String uuidFlag, InvoiceFileTaxManageReq invoiceFileReq, InvoiceFileTaxManageFunctionReq function
            , TkUserUrl userUrl) {
        String requestUrl = userUrl.getRequestUrl() + "/client/number/optNumberTaxnoInfo.do?";
        String signStr = "AccessKeyID=%s&SignatureNonce=%s&TaxNo=%s&TimeStamp=%s&Version=1.0";
        String signatureNonce = UUIDGenerator.generate();
        String timeStamp = DateUtils.getDataString(DateUtils.yyyymmddthhmmssz);
        signStr = String.format(signStr, userUrl.getUsername(), signatureNonce, invoiceFileReq.getTaxno(), timeStamp);
        requestUrl += signStr + ("&Signature=" + getSign(signStr));

        String taxno = invoiceFileReq.getTaxno();
        JSONObject json = new JSONObject();
        json.put("taxno", invoiceFileReq.getTaxno());
        json.put("zoneCode", invoiceFileReq.getZoneCode());
        json.put("optType", function.getOptType());
        json.put("validType", function.getValidType());
        json.put("bussinessType", function.getBussinessType());
        json.put("keyType", function.getKeyType());
        json.put("invSpec", function.getInvSpec());
        json.put("initMonth", function.getInitMonth());

        log.info(uuidFlag + " taxno is " + taxno + " callNumberTaxInfo request url:" + requestUrl + ",param:" + json.toJSONString());
        JSONObject resultJson = null;
        try {
            ResponseContent ret = HttpHelper.postJsonEntity(requestUrl, json.toString());
            resultJson = JSONObject.parseObject(ret.getContent());
        } catch (Exception e) {
            e.printStackTrace();
            log.info(uuidFlag + " taxno is " + taxno + " callNumberTaxInfo is error! ", e);
        }
        log.info(uuidFlag + " taxno is " + taxno + " callNumberTaxInfo request result:" + (resultJson == null ? "null" : resultJson.toJSONString()));
        return resultJson;
    }

    public JSONObject callTax(String uuidFlag, InvoiceFileReq invoiceFileReq) {
        String requestUrl = FileConstants.taxInitHUrl + "?";
        String signStr = "AccessKeyID=%s&SignatureNonce=%s&TaxNo=%s&TimeStamp=%s&Version=1.0";
        String signatureNonce = UUIDGenerator.generate();
        String timeStamp = DateUtils.getDataString(DateUtils.yyyymmddthhmmssz);
        signStr = String.format(signStr, invoiceFileReq.getAccessKeyID(), signatureNonce, invoiceFileReq.getTaxno(), timeStamp);
        requestUrl += signStr + ("&Signature=" + getSign(signStr));

        String taxno = invoiceFileReq.getTaxno();
        JSONObject json = new JSONObject();
        json.put("taxno", invoiceFileReq.getTaxno());
        json.put("zoneCode", invoiceFileReq.getZoneCode());
        json.put("optType", invoiceFileReq.getOptType());

        log.info(uuidFlag + " taxno is " + taxno + " callTax request url:" + requestUrl + ",param:" + json.toJSONString());
        JSONObject resultJson = null;
        try {
            ResponseContent ret = HttpHelper.postJsonEntity(requestUrl, json.toString());
            resultJson = JSONObject.parseObject(ret.getContent());
        } catch (Exception e) {
            e.printStackTrace();
            log.info(uuidFlag + " taxno is " + taxno + " callTax is error! ", e);
        }
        log.info(uuidFlag + " taxno is " + taxno + " callTax request result:" + (resultJson == null ? "null" : resultJson.toJSONString()));

        return resultJson;
    }

    public JSONObject saveTokenInfo(String uuidFlag, InvoiceFileTaxManageReq invoiceFileReq) {
        String taxno = invoiceFileReq.getTaxno();

        JSONObject json = new JSONObject();
        json.put("taxno", invoiceFileReq.getTaxno());
        json.put("zoneCode", invoiceFileReq.getZoneCode());
        json.put("userCode", invoiceFileReq.getAccessKeyID());
        json.put("serverNo", CommonUtil.getServerNo());
        json.put("secert", invoiceFileReq.getSecert());
        json.put("taxUserInfo", invoiceFileReq.getUserInfoJson());
        json.put("userType", invoiceFileReq.getUserType());
        json.put("isValid", invoiceFileReq.getUserStatus());

        log.info(uuidFlag + " taxno is " + taxno + "saveTokenInfo request url:" + FileConstants.taxInitUrl + ",param:" + json.toJSONString());

        JSONObject resultJson = null;
        ResponseContent ret = HttpHelper.postJsonEntity(FileConstants.taxInitUrl, json.toString());
        try {
            resultJson = JSONObject.parseObject(ret.getContent());
        } catch (Exception e) {
            e.printStackTrace();
            log.info(uuidFlag + " taxno is " + taxno + " saveTokenInfo is error! ", e);
        }
        log.info(uuidFlag + " taxno is " + taxno + "saveTokenInfo request result:" + (resultJson == null ? "null" : resultJson.toJSONString()));
        return resultJson;
    }

    public JSONObject callWh(InvoiceFileReq invoiceFileReq, FileServer server) {
        JSONObject json = new JSONObject();
        json.put("taxno", invoiceFileReq.getTaxno());
        json.put("zoneCode", invoiceFileReq.getZoneCode());
        json.put("userCode", server.getUsername());
        json.put("serverNo", FileConstants.taxInitServerNo);

        log.info("callWh request url:" + FileConstants.taxInitUrl + ",param:" + json.toJSONString());

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        HttpEntity<Object> entity = new HttpEntity<Object>(json, headers);
        JSONObject resultJson = restTemplate.postForObject(FileConstants.taxInitUrl, entity, JSONObject.class);
        log.info("callWh request result:" + (resultJson == null ? "null" : resultJson.toJSONString()));
        return resultJson;
    }

    public JSONObject addEnterprise(String uuidFlag, String url, InvoiceFileTaxManageReq invoiceFileReq) {
        JSONObject resultJson = null;
        try {
            url = url + "/client/manageCompany.do";
            JSONObject json = new JSONObject();
            json.put("taxno", invoiceFileReq.getTaxno());
            json.put("taxname", invoiceFileReq.getTaxno());
            log.info("{} request url:{},param:{}", uuidFlag, url, json.toJSONString());

            Map<String, Object> paramsMap = Maps.newHashMap();
            paramsMap.put("data", json.toJSONString());
            paramsMap.put("username", invoiceFileReq.getAccessKeyID());
            paramsMap.put("rtype", "9001");
            paramsMap.put("timestamp", DateUtils.getDataString(DateUtils.yyyymmddhhmmss));
            paramsMap.put("sign", "test");

            ResponseContent ret = HttpHelper.postEntity(url, paramsMap);
            resultJson = JSONObject.parseObject(ret.getContent());
            log.info(uuidFlag + " addEnterprise request result:" + (resultJson == null ? "null" : resultJson.toJSONString()));
        } catch (Exception e) {
            logger.error("{} add enterprise error:", uuidFlag, e);
        }
        return resultJson;
    }

    public JSONObject queryTokenInfo(String uuidFlag, InvoiceFileReq invoiceFileReq) {
        JSONObject json = new JSONObject();

        String taxno = invoiceFileReq.getTaxno();
        json.put("taxno", invoiceFileReq.getTaxno());
        json.put("userCode", invoiceFileReq.getAccessKeyID());

        log.info(uuidFlag + " taxno is " + taxno + " queryTokenInfo request url:" + FileConstants.taxQueryUrl + ",param:" + json.toJSONString());

        JSONObject resultJson = null;
        try {
            ResponseContent ret = HttpHelper.postJsonEntity(FileConstants.taxQueryUrl, json.toString());
            resultJson = JSONObject.parseObject(ret.getContent());
        } catch (Exception e) {
            e.printStackTrace();
            log.info(uuidFlag + " taxno is " + taxno + " queryTokenInfo is error! " + e);
        }
        log.info(uuidFlag + " taxno is " + taxno + " queryTokenInfo request result:" + (resultJson == null ? "null" : resultJson.toJSONString()));
        return resultJson;
    }

    public static String getSign(String data) {
        try {
            return "test";//内部调用，不延签
            //return Security.getSignature(data.getBytes("UTF-8"),accessKeySecret.getBytes("UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public boolean isExsitExpNameList(String expName) {
        if (redisService.exists(expName)) {
            return true;
        } else {
            return false;
        }
    }

    public void delExpNameList(String expName) {
        if (isExsitExpNameList(expName)) {
            redisService.del(expName);
        }
    }


    public JsonResult<String> flushExpCacheByTaxno(String uuidFlag, InvoiceFileReq invoiceFileReq) {
        JsonResult jsonResult = new JsonResult();
        String userName = invoiceFileReq.getAccessKeyID();
        String taxno = invoiceFileReq.getTaxno();
        TkTaxUser taxUser = tkTaxUserService.queryTaxUser(userName, taxno);
        List<Map<String, Object>> tkFileCountList = tkFileService.countWaitDownFileList(taxUser);
        Set statusSet = Sets.newHashSet();
        int downNum = 0;
        for(Map<String, Object> tkFileCountMap:tkFileCountList) {
            if("0".equals(tkFileCountMap.get("response_status"))) {
                downNum += (long)tkFileCountMap.get("down_num");
                statusSet.add(tkFileCountMap.get("response_status"));
            }
        }
        if(statusSet.contains("0")) {
            setExpNameList(userName, taxno, HttpRedisContants.COLLECT_LIST_TYPE_FILE);
        }
        jsonResult.setData(taxno + "=" + downNum);
        logger.info(uuidFlag + " taxno " + taxno + ",downNum:" + downNum);
        return jsonResult;
    }


    public void setExpNameList(String userName, String taxno, String dataType) {
        String expName = HttpRedisContants.getInvoiceExpListGroupName(userName, taxno, dataType);
        redisService.set(expName, DateUtils.getDataString(DateUtils.yyyymmddhhmmss), 60 * 60 * 24 * 60);
    }


    @Override
    public JsonResult<Map> handApplyFile(String uuidFlag, TkTaxUser taxUser, ApplyFileReq applyFileReq) {
        JsonResult jsonResult = new JsonResult();
        Date curDate = DateUtils.getDate();
        String curMonth = DateUtils.getDataString(new SimpleDateFormat("yyyyMM"));

        List<String> monthList = getMonthList(curMonth, Integer.parseInt(FileConstants.downLoadMaxMonth));
        List<ApplyFileReqModel> applyInfoList = applyFileReq.getApplyInfoList();

        int rightNum = 0;
        for(ApplyFileReqModel applyInfo:applyInfoList) {
            if(StringUtil.isEmpty(applyInfo.getTaxno())) {
                applyInfo.setTaxno(taxUser.getTaxno());
            }
            String fileMonth = applyInfo.getFileMonth();
            if(!FileDownloadUtil.checkInvSpec(applyInfo.getInvSpec())) {
                applyInfo.setErrorCode("1");
                applyInfo.setErrorMessage("进销项参数不正确");
            } else if(!FileDownloadUtil.checkForceFlag(applyInfo.getForceApplyFlag())) {
                applyInfo.setErrorCode("1");
                applyInfo.setErrorMessage("强制申请参数不正确");
            } else if(!FileDownloadUtil.checkInvType(applyInfo.getInvSpec(), applyInfo.getInvType())) {
                applyInfo.setErrorCode("1");
                applyInfo.setErrorMessage("发票类型参数不正确");
            } else if(!monthList.contains(fileMonth)) {
                applyInfo.setErrorCode("1");
                applyInfo.setErrorMessage("申请月份超过最大范围");
            } else {
                String applyDateStartStr = DateUtils.getMonthFirstByStr(fileMonth);
                String applyDateEndStr = DateUtils.getMonthLastByStr(fileMonth);
                if(fileMonth.equals(curMonth)) {
                    Date endDate = DateUtils.getPreDateCurMonth(curDate, FileConstants.applyCycle);
                    applyDateEndStr = DateUtils.date2Str(endDate, new SimpleDateFormat("yyyy-MM-dd"));
                }
                applyInfo.setApplyDateStart(applyDateStartStr);
                applyInfo.setApplyDateEnd(applyDateEndStr);
                rightNum++;
            }
        }
        tkFileService.saveHandApplyFileList(uuidFlag, taxUser, applyInfoList);
        fileApplyLogServiceImpl.saveLog(uuidFlag, taxUser.getUserName(), taxUser.getZoneCode(), applyInfoList);
        jsonResult.setData(applyInfoList);
        return jsonResult;
    }

    @Override
    public JsonResult<Map> handApplyMonthFile(String uuidFlag, TkTaxUser taxUser, ApplyMonthFileReq applyMonthFileReq) {
        JsonResult jsonResult = new JsonResult();
        String curMonth = DateUtils.getDataString(new SimpleDateFormat("yyyyMM"));

        List<String> monthList = getMonthList(curMonth, Integer.parseInt(FileConstants.downLoadMaxMonth));
        if(!FileDownloadUtil.checkAllInvSpec(applyMonthFileReq.getInvSpec())) {
            jsonResult.setErrorCode(ResultEnum.fail.getCode());
            jsonResult.setMessage("进销项参数不正确");
        } else if(!FileDownloadUtil.checkForceFlag(applyMonthFileReq.getForceApplyFlag())) {
            jsonResult.setErrorCode(ResultEnum.fail.getCode());
            jsonResult.setMessage("强制申请参数不正确");
        } else if(!monthList.contains(applyMonthFileReq.getFileMonth())) {
            jsonResult.setErrorCode(ResultEnum.fail.getCode());
            jsonResult.setMessage("申请月份超过最大范围");
        } else {
            ApplyFileReq applyFileReq = new ApplyFileReq();
            List<ApplyFileReqModel> applyInfoList = Lists.newArrayList();

            Set<String> invSpecList = Sets.newConcurrentHashSet();
            if(applyMonthFileReq.getInvSpec().equals("0")) {
                invSpecList.addAll(FileDownloadUtil.gxDic.keySet());
            } else {
                invSpecList.add(applyMonthFileReq.getInvSpec());
            }

            for(String invSpec:invSpecList) {
                Map<String, String> invTypeMap = null;
                if (invSpec.equals(FileDownloadUtil.INVTYPE_INCOME)) {
                    invTypeMap = FileDownloadUtil.invTypeDicG;
                } else {
                    invTypeMap = FileDownloadUtil.invTypeDicX;
                }
                for (String invType : invTypeMap.keySet()) {
                    ApplyFileReqModel reqModel = new ApplyFileReqModel();
                    reqModel.setInvSpec(invSpec);
                    reqModel.setInvType(invType);
                    reqModel.setForceApplyFlag(applyMonthFileReq.getForceApplyFlag());
                    reqModel.setFileMonth(applyMonthFileReq.getFileMonth());
                    applyInfoList.add(reqModel);
                }
            }
            applyFileReq.setApplyInfoList(applyInfoList);
            JsonResult<Map> applyJsonResult = handApplyFile(uuidFlag, taxUser, applyFileReq);
            jsonResult.setData(applyJsonResult.getData());
        }
        return jsonResult;
    }

    @Override
    public JsonResult<Map> queryErrorFileList(String uuidFlag, TkTaxUser taxUser, QueryFileReqModel applyInfo) {
        JsonResult jsonResult = new JsonResult();
        String curMonth = DateUtils.getDataString(new SimpleDateFormat("yyyyMM"));
        String taskno = UUIDGenerator.generate();
        List<String> monthList = getMonthList(curMonth, Integer.parseInt(FileConstants.downLoadMaxMonth));
        String fileMonth = applyInfo.getFileMonth();

        if(!monthList.contains(fileMonth)) {
            jsonResult.setErrorCode("1");
            jsonResult.setMessage("查询月份超过最大范围");
        } else {
            List<TkFile> fileList = tkFileService.queryErrorFileList(taxUser, fileMonth);
            jsonResult.setData(createErrorResponseJson(taskno, fileList));
        }
        return jsonResult;
    }

    @Override
    public JsonResult<String> batchTaxManage(InvoiceFileTaxBatchManageReq invoiceFileTaxBatchManageReq) {
        JsonResult jsonResult = new JsonResult();
        List<TokenInfo> errorTokenList = tokenClient.selectTokenListByErrorCode(invoiceFileTaxBatchManageReq.getUserCode(),
                invoiceFileTaxBatchManageReq.getErrorCode(), invoiceFileTaxBatchManageReq.getZoneCode());

        int rightNum = 0;
        for(TokenInfo errorToken:errorTokenList) {
            List<InvoiceFileTaxManageFunctionReq> functionList = Lists.newArrayList();
            functionList.add(new InvoiceFileTaxManageFunctionReq("1","05"));

            String uuidFlag = UUIDGenerator.generate();
            InvoiceFileTaxManageReq invoiceFileReq = new InvoiceFileTaxManageReq();
            invoiceFileReq.setTaxno(errorToken.getTaxno());
            invoiceFileReq.setZoneCode(errorToken.getZoneCode());
            invoiceFileReq.setFunctionList(functionList);
            invoiceFileReq.setAccessKeyID(errorToken.getUserCode());
            invoiceFileReq.setSignatureNonce(uuidFlag);

            JsonResult<String> manageResult = taxManage(invoiceFileReq);
            log.info(uuidFlag + " batchTaxManage " + manageResult);
            if(manageResult.isSuccess()) {
                rightNum++;
            }
        }
        jsonResult.setData(errorTokenList.size() + "=" + rightNum);
        return jsonResult;
    }


    public Map createErrorResponseJson(String taskno, List<TkFile> invFileList) {
        Map result = new HashMap();
        List<InvoiceErrorFileRes> invoiceFiles = getFileErrorModel(invFileList);
        int quantity = invoiceFiles.size();
        result.put("taskno", taskno);
        result.put("quantity", quantity);
        result.put("invoiceFileList", invoiceFiles);
        return result;
    }

    //模型转换
    private List<InvoiceErrorFileRes> getFileErrorModel(List<TkFile> tkFiles) {
        List<InvoiceErrorFileRes> invoiceFiles = new ArrayList<InvoiceErrorFileRes>();
        if (tkFiles != null && tkFiles.size() > 0) {
            Iterator<TkFile> iter = tkFiles.iterator();
            while (iter.hasNext()) {
                TkFile tkFile = iter.next();
                InvoiceErrorFileRes iFile = new InvoiceErrorFileRes();
                iFile.setInvSpec(tkFile.getInvSpec());
                iFile.setInvType(tkFile.getInvType());
                iFile.setTaxno(tkFile.getTaxno());
                iFile.setErrorReason(StringUtils.defaultIfEmpty(tkFile.getFileName(), "处理中"));
                iFile.setPreApplyDate(tkFile.getOldApplyDate() != null ? new SimpleDateFormat("yyyy-MM-dd").format(tkFile.getOldApplyDate()) : "");
                iFile.setInvDateStart(tkFile.getInvDateStart() != null ? new SimpleDateFormat("yyyy-MM-dd").format(tkFile.getInvDateStart()) : "");
                iFile.setInvDateEnd(tkFile.getInvDateEnd() != null ? new SimpleDateFormat("yyyy-MM-dd").format(tkFile.getInvDateEnd()) : "");
                invoiceFiles.add(iFile);
            }
        }
        return invoiceFiles;
    }

    private List<String> getMonthList(String curMonth, int moveValue) {
        List<String> monthList = Lists.newArrayList();
        for(int i=0;i<=moveValue;i++) {
            String yearMonth = DateUtils.getPastMonth(curMonth, -i);
            monthList.add(yearMonth);
        }
        return monthList;
    }

    private void createViewInfo(List<Map> functionResultList, Map functionResult, String optResult, String optMessage) {
        functionResult.put("optResult", optResult);
        functionResult.put("optMessage", optMessage);
        functionResultList.add(functionResult);
    }
}