package com.xxfc.platform.universal.service.invoice.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.google.common.collect.Lists;
import com.xxfc.platform.universal.entity.Invoice;
import com.xxfc.platform.universal.entity.OrderData;
import com.xxfc.platform.universal.service.invoice.InvoiceDao;
import lombok.extern.slf4j.Slf4j;
import nuonuo.open.sdk.NNOpenSDK;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: Administrator
 * @Date: 2019/12/31 10:26
 * @Description:
 */
@Service
@Primary
@Slf4j
public class InvoiceDaoImpl implements InvoiceDao {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 诺诺-极速开票
     */
    @Value("${invoice.nuonuo.js.taxnum}")
    private String taxnum;
    @Value("${invoice.nuonuo.js.appKey}")
    private String appKey;
    @Value("${invoice.nuonuo.js.appSecret}")
    private String appSecret;

    /**
     * 诺诺-诺诺发票
     */
    @Value("${invoice.nuonuo.nn.taxnum}")
    private String taxnum2;
    @Value("${invoice.nuonuo.nn.appKey}")
    private String appKey2;
    @Value("${invoice.nuonuo.nn.appSecret}")
    private String appSecret2;

    @Value("${invoice.nuonuo.queryUrl}")
    private String queryUrl ;
    @Value("${invoice.nuonuo.invoiceUrl}")
    private String invoiceUrl ;




    /**
     * 给定的部分名,获取税号
     *
     * @param name
     * @return
     */
    @Override
    public List<Map<String, String>> corporateName(String name) {
        NNOpenSDK sdk = NNOpenSDK.getIntance();
        HashMap<String, String> map = new HashMap();
        map.put("q", name);
        String content = JSON.toJSONString(map);

        //方法名
        String method = "nuonuo.speedBilling.prefixQuery";
        // SDK请求地址
        String url = "https://sdk.nuonuo.com/open/v1/services";
        // 唯一标识，由企业自己生成32位随机码
        String senid = UUID.randomUUID().toString().replace("-", "");
        String result = sdk.sendPostSyncRequest(url, senid, appKey, appSecret, getTokenJS(), taxnum, method, content);
        JSONObject jsonObject = JSON.parseObject(result);
        List<Map<String, String>> mapList = (List<Map<String, String>>) jsonObject.get("result");
        if (CollectionUtil.isNotEmpty(mapList)) {
            return mapList;
        }
        return new ArrayList<>();
    }

    /**
     * 根据开票代码,调用第三方接口获取税号
     *
     * @param code
     * @return
     */
    @Override
    public String getDutyParagraphByCode(String code) {
        NNOpenSDK sdk = NNOpenSDK.getIntance();
        // API方法名
        String method = "nuonuo.speedBilling.queryNameAndTaxByCode";
        // SDK请求地址
        String url = "https://sdk.jss.com.cn/open/v1/services";

        HashMap<String, String> map = new HashMap();
        map.put("code", code);
        String content = JSON.toJSONString(map);
        // 唯一标识，由企业自己生成32位随机码
        String senid = UUID.randomUUID().toString().replace("-", "");
        String result = sdk.sendPostSyncRequest(url, senid, appKey, appSecret, getTokenJS(), taxnum, method, content);
        JSONObject jsonObject = JSON.parseObject(result);
        Map<String, String> resultMap = (Map<String, String>) jsonObject.get("result");
        return resultMap.get("kpCode");
    }


