package kr.xit.biz.common;

import java.util.Arrays;

import kr.xit.core.exception.BizRuntimeException;
import lombok.Getter;

/**
 * <pre>
 * description :
 *
 * packageName : kr.xit.ens.support.common
 * fileName    : KakaoConstants
 * author      : limju
 * date        : 2023-05-04
 * ======================================================================
 * 변경일         변경자        변경 내용
 * ----------------------------------------------------------------------
 * 2023-05-04    limju       최초 생성
 *
 * </pre>
 */
public class ApiConstants {

    /**
     * profile
     */
    public static final String PROFILE = System.getProperty("spring.profiles.active");
    /**
     * profile : local 여부
     */
    public static final boolean IS_PROFILE_LOCAL = PROFILE.matches("local-.*");

    /**
     * profile : 춘천 시스템 여부
     */
    public static final boolean IS_CCN = PROFILE.matches(".*-ccn");
    public static final String FFNLN_CODE = "11";

    /**
     * 구분자 없는 date-time 포맷
     */
    public static final String FMT_DT_EMPTY_DLT = "yyyyMMddHHmmss";

    /**
     * date-time 표준 포맷
     */
    public static final String FMT_DT_STD = "yyyy-MM-dd HH:mm:ss";

    /**
     * <pre>
     * 문서 조회 버튼의 명칭을 구분하기 위한 값
     * code(실제 파라미터로 보내는 값) : button_name(내문서함 내부에 표기되는 버튼 명칭)- name(내문서함 내부에서 구분하기 위한 명칭)
     * Default : 문서확인 - Default
     * BILL : 문서확인 - 고지서
     * BILL_PAY : 문서확인후 납부 - 납부가 포함된 고지서
     * NOTICE : 문서확인 - 안내문
     * CONTRACT : 문서확인 - 계약서
     * REPORT : 문서확인 - 리포트
     * </pre>
     */
    @Getter
    public enum Categories {
        DEFAULT("Default")
        , BILL("BILL")
        , BILL_PAY("BILL_PAY")
        , NOTICE("NOTICE")
        , CONTRACT("CONTRACT")
        , REPORT("REPORT")
        ;

        private final String code;

        Categories(String code) {
            this.code = code;
        }

    }

    /**
     * <pre>
     * INVALID_VALUE : http status code : 400
     *                 파라미터가 형식에 맞지않음 혹은 필수파라미터 누락
     *                 {"error_code": "INVALID_VALUE", "error_message": "유효하지 않은 값입니다."
     * UNIDENTIFIED_USER : http status code : 400
     *                     받는이의 정보로 발송대상을 특정 할 수 없을때
     *                     {"error_code": "INVALID_VALUE", "error_message": "유효하지 않은 값입니다."
     * UNAUTHORIZED : http status code : 401
     *                access token이 유효하지 않거나 잘못된 경우
     *                {"error_code": "UNAUTHORIZED","error_message": "접근 권한이 없습니다."
     * FORBIDDEN : http status code : 403
     *             문서의 대상자가 내문서함에서 수신거부를 한 경우
     *             {"error_code": "FORBIDDEN","error_message": "허용되지 않는 요청입니다. 수신거부된 사용자 입니다."}
     * NOT_FOUND : http status code : 404
     *             "Contract-Uuid" or "document_binder_uuid"가 유효하지 않거나 잘못된 경우
     *             {"error_code": "NOT_FOUND","error_message": "요청 정보를 찾을 수 없습니다."
     * INTERNAL_ERROR : http status code : 500
     *                  카카오페이 서버에러
     *                  {"error_code": "INTERNAL_SERVER_ERROR","error_message": "서버 에러입니다. 다시 시도해 주세요."}
     *  </pre>
     * 카카오페이 전자문서 발송 요청 에러 코드
     */
    @Getter
    public enum Error {
        INVALID_VALUE("INVALID_VALUE")
        , UNIDENTIFIED_USER("UNIDENTIFIED_USER")
        , UNAUTHORIZED("UNAUTHORIZED")
        , FORBIDDEN("FORBIDDEN")
        , NOT_FOUND("NOT_FOUND")
        , INTERNAL_ERROR("INTERNAL_ERROR")
        ;

        private final String code;

        Error(String code) {
            this.code = code;
        }

    }

