package cokr.xit.ens.modules.nvsigntalk.service.support;

import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.core.utils.IdGenerator;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * <ul>
 * <li>업무 그룹명: 네이버 인증톡 서비스</li>
 * <li>설 명: </li>
 * <li>작성일: 2021. 11. 18. 오후 5:01:36
 * </ul>
 *
 * @author 박민규
 */
@Slf4j
@Component
@Profile({"local-test"})
public class NvSigntalkApiTest implements NvSigntalkApiSpec {

    @Value("${contract.naver.signtalk.host}")
    private String HOST;
    @Value("${contract.naver.signtalk.api.ping}")
    private String API_PING;
    @Value("${contract.naver.signtalk.api.token}")
    private String API_TOKEN;
    @Value("${contract.naver.signtalk.api.bulksend}")
    private String API_BULKSEND;
    @Value("${contract.naver.signtalk.api.bulkstatus}")
    private String API_BULKSTATUS;


    /**
     * Ping Test Url
     */
//	설명: 고지서 서버 ping check url
//	호출경로: GET /invoice/v1/ping
//	반환값 (200 OK) "pong"
    @Override
    public ResponseEntity<String> ping() {
       
        HttpHeaders headers = new HttpHeaders();
//		headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));

       
        StringBuilder url = new StringBuilder();
        url.append(this.HOST)
                .append(API_PING);

       
        ResponseEntity<String> resp = this.callApi(HttpMethod.GET, url.toString(), null, headers);


        String data = "pong";
        return ResponseEntity.ok(data);
    }


    /**
     * 토큰 유효성 검증(Redirect URL  접속 허용/불허)
     */
//	설명: RedirectUrl로 전달된 nonce 값의 검증을 요청
//	호출경로: POST /invoice/v1/nonce/status
//  Content-Type: application/json
    @Override
    public ResponseEntity<String> token(String xNaverClientId, String xNaverClientSecret, String docId, String nonce) {
       
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
        headers.set("X-Naver-Client-Id", xNaverClientId);
        headers.set("X-Naver-Client-Secret", xNaverClientSecret);

       
        StringBuilder url = new StringBuilder();
        url.append(this.HOST)
                .append(API_TOKEN);

        String jsonStr = "{" +
                "    \"docId\": \"" + docId + "\"" +
                "    ,\"nonce\": \"" + nonce + "\"" +
//				"    ,\"additionalErrorResponseFieldList\": [" +
//				"        \"clientDocId\"" +
//				"    ]" +
                "}";

       
        ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);

        String data = "{\"result\":\"success\",\"docId\":\"#{docId}\",\"clientDocId\":\"company_20200119_00001\",\"sendTs\":1578483002152,\"recvTs\":1578483106459,\"authReqTs\":1578483002152,\"authViewTs\":1578483106459,\"authCompleteTs \":1578483106459,\"expireTs\":1578489106459,\"orgNotifiedTs\":1578489106459}";
        return ResponseEntity.ok(data.replace("#{docId}", docId));
    }


    /**
     * 대량(bulk) 문서발송 요청
     * -.이용기관 서버에서 API 서버로 대량(bulk) 문서발송 처리를 요청합니다.
     */
//	설명: 네이버 고지서 서버에 1건 이상의 고지서 발송 요청
//	호출경로: POST /invoice/v1/request
//  Content-Type: application/json
    @Override
    public ResponseEntity<String> bulkSend(String xNaverClientId, String xNaverClientSecret, String jsonStr) {
       
        HttpHeaders headers = new HttpHeaders();
//		headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
        headers.set("X-Naver-Client-Id", xNaverClientId);
        headers.set("X-Naver-Client-Secret", xNaverClientSecret);

       
        StringBuilder url = new StringBuilder();
        url.append(this.HOST)
                .append(API_BULKSEND);

       
        ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);

        String successDoc = "{\"result\":\"success\",\"clientDocId\":\"#{clientDocId}\",\"docId\":\"#{docId}\"},";

        Gson gson = new Gson();
        Map<String, List> m = gson.fromJson(jsonStr, Map.class);
        List<Map<String, Object>> documents = m.get("data");
        StringBuffer data = new StringBuffer();
        data.append("{\"data\":[");
        documents.forEach(dataset -> data.append(successDoc.replace("#{clientDocId}", (String) dataset.get("clientDocId")).replace("#{docId}", IdGenerator.getShortUUID())));
        data.append("]}");
        return ResponseEntity.ok(data.toString().replace(",]}", "]}"));

    }


    /**
     * 대량(bulk) 문서 상태 조회 API
     */
