package kr.xit.biz.ens.web;

import static kr.xit.core.support.utils.JsonUtils.*;

import java.util.*;
import java.util.concurrent.atomic.*;

import org.apache.commons.collections4.*;
import org.apache.commons.lang3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

import io.swagger.v3.oas.annotations.*;
import io.swagger.v3.oas.annotations.media.*;
import io.swagger.v3.oas.annotations.tags.*;
import kr.xit.biz.ens.cmm.*;
import kr.xit.biz.ens.model.cmm.*;
import kr.xit.biz.ens.model.kakao.pay.*;
import kr.xit.biz.ens.model.kakao.talk.*;
import kr.xit.core.model.*;
import kr.xit.core.spring.util.*;
import kr.xit.core.support.utils.*;
import lombok.*;
import lombok.extern.slf4j.*;

/**
 * <pre>
 * description :
 *
 * packageName : kr.xit.biz.ens.web
 * fileName    : KkotalkApiDummyTestController
 * author      : limju
 * date        : 2023-08-31
 * ======================================================================
 * 변경일         변경자        변경 내용
 * ----------------------------------------------------------------------
 * 2023-08-31    limju       최초 생성
 *
 * </pre>
 */
@Tag(name = "KkotalkApiDummyTestController", description = "카카오톡 전자고지 API Dummy 테스트")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/batch/ens/test/kakao/talk")
@Slf4j
public class KkotalkApiDummyTestController {
    @Value("${app.contract.host}")
    private String apiHost;

    private String requestSend = "/api/kakao/talk/test/documents";
    
    private String apiBulkSend = "/api/kakao/talk/test/documents/bulk";
    private String apiBulkSendError = "/api/kakao/talk/test/documents/bulk/error";
    
    private String apiBulkStatus = "/api/kakao/talk/test/documents/bulk/status";

    private final ApiWebClientUtil apiWebClient;