    /**
     * <pre>
     * 카카오페이 문서 상태
     * SENT(송신) > RECEIVED(수신) > READ(열람)/EXPIRED(미열람자료의 기한만료)
     * </pre>
     */
    @Getter
    public enum KkopayDocStatus {
        SENT("SENT")
        , RECEIVED("RECEIVED")
        , READ("READ")
        , EXPIRED("EXPIRED")
        ;

        private final String code;

        KkopayDocStatus(String code) {
            this.code = code;
        }

    }

    /**
     * <pre>
     * 카카오톡 문서 상태
     * RECEIVE(수신, 미열람) > READ(열람)/EXPIRED(최초열람만료일시 또는 재열람 만료일시 초과)
     * </pre>
     */
    @Getter
    public enum KkotalkDocStatus {
        RECEIVED("RECEIVE")
        , READ("READ")
        , EXPIRED("EXPIRED")
        ;

        private final String code;

        KkotalkDocStatus(String code) {
            this.code = code;
        }

    }

    /**
     * 발송처리상태 : ENS003
     */
    @Getter
    public enum SndngProcessStatus {
        ACCEPT("accept"),
        ACCEPT_OK("accept-ok"),
        ACCEPT_FAIL("accept-fail"),
        MAKE_OK("make-ok"),
        MAKE_FAIL1("make-fail1"),
        MAKE_FAIL2("make-fail2"),
        MAKE_FAIL3("make-fail3"),
        SENDING1("sending1"),
        SENDING2("sending2"),
        SEND_OK("send-ok"),
        SEND_FAIL1("send-fail1"),
        SEND_FAIL2("send-fail2"),
        SEND_FAIL3("send-fail3"),
        CLOSE("close")

        ;

        private final String code;

        SndngProcessStatus(String code) {
            this.code = code;
        }

    }

    /**
     * 발송구분코드
     */
    @Getter
    public enum SndngSeCode {
        KAKAO("KKO-MY-DOC", "카카오"),
        KAKAO_NEW("KKO-NEW", "카카오NEW"),
        KT_BC("KT-BC", "공공알림문자"),
        KT_GIBIS("KT-GIBIS", "GIBIS알림문자"),
        ;

        private final String code;
        private final String desc;

        SndngSeCode(final String code, final String desc) {
            this.code = code;
            this.desc = desc;
        }

        public static SndngSeCode getSndngSeCode(final String code){
            return Arrays.stream(SndngSeCode.values())
                .filter(ssc -> ssc.getCode().equals(code))
                .findFirst()
                .orElseThrow(() -> BizRuntimeException.create(String.format("미정의된 문서 중계자가[%s]", code)));
        }
    }

    /**
     * SignguCode
     */
    @Getter
    public enum SignguCode {
        /**
         * 춘천
         */
        CHUNCHEON("51110"),
        /**
         * 천안동남구청
         */
        CHEONAN_ES("44131"),
        /**
         * 천안서북
         */
        CHEONAN_WN("44133"),
        ;

        private final String code;

        SignguCode(String code) {
            this.code = code;
        }

    }

    public enum NiceCiWrkDiv {
        TOKEN,
        PUBLIC_KEY,
        SYM_KEY,
        CI
    }

    public enum KtServiceCode {
        SISUL,
        CHUMO;

        public static KtServiceCode compare(final String en){
            return valueOf(en);
        }
    }

    /**
     * <pre>
     * 춘천의 발송처리상태 : ENS003 매핑
     * 01: 요청, 11: 접수완료, 19: 접수실패
     * 22: 제작완료, 29: 제작실패, 08: 발송완료, 09: 마감, 99: 발송실패
     * </pre>
     */
    @Getter
    public enum MappingCcnSndngProcessStatus {
        ACCEPT("accept", "01"),
        ACCEPT_OK("accept-ok", "11"),
        ACCEPT_FAIL("accept-fail", "19"),
        MAKE_OK("make-ok", "22"),
        MAKE_FAIL1("make-fail1", "29"),
        MAKE_FAIL2("make-fail2", "29"),
        MAKE_FAIL3("make-fail3", "29"),
        SENDING1("sending1", "08"),
        SENDING2("sending2", "08"),
        SEND_OK("send-ok", "08"),
        SEND_FAIL1("send-fail1", "99"),
        SEND_FAIL2("send-fail2", "99"),
        SEND_FAIL3("send-fail3", "99"),
        CLOSE("close", "09")

