package com.ningdatech.pmapi.provincial.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.ningdatech.irs.contants.IrsContant;
import com.ningdatech.irs.service.IRefreshTokenService;
import com.ningdatech.pmapi.common.config.ProvincialProperties;
import com.ningdatech.pmapi.common.constant.BizConst;
import com.ningdatech.pmapi.common.util.HttpUtil;
import com.ningdatech.pmapi.organization.model.vo.ProvincialGovBusinessStripVO;
import com.ningdatech.pmapi.provincial.model.dto.ProvinceApiResponse;
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO;
import com.ningdatech.pmapi.provincial.model.res.SjApiResponse;
import com.ningdatech.pmapi.provincial.service.IJoinReviewProvincialBureauService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Classname JointReviewProvincialBureauService
 * @Description 省局联审接口
 * @Date 2023/3/2 9:29
 * @Author PoffyZhang
 */
@Service
@Slf4j
public class JoinReviewProvincialBureauServiceImpl implements IJoinReviewProvincialBureauService {

    @Autowired
    private ProvincialProperties provincialProperties;

    @Autowired
    private RestTemplate restTemplate;

    @Resource(name = "refreshToken")
    private IRefreshTokenService refreshTokenService;

    @Value("${irs.interface-refresh.request-token-url}")
    private String govRequestTokenUrl;
    @Value("${irs.interface-refresh.refresh-token-url}")
    private String govRefreshTokenUrl;

    @Value("${irs.province-gov.url}")
    private String govUrl;

    @Value("${irs.province-gov.appSecret}")
    private String govAppSecret;

    @Value("${irs.province-gov.appKey}")
    private String govAppKey;

    @Value("${irs.province-gov.interfaceName}")
    private String interfaceName;

    /**
     * 推送/保存 重大接口到 省局联审
     * @return
     */
    @Override
    public Boolean pushImportProject(ProvincialProjectDTO project){
        Long timeStamp = System.currentTimeMillis()/1000;
        String url = provincialProperties.getHost() + provincialProperties.getPushUrl()
                + "?timestamp=" + timeStamp;
        log.info("省局推送联审url {}",url);
        ResponseEntity<ProvinceApiResponse> responseEntity = null;

        String signature = getSha256(timeStamp,provincialProperties.getPushUrl(),
                HttpMethod.POST.name(),provincialProperties.getKey(),provincialProperties.getSecret());

        //发送post请求
        RequestEntity<ProvincialProjectDTO> requestEntity = RequestEntity
                .post(url)
                .header("Accept", MediaType.APPLICATION_JSON.toString())
                .header("X-Hmac-Auth-Key",provincialProperties.getKey())
                .header("X-Hmac-Auth-Signature",signature)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)
                .body(project);

        log.info("省局联审 提交 :{}", requestEntity);
        log.info("省局联审 提交body :{}", JSON.toJSONString(requestEntity.getBody()));
        try {
            responseEntity = restTemplate.exchange(requestEntity, ProvinceApiResponse.class);
            log.info("省局联审 响应 :{}",responseEntity);
            if(responseEntity.getBody().getCode().equals(200)){
                return Boolean.TRUE;
            }
        } catch (Exception e) {
            log.error("[省局联审] http request error", e);
        }

        return Boolean.FALSE;
    }

    /**
     * 获取流程审批详情
     * @param projectId
     * @return
     */
    @Override
    public SjApiResponse processInfo(String projectId) {
        Long timeStamp = System.currentTimeMillis()/1000;
        String url = provincialProperties.getHost() + provincialProperties.getDetailUrl()
                + "?timestamp=" + timeStamp;

        log.info("省局获取审核详情 url {}",url);
        ResponseEntity<SjApiResponse> responseEntity = null;

        String signature = getSha256(timeStamp,provincialProperties.getDetailUrl(),
                HttpMethod.POST.name(),provincialProperties.getKey(),provincialProperties.getSecret());

        JSONObject jsonBaby = new JSONObject();
        jsonBaby.put("projectId",projectId);
        //发送post请求
        RequestEntity<JSONObject> requestEntity = RequestEntity
                .post(url)
                .header("Accept", MediaType.APPLICATION_JSON.toString())
                .header("X-Hmac-Auth-Key",provincialProperties.getKey())
                .header("X-Hmac-Auth-Signature",signature)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)
                .body(jsonBaby); //也可以是DTO

        try {
            responseEntity = restTemplate.exchange(requestEntity,SjApiResponse.class);
            log.info("获取审批详情 响应 :{}",responseEntity);
        } catch (Exception e) {
            log.error("[省局获取审核详情] http request error", e);
        }

        return responseEntity.getBody();
    }

    @Override
    public List<ProvincialGovBusinessStripVO> searchGovUnits() {
        Long timeStamp = System.currentTimeMillis();
        String appSecret = govAppSecret;
        String appKey = govAppKey;
        String method = HttpMethod.POST.name();
        String secret = refreshTokenService.refreshToken(appKey,appSecret,govRequestTokenUrl,govRefreshTokenUrl,interfaceName,method);
        String sign = MD5.create().digestHex(appKey + secret + timeStamp);
        HttpComponentsClientHttpRequestFactory factory = HttpUtil.generateHttpRequestFactory();
        RestTemplate restTemplate;
        if(Objects.nonNull(factory)){
            restTemplate = new RestTemplate(factory);
        }else{
            restTemplate = new RestTemplate();
        }

        String authSignature = getSha256(timeStamp/1000,provincialProperties.getDomainUrl(), HttpMethod.POST.name(),
                provincialProperties.getKey(),provincialProperties.getSecret());
        String url = govUrl + "?appKey=" + appKey +
                "&timestamp=" + timeStamp/1000 + "&sign=" + sign +
                "&authKey=" + provincialProperties.getKey() + "&authSignature=" + authSignature +
                "&requestTime=" + timeStamp;
        log.info("gov search url :{}",url);
        ResponseEntity<JSONObject> forEntity = restTemplate.postForEntity(url,null, JSONObject.class, Maps.newHashMap());
        JSONObject body = forEntity.getBody();
        log.info("seach response :{}",body);
        if(Objects.isNull(body)){
            return Collections.emptyList();
        }
        String code = body.getString(IrsContant.RefreshToken.RESPONSE_KEY_CODE);
        if(IrsContant.RefreshToken.SUCESS_CODE.equals(code)){
            JSONObject datas = body.getJSONObject(IrsContant.RefreshToken.RESPONSE_KEY_DATAS);

            if(Objects.isNull(datas)){
                return Collections.emptyList();
            }
            JSONArray jsonArray = datas.getJSONArray(BizConst.RESPONSE_KEY_DATA);
            if(CollUtil.isEmpty(jsonArray)){
                return Collections.emptyList();
            }
            return jsonArray.stream().map(j -> {
                JSONObject json = JSON.parseObject(JSON.toJSONString(j));
                ProvincialGovBusinessStripVO vo = new ProvincialGovBusinessStripVO();
                vo.setBusinessStripCode(json.getString(BizConst.ORG_CODE));
                vo.setBusinessStripName(json.getString(BizConst.ORG_NAME));
                return vo;
            }).collect(Collectors.toList());
        }

        return Collections.emptyList();
    }

    private static String getSha256(Long timeStamp,String url,String method,String key,String secret){
        String bytesToSign = method + StrUtil.LF + url + StrUtil.LF + timeStamp + StrUtil.LF + key;
        log.info("加密message :{}",bytesToSign);
        String res = SecureUtil.hmacSha256(secret).digestBase64(bytesToSign,false);
        log.info("加密结果 :{}",res);
        return res;
    }
}