    /**
     * 调用第三方开票接口进行开票
     * @param invoice
     * @param orders
     * @return
     */
    @Override
    public String Invoicing(Invoice invoice, List<OrderData> orders) {

        NNOpenSDK sdk = NNOpenSDK.getIntance();
        // API方法名
        String method = "nuonuo.electronInvoice.requestBilling";
        String senid = UUID.randomUUID().toString().replace("-", "");
        HashMap<String, Object> map = new HashMap<>();
        HashMap<String, Map<String, Object>> orderMap = new HashMap<>();
        orderMap.put("order", map);
        //购方信息
        map.put("buyerName", invoice.getPurchaserName());
        map.put("buyerTaxNum", invoice.getPurchaserTaxCode());
//        map.put("buyerTel", invoice.getPurchaserPhone());
        map.put("buyerAddress", invoice.getPurchaserAddressPhone());
        map.put("buyerAccount", invoice.getPurchaserAccountBank());
        map.put("buyerPhone", invoice.getPurchaserPhone());
        map.put("email", invoice.getPurchaserEmail());
        map.put("remark", invoice.getRemark());
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //销方信息
        map.put("orderNo", invoice.getOrderNo());
        map.put("invoiceDate", dateFormat.format(invoice.getInvoiceDate()));
        map.put("salerName", invoice.getSalerName());
        map.put("salerTaxNum", invoice.getSalerTaxCode());
        map.put("salerTel", invoice.getSalerPhone());
        map.put("salerAddress", invoice.getSalerAddress());
        map.put("salerAccount", invoice.getSalerAccountBank());
        map.put("clerk", invoice.getIssuer());
        map.put("payee", invoice.getPayee());
        map.put("checker", invoice.getReviewer());

        //其他设置
        map.put("pushMode", String.valueOf(invoice.getPushMode()));
        map.put("invoiceType", String.valueOf(invoice.getInvoiceType()));


        //订单信息
        ArrayList<Map<String, String>> arrayList = Lists.newArrayList();
        map.put("invoiceDetail", arrayList);
        for (OrderData order : orders) {
            HashMap<String, String> mx = new HashMap<>();
            mx.put("goodsName", invoice.getContent());
            mx.put("num", String.valueOf(order.getNum()));
            //单价含税标志，0:不含税,1:含税
            mx.put("withTaxFlag", String.valueOf(order.getWithTaxFlag()));
            mx.put("price", String.valueOf(order.getPrice()));
            mx.put("taxRate", String.valueOf(order.getTaxRate()));
            mx.put("unit", order.getUnit());
            mx.put("specType", order.getOrderName());
            arrayList.add(mx);
        }
        String token = getTokenFP();
        String jsonString = JSON.toJSONString(orderMap);
        //调用第三方接口
        String result = sdk.sendPostSyncRequest(invoiceUrl, senid, appKey2, appSecret2, token, taxnum2, method, jsonString);
        log.info("result={}", result);
        //把字符串json数据转换为map
        JSONObject jsonObject = JSON.parseObject(result);
        Map<String, String> data = (Map<String, String>) jsonObject.get("result");
        String invoiceSerialNum = data.get("invoiceSerialNum");
        if (StringUtils.isBlank(invoiceSerialNum)) {
            log.error("失败原因={}", result);
            throw new BaseException("开票失败");
        }
        return invoiceSerialNum;
    }

    @Override
    public List<Map<String, Object>> invoiceResult(String invoiceSerialNum) {
        NNOpenSDK sdk = NNOpenSDK.getIntance();
        // API方法名
        String method = "nuonuo.electronInvoice.CheckEInvoice";
        HashMap<String, List<String>> map = new HashMap<>();
        ArrayList<String> arrayList = Lists.newArrayList();
        arrayList.add(invoiceSerialNum);
        map.put("invoiceSerialNum", arrayList);
        String content = JSON.toJSONString(map);
        // 唯一标识，由企业自己生成32位随机码
        String senid = UUID.randomUUID().toString().replace("-", "");

        String data = null;
        try {
            data = sdk.sendPostSyncRequest(queryUrl, senid, appKey2, appSecret2, getTokenFP(), taxnum2, method, content);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (data!=null){
            try {
                JSONObject jsonObject = JSON.parseObject(data);
                List<Map<String, Object>> mapList = (List<Map<String, Object>>) jsonObject.get("result");
                return mapList;
            } catch (Exception e) {
                throw new BaseException("发票请求流水号错误");
            }
        }
      return null;
    }


    /**
     * 获取极速开票token
     */
    private String getTokenJS() {
        return getToken(appKey, appSecret);
    }


    /**
     * 获取诺诺发票token
     */
    public String getTokenFP() {
        return getToken(appKey2, appSecret2);
    }


    private String getToken(String appKey, String appSecret) {
        String token = (String) redisTemplate.opsForValue().get(appKey);
        if (StringUtils.isBlank(token)) {
            String json = NNOpenSDK.getIntance().getMerchantToken(appKey, appSecret);
            log.info("token={}", json);
            JSONObject jsonObject = JSONObject.parseObject(json);
            token = (String) jsonObject.get("access_token");
            if (StringUtils.isBlank(token)) {
                throw new BaseException("获取极速开票token失败");
            }
            redisTemplate.opsForValue().set(appKey, token, 23, TimeUnit.HOURS);
        }
        return token;

    }


}
