package kr.xit.core.support.utils;

import static org.junit.jupiter.api.Assertions.*;

import java.util.*;

import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.*;
import org.mockito.junit.jupiter.*;

import com.fasterxml.jackson.core.*;

import kr.xit.biz.common.*;
import kr.xit.biz.ens.model.kakao.pay.*;
import kr.xit.biz.ens.model.kakao.talk.*;
import kr.xit.core.exception.*;
import kr.xit.core.model.*;
import lombok.*;
import lombok.extern.slf4j.*;

@Slf4j
@ExtendWith(MockitoExtension.class)
public class JsonUtilsTest {
    
    /**
     * This class provides methods to test the functionality of JsonUtils.
     * The 'toObject' method converts a JSON string into an object of the specified class type.
     */

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static class TestObject {
        private String name;
        private int age;
    }
    
    @Test
    void testSendBulks() throws JsonProcessingException {
      String sendJson1 = """
            {"envelopes":[{"externalId":"41220110994794765","envelopeId":"EVLP-01JCQC971QBBQQ6N54TKSEP9WT-00"}]}
            """;
        String sendJson = "{\"envelopes\":[{\"externalId\":\"41220110994794765\",\"envelopeId\":\"EVLP-01JCQC971QBBQQ6N54TKSEP9WT-00\"}]}";
        String statusJson = """
            {"envelopeStatus":[{"envelopeId":"EVLP-01JCQC971QBBQQ6N54TKSEP9WT-00","externalId":"41220110994794765","status":"RECEIVED","sentAt":"2024-11-15T16:40:57","receivedAt":"2024-11-15T16:40:57","readExpiredAt":"2024-12-31T23:59:59","isNotificationUnavailable":false}]}
            """;
        ApiResponseDTO kkoStatusList = getKkoStatusList();
        List<ApiResponseDTO> apiResults = new ArrayList<>(Collections.singleton(kkoStatusList));

        final List<KkopayDocBulkDTO.BulkStatusResponses> resList = new ArrayList<>();
        //noinspection rawtypes
        for(ApiResponseDTO apiResult : apiResults) {
            if(apiResult.getData() != null) {
                resList.add(toObjByObj(apiResult.getData(), KkopayDocBulkDTO.BulkStatusResponses.class));
            }
        }
        
        toObject(sendJson, KkotalkDTO.BulkSendResponse.class);
        toObject(statusJson, KkotalkDTO.BulkStatusResponse.class);
    }

    private static <T> T toObjByObj(Object obj, Class<T> clazz) {
        return JsonUtils.toObjByObj(obj, clazz);
    }

    private static <T> T toObject(String obj, Class<T> clazz) {
        return JsonUtils.toObject(obj, clazz);
    }

    @Test
    void testToObject_validJson() {
        String json = "{\"name\": \"John\", \"age\": 30}";
        TestObject expectedObject = new TestObject("John", 30);

        TestObject result = JsonUtils.toObject(json, TestObject.class);

        assertEquals(expectedObject, result, "Converting JSON to TestObject did not produce the expected object.");
    }

    @Test
    void testToObject_emptyString() {
        String json = "";

        assertNull(JsonUtils.toObject(json, TestObject.class), "Empty string should result in a null object.");
    }

    @Test
    void testToObject_nullString() {
        assertNull(JsonUtils.toObject(null, TestObject.class), "Null string should result in a null object.");
    }

    @Test
    void testToObject_invalidJson() {
        String json = "{\"name\": \"John\", \"age\": \"thirty\"}";

        assertThrows(BizRuntimeException.class, () -> JsonUtils.toObject(json, TestObject.class),
            "Invalid JSON should throw a BizRuntimeException.");
    }
    
    private static ApiResponseDTO getKkoStatusList(){
        List<KkopayDocBulkDTO.BulkStatus> resDTO = new ArrayList<>();

        resDTO.add(KkopayDocBulkDTO.BulkStatus.builder()
            .document_binder_uuid("dkdkdkkdkd")
            .error_code(ApiConstants.Error.NOT_FOUND.getCode())
            .error_message("요청 정보를 찾을 수 없습니다. documentBinder를 찾을수 없습니다.")
            .build()
        );

        resDTO.add(KkopayDocBulkDTO.BulkStatus.builder()
            .document_binder_uuid("susuusus")
            .status_data(KkopayDocAttrDTO.DocStatus.builder()
                .doc_box_status(ApiConstants.KkopayDocStatus.RECEIVED)
                .doc_box_sent_at(1443456743L)
                .doc_box_received_at(1443456743L)
                .user_notified_at(1443456743L)
                .build())
            .build()
        );

        resDTO.add(KkopayDocBulkDTO.BulkStatus.builder()
            .document_binder_uuid("djdjfjjf")
            .status_data(KkopayDocAttrDTO.DocStatus.builder()
                .doc_box_status(ApiConstants.KkopayDocStatus.READ)
                .doc_box_sent_at(1443456743L)
                .doc_box_received_at(1443456743L)
                .doc_box_read_at(1443456743L)
                .authenticated_at(1443456743L)
                .token_used_at(1443456743L)
                .user_notified_at(1443456743L)
                .build())
            .build()
        );

        return ApiResponseDTO.success(KkopayDocBulkDTO.BulkStatusResponses.builder()
            .documents(resDTO)
            .build());
    }
}