package com.eactive.eai.custom.message;

import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * DJBank(제주은행) 차세대 표준전문 GUID 생성기
 *
 * GUID 구성 (40자):
 *   일자(8) + 시간(6) + 밀리초(3) + 시스템코드(3) + 노드번호(2) + 세션ID(12) + Random(6)
 *   = 8 + 6 + 3 + 3 + 2 + 12 + 6 = 40자
 */
public final class GUIDGeneratorDJB {

    public static final int GUID_LENGTH = 40;

    private static final DateTimeFormatter FMT_DATE   = DateTimeFormatter.ofPattern("yyyyMMdd");
    private static final DateTimeFormatter FMT_TIME   = DateTimeFormatter.ofPattern("HHmmss");
    private static final DateTimeFormatter FMT_MILLIS = DateTimeFormatter.ofPattern("SSS");

    private static final AtomicInteger seq = new AtomicInteger(1);
    private static final SecureRandom  rnd = new SecureRandom();

    private static final String NODE_NO;
    private static final String SESSION_ID_BASE;

    static {
        // 노드번호(2): 서버명 마지막 2자리, 없으면 "00"
        String serverName = System.getProperty("server.key", "");
        if (serverName.length() >= 2) {
            NODE_NO = serverName.substring(serverName.length() - 2);
        } else {
            NODE_NO = "00";
        }

        // 세션ID 기반(12): 호스트명 앞 12자 (부족 시 '_'로 우측패딩)
        String hostname;
        try {
            hostname = java.net.InetAddress.getLocalHost().getHostName();
        } catch (Exception e) {
            hostname = "____________";
        }
        if (hostname.length() >= 12) {
            SESSION_ID_BASE = hostname.substring(0, 12).toUpperCase();
        } else {
            SESSION_ID_BASE = String.format("%-12s", hostname).toUpperCase().replace(' ', '_');
        }
    }

    private GUIDGeneratorDJB() {
    }

    /**
     * @param systemCode 시스템구분코드 3자 (예: "EAI", "OPA")
     */
    public static String getGUID(String systemCode) {
        LocalDateTime now = LocalDateTime.now();

        String date    = now.format(FMT_DATE);   // 8자
        String time    = now.format(FMT_TIME);   // 6자
        String millis  = now.format(FMT_MILLIS); // 3자

        // 시스템코드 3자 정규화
        String sysCode = normalizeCode(systemCode, 3);

        // 노드번호 2자
        String nodeNo = NODE_NO;

        // 세션ID 12자
        String sessionId = SESSION_ID_BASE;

        // Random 6자 (숫자)
        int seqVal = seq.getAndUpdate(v -> v >= 999999 ? 1 : v + 1);
        String random = String.format("%06d", seqVal);

        String guid = date + time + millis + sysCode + nodeNo + sessionId + random;

        if (guid.length() != GUID_LENGTH) {
            throw new IllegalStateException("GUID length error: " + guid.length() + " [" + guid + "]");
        }
        return guid;
    }

    private static String normalizeCode(String code, int len) {
        if (code == null) code = "";
        code = code.toUpperCase();
        if (code.length() >= len) return code.substring(0, len);
        return String.format("%-" + len + "s", code).replace(' ', '_');
    }
}
