package com.eactive.eai.rms.onl.apim.common;

import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
import com.google.gson.GsonBuilder;

import java.nio.charset.StandardCharsets;

/**
 * 외부 API 엔드포인트를 위한 Base REST Controller
 *
 * <p>기능:</p>
 * <ul>
 *   <li>세션 체크 우회 (InterceptorSkipController)</li>
 *   <li>JSON 변환 유틸리티 (pretty print 지원)</li>
 *   <li>응답 크기 포맷팅</li>
 * </ul>
 *
 * <p>보안:</p>
 * <ul>
 *   <li>세션 인증 생략 (InterceptorSkipController 구현)</li>
 *   <li>IP 화이트리스트 인증 필요 (IpWhitelistInterceptor를 통해)</li>
 *   <li>허용된 IP는 속성에서 설정: kjb.api.allow_ip_list</li>
 * </ul>
 *
 * <p>사용 예:</p>
 * <pre>
 * {@code
 * @Controller
 * public class MyApiController extends BaseRestController {
 *     @RequestMapping(value = "/api/something.json", produces = JSON_CONTENT_TYPE)
 *     @ResponseBody
 *     public String getSomething(@RequestParam(value = "pretty", required = false) Boolean pretty) {
 *         List<MyDTO> data = service.getData();
 *         return toJson(data, pretty);
 *     }
 * }
 * }
 * </pre>
 *
 * @see com.eactive.eai.rms.common.interceptor.IpWhitelistInterceptor
 */
public abstract class BaseRestController implements InterceptorSkipController {

    /**
     * JSON 응답 Content-Type
     */
    protected static final String JSON_CONTENT_TYPE = "application/json;charset=utf-8";

    /**
     * 객체를 JSON 문자열로 변환
     *
     * @param object 변환할 객체
     * @param pretty true면 들여쓰기 적용 (null이면 false로 처리)
     * @return JSON 문자열
     */
    protected String toJson(Object object, Boolean pretty) {
        GsonBuilder builder = new GsonBuilder().serializeNulls();
        if (Boolean.TRUE.equals(pretty)) {
            builder.setPrettyPrinting();
        }
        return builder.create().toJson(object);
    }

    /**
     * 객체를 JSON 문자열로 변환 (기본: 한 줄 출력)
     *
     * @param object 변환할 객체
     * @return JSON 문자열
     */
    protected String toJson(Object object) {
        return toJson(object, false);
    }

    /**
     * 바이트 크기를 읽기 쉬운 형식으로 변환
     * 예: 1024 -> "1.0 KB", 1048576 -> "1.0 MB"
     *
     * @param bytes 바이트 수
     * @return 포맷된 문자열
     */
    protected String formatByteSize(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return String.format("%.1f KB", bytes / 1024.0);
        } else {
            return String.format("%.1f MB", bytes / (1024.0 * 1024.0));
        }
    }

    /**
     * JSON 문자열의 바이트 크기 계산 (UTF-8 기준)
     *
     * @param json JSON 문자열
     * @return 바이트 수
     */
    protected int getJsonByteSize(String json) {
        return json.getBytes(StandardCharsets.UTF_8).length;
    }

    /**
     * JSON 문자열의 포맷된 바이트 크기 반환
     *
     * @param json JSON 문자열
     * @return 포맷된 크기 문자열
     */
    protected String getFormattedJsonSize(String json) {
        return formatByteSize(getJsonByteSize(json));
    }
}