//	설명: 네이버Sign 서버에 고지서 상태 조회 요청
//	호출경로: POST /invoice/v1/status
    @Override
    public ResponseEntity<String> bulkStatus(String xNaverClientId, String xNaverClientSecret, String jsonStr) {
       
        HttpHeaders headers = new HttpHeaders();
//		headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Charset.forName("utf-8")));
        headers.set("X-Naver-Client-Id", xNaverClientId);
        headers.set("X-Naver-Client-Secret", xNaverClientSecret);

       
        StringBuilder url = new StringBuilder();
        url.append(this.HOST)
                .append(API_BULKSTATUS);

       
        ResponseEntity<String> resp = this.callApi(HttpMethod.POST, url.toString(), jsonStr, headers);

        String successDoc = "{\"result\":\"success\",\"docId\":\"#{docId}\",\"clientDocId\":\"#{clientDocId}\",\"sendTs\":1578483002152,\"recvTs\":157848310645,\"authReqTs\":1578483002152,\"authViewTs\":1578483106459,\"authCompleteTs\":1578483106459,\"expireTs\":1578489106459,\"orgNotifiedTs\":1578489106459},";

        Gson gson = new Gson();
        Map<String, List> m = gson.fromJson(jsonStr, Map.class);
        List<String> documents = m.get("docIdList");
        StringBuffer data = new StringBuffer();
        data.append("{\"data\":[");
        documents.forEach(docId -> data.append(successDoc.replace("#{docId}", docId)));
        data.append("]}");
        return ResponseEntity.ok(data.toString().replace("},]}", "}]}"));
    }


    /**
     * <pre>메소드 설명: API 호출
     * </pre>
     *
     * @param method
     * @param url
     * @param body
     * @param headers
     * @return ResponseEntity 요청처리 후 응답객체
     * @author: 박민규
     * @date: 2021. 8. 4.
     * @apiNote: 사이트 참조 https://e2e2e2.tistory.com/15
     */
    private ResponseEntity<String> callApi(HttpMethod method, String url, String body, HttpHeaders headers) {

        StringBuffer sb = new StringBuffer();
        ResponseEntity<String> responseEntity = ResponseEntity.ok("test");
        try {
           
            HttpEntity<?> entity = null;
            UriComponents uri = null;
            switch (method) {
                case GET:
                    entity = new HttpEntity<>(headers);
                    uri = UriComponentsBuilder
                            .fromHttpUrl(String.format("%s?%s", url, body == null ? "" : body))
                            .build(false);
                    break;
                case POST:
                    entity = new HttpEntity<>(body, headers);
                    uri = UriComponentsBuilder
                            .fromHttpUrl(url)
                            .encode(StandardCharsets.UTF_8)
                            .build();
                    break;

                default:
                    break;
            }

            sb.append("\n  url => " + uri.toString())
                    .append("\n  method => " + method)
                    .append("\n  headers => " + entity.getHeaders().toString())
                    .append("\n  body => " + entity.getBody());
        } catch (Exception e) {
            log.error("call API 기타오류\n[ url ]: {} \n[ param ]: {} \n[ error ]: {}", url, body, CmmnUtil.printStackTraceToString(e));
        } finally {
            log.info("네이버 고지서(인증톡) API\n[ REQUEST ]-----------------------------------------------------------------------\n{}\n[ RESPONSE ]-----------------------------------------------------------------------\n{}", sb.toString(), responseEntity.getBody());
        }

       
        return responseEntity;
    }

}