        ;

        private final String ensCode;
        private final String trfCode;

        MappingCcnSndngProcessStatus(String ensCode, String trfCode) {
            this.ensCode = ensCode;
            this.trfCode = trfCode;
        }

        /**
         * <pre>
         * traffic 상태코드를 ens 상태코드로 매핑
         * @param trfCode
         * @return traffic 상태코드에 매핑된 ens 상태코드
         * </pre>
         */
        public static String fromTraffic(final String trfCode){
            return Arrays.stream(MappingCcnSndngProcessStatus.values())
                .filter(en -> en.getTrfCode().equals(trfCode))
                .findFirst()
                .map(MappingCcnSndngProcessStatus::getEnsCode)
                .orElseThrow(() -> BizRuntimeException.create(String.format("미정의된 상태코드가[%s]", trfCode)));
        }

        /**
         * <pre>
         * ens 상태코드를 traffic 상태코드로 매핑
         * @param ensCode
         * @return ens 상태코드에 매핑된 traffic 상태코드
         * </pre>
         */
        public static String fromEns(final String ensCode){
            return Arrays.stream(MappingCcnSndngProcessStatus.values())
                .filter(en -> en.getEnsCode().equals(ensCode))
                .findFirst()
                .map(MappingCcnSndngProcessStatus::getTrfCode)
                .orElseThrow(() -> BizRuntimeException.create(String.format("미정의된 상태코드가[%s]", ensCode)));
        }
    }

    /**
     * <pre>
     * 천안의 발송처리상태 : ENS003 매핑
     * 01: 요청, 11: 접수완료, 19: 접수실패
     * 22: 제작완료, 29: 제작실패, 08: 발송완료, 09: 마감, 99: 발송실패
     * </pre>
     */
    @Getter
    public enum MappingCanSndngProcessStatus {
        ACCEPT("accept", "accept"),
        ACCEPT_OK("accept-ok", "acptok"),
        ACCEPT_FAIL("accept-fail", "acptfail"),
        MAKE_OK("make-ok", "ensmake"),
        MAKE_FAIL1("make-fail1", "makefail"),
        MAKE_FAIL2("make-fail2", "makefail"),
        MAKE_FAIL3("make-fail3", "makefail"),
        SENDING1("sending1", "ensok"),
        SENDING2("sending2", "ensok"),
        SEND_OK("send-ok", "ensopen"),
        SEND_FAIL1("send-fail1", "ensfail"),
        SEND_FAIL2("send-fail2", "ensfail"),
        SEND_FAIL3("send-fail3", "ensfail"),
        CLOSE("close", "ensclose")

        ;

        private final String ensCode;
        private final String trfCode;

        MappingCanSndngProcessStatus(String ensCode, String trfCode) {
            this.ensCode = ensCode;
            this.trfCode = trfCode;
        }

        /**
         * <pre>
         * traffic 상태코드를 ens 상태코드로 매핑
         * @param trfCode
         * @return traffic 상태코드에 매핑된 ens 상태코드
         * </pre>
         */
        public static String fromTraffic(final String trfCode){
            return Arrays.stream(MappingCanSndngProcessStatus.values())
                .filter(en -> en.getTrfCode().equals(trfCode))
                .findFirst()
                .map(MappingCanSndngProcessStatus::getEnsCode)
                .orElseThrow(() -> BizRuntimeException.create(String.format("미정의된 상태코드가[%s]", trfCode)));
        }

        /**
         * <pre>
         * ens 상태코드를 traffic 상태코드로 매핑
         * @param ensCode
         * @return ens 상태코드에 매핑된 traffic 상태코드
         * </pre>
         */
        public static String fromEns(final String ensCode){
            return Arrays.stream(MappingCanSndngProcessStatus.values())
                .filter(en -> en.getEnsCode().equals(ensCode))
                .findFirst()
                .map(MappingCanSndngProcessStatus::getTrfCode)
                .orElseThrow(() -> BizRuntimeException.create(String.format("미정의된 상태코드가[%s]", ensCode)));
        }
    }
}
