package com.eactive.ext.kjb.obp;

import com.eactive.ext.kjb.common.KjbObpException;
import com.eactive.ext.kjb.common.KjbProperty;
import com.eactive.ext.kjb.common.KjbPropertyHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

@Slf4j
public class KjbObpModule {
    private static final String FAKE_PARTNER_CODE = "999999-99";

    private static volatile KjbObpModule instance;

    private KjbObpModule() {
        // 싱글톤
    }

    public static KjbObpModule getInstance() {
        if (instance == null) {
            synchronized (KjbObpModule.class) {
                if (instance == null) {
                    instance = new KjbObpModule();
                }
            }
        }
        return instance;
    }

    private static KjbProperty getProperty() {
        return KjbPropertyHolder.get();
    }

    private ObpClient getClient() {
        return ObpClient.getInstance();
    }

    /**
     * 사업자등록번호로 partnerCode 조회
     * @param bizNo 사업자등록번호 (숫자 외 문자 자동 제거)
     * @return partnerCode
     * @throws KjbObpException 조회 실패 시
     */
    public String queryPartnerCode(String bizNo) throws KjbObpException {
        bizNo = ObpUtil.onlyDigit(bizNo);

        if (StringUtils.isEmpty(bizNo)) {
            throw new IllegalArgumentException("BizNo is empty.");
        }

        if (bizNo.length() != 10) {
            throw new IllegalArgumentException("BizNo must be 10 digits. (input: " + bizNo + ")");
        }

        ObpClient client = getClient();

        // 가상모드: URL 미설정 시 가상 파트너코드 반환
        if (!client.isRealMode()) {
            log.info("[OBP] 가상모드 - 가상 partnerCode 반환: {}", FAKE_PARTNER_CODE);
            return FAKE_PARTNER_CODE;
        }

        String path = String.format(getProperty().getObpUrlOrganizationFmt(), bizNo);
        log.debug("[OBP] queryPartnerCode - bizNo: {}, path: {}", bizNo, path);

        ObpResponse response = client.get(path);

        if (response.getStatus() != 200) {
            log.warn("[OBP] queryPartnerCode failed - status: {}, body: {}", response.getStatus(), response.getBody());
            throw new KjbObpException(response.getStatus(), "OBP 조회 실패: " + response.getBody());
        }

        ObpOrganization org = ObpOrganization.fromResponse(response);

        if (org == null) {
            throw new KjbObpException("OBP 응답 파싱 실패");
        }

        if (!org.hasPartnerCode()) {
            throw new KjbObpException("partnerCode가 없습니다. bizNo: " + bizNo);
        }

        return org.getPartnerCode();
    }
}