    /**
     * <pre>
     * 모바일웹 연계 문서발송 요청
     * -.이용기관 서버에서 전자문서 서버로 문서발송 처리를 요청합니다.
     * </pre>
     * @param reqDTO
     * @return ResponseEntity
     */
    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(mediaType = "application/json", examples = {
            @ExampleObject(value = """
                {
                   "productCode": "D10_2",
                   "envelope": {
                     "title": "문서 제목",
                     "content": {
                       "link": "http://ipAddress/api/kakaopay/v1/ott",
                       "html": ""
                     },
                     "hash": "73deae8287321e7237ed080f515d064fffe9dec380c3d3cb57a9d436007ad9e2",
                     "guide": "문서 정보 안내 화면에 노출할 문구",
                     "payload": "payload 파라미터 입니다.",
                     "readExpiresAt": "2023-12-31T10:00:00",
                     "reviewExpiresAt": "2023-12-31T13:00:00",
                     "useNonPersonalizedNotification": false,
                     "ci": "",
                     "phoneNumber": "01012345678",
                     "name": "김페이",
                     "birthday": "19801101",
                     "externalId": ""
                   },
                   "signguCode": "51110",
                   "ffnlgCode": "11",
                   "profile": "local"
                }
            """)
        })
    })
    @Operation(summary = "문서발송 요청", description = "카카오페이 전자문서 서버로 문서발송 처리를 요청")
    @PostMapping(value = "/documents", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse requestSend(
        @RequestBody final KkopayDocDTO.SendRequest reqDTO
    ) {
        StringBuilder url = new StringBuilder()
            .append(apiHost)
            .append(requestSend);

        return apiWebClient.exchangeKkotalk(
            url.toString(),
            HttpMethod.POST,
            JsonUtils.toJson(reqDTO),
            ApiResponseDTO.class,
            getRlaybsnmDTO()
        );
    }


    /**
     * <pre>
     * 모바일웹 연계 문서발송 요청
     * -.이용기관 서버에서 전자문서 서버로 문서발송 처리를 요청합니다.
     * </pre>
     * @param reqDTO KkopayDocBulkDTO.BulkSendRequests
     * @return ApiResponseDTO
     */
    @Operation(summary = "대량 문서발송 요청", description = "카카오페이 전자문서 서버로 대량 문서발송 처리를 요청")
    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(mediaType = "application/json", examples = {
            @ExampleObject(value = """
                {
                  "productCode": "D10_1",
                  "envelopes": [
                    {
                      "title": "문서 제목",
                      "content": {
                        "link": "http://ipAddress/api/kakaopay/v1/ott",
                        "html": ""
                      },
                      "hash": "1375b68517c3055a2d5b425d8c6d32f6dbc9c74fb7f5fc796eb16c11a7a183b7",
                      "guide": "문서 정보 안내 화면에 노출할 문구",
                      "payload": "payload 파라미터 입니다.",
                      "readExpiresAt": "2023-12-31T10:00:00",
                      "reviewExpiresAt": "2023-12-31T13:00:00",
                      "useNonPersonalizedNotification": false,
                      "ci": "",
                      "phoneNumber": "01012345678",
                      "name": "김페이",
                      "birthday": "19801101",
                      "externalId": "41220202410170021"
                    },
                    {
                      "title": "문서 제목1",
                      "content": {
                        "link": "http://ipAddress/api/kakaopay/v1/ott",
                        "html": ""
                      },
                      "hash": "ad23397eea6951e4a967e4561b9b0459d59239d5f1e92f3b3fe5a8a511e99e83",
                      "guide": "문서 정보 안내 화면에 노출할 문구",
                      "payload": "payload 파라미터 입니다1.",
                      "readExpiresAt": "2023-12-31T10:00:00",
                      "reviewExpiresAt": "2023-12-31T13:00:00",
                      "useNonPersonalizedNotification": false,
                      "ci": "",
                      "phoneNumber": "01012345678",
                      "name": "김페이1",
                      "birthday": "19801101",
                      "externalId": "4413311202408200033"
                    },
                    {
                      "title": "문서 제목2",
                      "content": {
                        "link": "http://ipAddress/api/kakaopay/v1/ott",
                        "html": ""
                      },
                      "hash": "73deae8287321e7237ed080f515d064fffe9dec380c3d3cb57a9d436007ad9e2",
                      "guide": "문서 정보 안내 화면에 노출할 문구",
                      "payload": "payload 파라미터 입니다2.",
                      "readExpiresAt": "2023-12-31T10:00:00",
                      "reviewExpiresAt": "2023-12-31T13:00:00",
                      "useNonPersonalizedNotification": false,
                      "ci": "",
                      "phoneNumber": "01012345678",
                      "name": "김페이2",
                      "birthday": "19801101",
                      "externalId": "41220202410170011"
                    }
                  ],
                  "signguCode": "51110",
                  "ffnlgCode": "11",
                  "profile": "local"
                }
            """)
        })
    })
    @PostMapping(value = "/documents/bulk", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse requestSendBulk(
        @RequestBody final KkotalkDTO.BulkSendRequest reqDTO
    ) {
        final String url = apiHost + apiBulkSend;

        return apiWebClient.exchangeKkotalk(
            url,
            HttpMethod.POST,
            JsonUtils.toJson(reqDTO),
            ApiResponseDTO.class,
            getRlaybsnmDTO()
        );
    }

    @Operation(summary = "대량 문서발송 요청", description = "카카오페이 전자문서 서버로 대량 문서발송 처리를 요청")
    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(mediaType = "application/json", examples = {
            @ExampleObject(value = """
                {
                  "productCode": "D10_1",
                  "envelopes": [
                    {
                      "title": "문서 제목",
                      "content": {
                        "link": "http://ipAddress/api/kakaopay/v1/ott",
                        "html": ""
                      },
                      "hash": "1375b68517c3055a2d5b425d8c6d32f6dbc9c74fb7f5fc796eb16c11a7a183b7",
                      "guide": "문서 정보 안내 화면에 노출할 문구",
                      "payload": "payload 파라미터 입니다.",
                      "readExpiresAt": "2023-12-31T10:00:00",
                      "reviewExpiresAt": "2023-12-31T13:00:00",
                      "useNonPersonalizedNotification": false,
                      "ci": "",
                      "phoneNumber": "01012345678",
                      "name": "김페이",
                      "birthday": "19801101",
                      "externalId": "41220202410170021"
                    },
                    {
                      "title": "문서 제목1",
                      "content": {
                        "link": "http://ipAddress/api/kakaopay/v1/ott",
                        "html": ""
                      },
                      "hash": "ad23397eea6951e4a967e4561b9b0459d59239d5f1e92f3b3fe5a8a511e99e83",
                      "guide": "문서 정보 안내 화면에 노출할 문구",
                      "payload": "payload 파라미터 입니다1.",
                      "readExpiresAt": "2023-12-31T10:00:00",
                      "reviewExpiresAt": "2023-12-31T13:00:00",
                      "useNonPersonalizedNotification": false,
                      "ci": "",
                      "phoneNumber": "01012345678",
                      "name": "김페이1",
                      "birthday": "19801101",
                      "externalId": "4413311202408200033"
                    },
                    {
                      "title": "문서 제목2",
                      "content": {
                        "link": "http://ipAddress/api/kakaopay/v1/ott",
                        "html": ""
                      },
                      "hash": "73deae8287321e7237ed080f515d064fffe9dec380c3d3cb57a9d436007ad9e2",
                      "guide": "문서 정보 안내 화면에 노출할 문구",
                      "payload": "payload 파라미터 입니다2.",
                      "readExpiresAt": "2023-12-31T10:00:00",
                      "reviewExpiresAt": "2023-12-31T13:00:00",
                      "useNonPersonalizedNotification": false,
                      "ci": "",
                      "phoneNumber": "01012345678",
                      "name": "김페이2",
                      "birthday": "19801101",
                      "externalId": "41220202410170011"
                    }
                  ],
                  "signguCode": "51110",
                  "ffnlgCode": "11",
                  "profile": "local"
                }
            """)
        })
    })
    @PostMapping(value = "/documents/bulk/error", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse requestSendBulkAndError(
        @RequestBody final KkotalkDTO.BulkSendRequest reqDTO
    ) {
        final String url = apiHost + apiBulkSend;

        final List<KkotalkDTO.BulkSendResponse> resList = new ArrayList<>();
        boolean isSuccess = false;
        String errMsg = null;
        final List<KkotalkApiDTO.Envelope> envelopes = reqDTO.getEnvelopes();
        
        for(int idx = 0; idx<3; idx++) {
            ApiResponseDTO<?> response = apiWebClient.exchangeKkotalk(
                apiHost + (idx==0? apiBulkSendError : apiBulkSend),
                HttpMethod.POST,
                JsonUtils.toJson(reqDTO),
                ApiResponseDTO.class,
                getRlaybsnmDTO()
            );

            if(response.getData() != null) {
                try {
                    resList.add(toObjByObj(response.getData(), KkotalkDTO.BulkSendResponse.class));
                    
                    // FIXME::카카오톡 API 수신 결과가 아닌 경우 - 이렇게 수신 되는 경우가 있는지 테스트 불가 하여 방어 코드 추가 함
                    // {"timestamp":"2024-12-16T01:19:57.040+00:00","path":"/pxy/kkoNew/v1/bulk/envelopes/D10_2","status":500,"error":"Internal Server Error","requestId":"541faefe-45126"}
                    if(ObjectUtils.isNotEmpty(resList)){
                        KkotalkDTO.BulkSendResponse bulkSendResponse = resList.get(0);
                        List<KkotalkApiDTO.EnvelopeRes> envelopeRes = bulkSendResponse.getEnvelopes();
                        // FIXME::카카오톡 API 수신 결과가 아닌 경우 - 이렇게 수신 되는 경우가 있는지 테스트 불가 하여 방어 코드 추가 함
                        if(ObjectUtils.isEmpty(envelopeRes) || ObjectUtils.isEmpty(envelopeRes.get(0).getExternalId())){
                            resList.clear();
                            setErrorSendDto(envelopes, resList, "Internal Server Error");
                        }else{
                            isSuccess = true;    
                        };
                    }
                }catch (Exception e){
                    log.error("API 호출 결과 비정상 데이타::apiResult.getData() - {}", response.getMessage());
                    setErrorSendDto(envelopes, resList, "Internal Server Error");
                }
                //extractService.saveKkotalkSendResult(resList);
                resList.clear();
                continue;
            }else{
                log.error(">>>> API 호출 결과 에러[비정상 return - proxy 에서 error return]::ApiResponseDTO - {}", response);
                setErrorSendDto(envelopes, resList, "Internal Server Error");
                //extractService.saveKkotalkSendResult(resList);
                resList.clear();
            }
            errMsg = response.getMessage();
        }
        return ApiResponseDTO.success(isSuccess);
    }

    @Operation(summary = "대량 문서발송 요청", description = "카카오페이 전자문서 서버로 대량 문서발송 처리를 요청")
    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(mediaType = "application/json", examples = {
            @ExampleObject(value = """
                {
                  "productCode": "D10_1",
                  "envelopes": [
                    {
                      "title": "문서 제목",
                      "content": {
                        "link": "http://ipAddress/api/kakaopay/v1/ott",
                        "html": ""
                      },
                      "hash": "1375b68517c3055a2d5b425d8c6d32f6dbc9c74fb7f5fc796eb16c11a7a183b7",
                      "guide": "문서 정보 안내 화면에 노출할 문구",
                      "payload": "payload 파라미터 입니다.",
                      "readExpiresAt": "2023-12-31T10:00:00",
                      "reviewExpiresAt": "2023-12-31T13:00:00",
                      "useNonPersonalizedNotification": false,
                      "ci": "",
                      "phoneNumber": "01012345678",
                      "name": "김페이",
                      "birthday": "19801101",
                      "externalId": "41220202410170021"
                    },
                    {
                      "title": "문서 제목1",
                      "content": {
                        "link": "http://ipAddress/api/kakaopay/v1/ott",
                        "html": ""
                      },
                      "hash": "ad23397eea6951e4a967e4561b9b0459d59239d5f1e92f3b3fe5a8a511e99e83",
                      "guide": "문서 정보 안내 화면에 노출할 문구",
                      "payload": "payload 파라미터 입니다1.",
                      "readExpiresAt": "2023-12-31T10:00:00",
                      "reviewExpiresAt": "2023-12-31T13:00:00",
                      "useNonPersonalizedNotification": false,
                      "ci": "",
                      "phoneNumber": "01012345678",
                      "name": "김페이1",
                      "birthday": "19801101",
                      "externalId": "4413311202408200033"
                    },
                    {
                      "title": "문서 제목2",
                      "content": {
                        "link": "http://ipAddress/api/kakaopay/v1/ott",
                        "html": ""
                      },
                      "hash": "73deae8287321e7237ed080f515d064fffe9dec380c3d3cb57a9d436007ad9e2",
                      "guide": "문서 정보 안내 화면에 노출할 문구",
                      "payload": "payload 파라미터 입니다2.",
                      "readExpiresAt": "2023-12-31T10:00:00",
                      "reviewExpiresAt": "2023-12-31T13:00:00",
                      "useNonPersonalizedNotification": false,
                      "ci": "",
                      "phoneNumber": "01012345678",
                      "name": "김페이2",
                      "birthday": "19801101",
                      "externalId": "41220202410170011"
                    }
                  ],
                  "signguCode": "51110",
                  "ffnlgCode": "11",
                  "profile": "local"
                }
            """)
        })
    })
    @PostMapping(value = "/documents/bulk/error2", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse requestSendBulkAndError2(
        @RequestBody final KkotalkDTO.BulkSendRequest reqDTO
    ) {
        
        final List<KkotalkApiDTO.Envelope> envelopes = reqDTO.getEnvelopes();


        final List<List<KkotalkApiDTO.Envelope>> partitions = ListUtils.partition(envelopes, 1);
        Map<String, String> headerMap = CmmEnsBizUtils.getHeadeMap();

        AtomicInteger idx = new AtomicInteger(-1);
        //noinspection rawtypes
        final List<ApiResponseDTO> apiResults = partitions.stream()
            .map(bulkSendList -> {
                idx.getAndIncrement();
                return apiWebClient.exchangeKkotalk(
                        apiHost + (idx.get() ==0? apiBulkSendError : apiBulkSend),
                        HttpMethod.POST,
                        JsonUtils.toJson(reqDTO),
                        ApiResponseDTO.class,
                        getRlaybsnmDTO());
                }
            )
            .toList();

        final List<KkotalkDTO.BulkSendResponse> resList = new ArrayList<>();
        boolean isSuccess = false;
        String errMsg = null;
        //noinspection rawtypes
        for(ApiResponseDTO apiResult : apiResults) {
            if(apiResult.getData() != null) {
                resList.add(toObjByObj(apiResult.getData(), KkotalkDTO.BulkSendResponse.class));
                // FIXME:: 카카오톡 bulk send별 결과 처리
                //extractService.saveKkotalkSendResult(resList);
                resList.clear();
                isSuccess = true;
                continue;
            }
            errMsg = apiResult.getMessage();
        }
        
        
        
        return ApiResponseDTO.success(reqDTO);
    }
    
    /**
     * <pre>
     * 모바일웹 연계 문서발송 요청
     * -.이용기관 서버에서 전자문서 서버로 문서발송 처리를 요청합니다.
     * </pre>
     * @param reqDTO KkopayDocBulkDTO.BulkStatusRequests
     * @return ApiResponseDTO<BulkStatusResponses.BulkStatusResponses>
     */
    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(mediaType = "application/json", examples = {
            @ExampleObject(value = """
                {
                  "document_binder_uuids": [
                    "BIN-883246dbff7b11edb3bb7affed8a016d",
                    "BIN-883246dbff7b11edb3bb7affed8a0161",
                    "BIN-883246dbff7b11edb3bb7affed8a0162"
                  ]
                }
            """)
        })
    })
    @Operation(summary = "대량 문서 상태 조회 요청", description = "카카오페이 전자문서 서버로 대량 문서 상태 조회 요청")
    @PostMapping(value = "/documents/bulk/status", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse findBulkStatus(
        @RequestBody final KkopayDocBulkDTO.BulkStatusRequests reqDTO
    ) {
        final String url = apiHost + apiBulkStatus;

        return apiWebClient.exchangeKkotalk(
            url,
            HttpMethod.POST,
            JsonUtils.toJson(reqDTO),
            ApiResponseDTO.class,
            getRlaybsnmDTO()
        );
    }

    private CmmEnsRlaybsnmDTO getRlaybsnmDTO(){
        return CmmEnsRlaybsnmDTO.builder()
                .kakaoClientId("")
                .kakaoContractUuid("")
                .build();
    }

    private void setErrorSendDto(List<KkotalkApiDTO.Envelope> envelopes, List<KkotalkDTO.BulkSendResponse> resList, String errMsg){
        List<KkotalkApiDTO.EnvelopeRes>  envelopeResList = new ArrayList<>();
        for(KkotalkApiDTO.Envelope envelope :envelopes){
            envelopeResList.add(
                KkotalkApiDTO.EnvelopeRes.builder()
                    .externalId(envelope.getExternalId())
                    .errorCode("E400_00")
                    .errorMessage(errMsg)
                    .build()
            );
        }
        resList.add(
            KkotalkDTO.BulkSendResponse.builder()
                .envelopes(envelopeResList)
                .build()
        );
    }
}
