package kr.xit.biz.ens.model.kakao.talk;

import javax.validation.Valid;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotEmpty;

import com.fasterxml.jackson.annotation.JsonInclude;

import io.swagger.v3.oas.annotations.media.Schema;
import kr.xit.biz.common.ApiConstants;
import kr.xit.biz.ens.model.cmm.CmmEnsRequestDTO;
import kr.xit.core.model.IApiResponse;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

/**
 * <pre>
 * description : 카카오톡 전자문서 DTO
 *               API 호출시 속성값이 없는 경우 속성을 json에 포함시키지 않는다.
 *               => @JsonInclude(JsonInclude.Include.NON_EMPTY) 설정
 * packageName : kr.xit.biz.ens.model.kakao.talk
 * fileName    : KkotalkApiDTO
 * author      : limju
 * date        : 2024-08-12
 * ======================================================================
 * 변경일         변경자        변경 내용
 * ----------------------------------------------------------------------
 * 2024-08-12    limju       최초 생성
 *
 * </pre>
 */
public class KkotalkApiDTO {

    //------------------- Envelope ------------------------------------------------------------------------------------------------
    @Schema(name = "Envelope", description = "문서발송(단건) 요청 파라메터 DTO")
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @SuperBuilder
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public static class Envelope {
        /**
         * 발송할 문서의 제목 : 필수 - max 40자
         */
        @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "발송할 문서의 제목", example = "문서 제목")
        @Size(max = 40, message = "발송할 문서의 제목은 필수 입니다(max:40)")
        private String title;

        @Schema(requiredMode = Schema.RequiredMode.REQUIRED)
        @Valid
        private Content content;

        /**
         * <pre>
         * 문서 원문(열람정보)에 대한 hash 값
         * D10_2 상품 사용시 필수
         * </pre>
         */
        @Schema(title = "문서 원문(열람정보)에 대한 hash 값", example = "6EFE827AC88914DE471C621AE")
        @Pattern(regexp = "^$|^[a-fA-F0-9]{44}$|^[a-fA-F0-9]{64}$", message = "문서 해시값은 44자 또는 64자의 16진수여야 합니다")
        private String hash;

        /**
         * 문서 정보 안내 화면에 노출할 문구(최대: 500자) - 필수
         */
        @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서 정보 안내 화면에 노출할 문구(최대: 500자)", example = "문서 정보 안내 화면에 노출할 문구")
        @Size(min=1, max = 500, message = "문서 정보 안내 화면에 노출할 문구(max=500)")
        private String guide;

        /**
         * payload
         */
        @Schema(title = "payload", example = "payload 파라미터 입니다.")
        @Size(max = 200, message = "payload(max=200)")
        private String payload;

        /**
         * <pre>
         * 최초 열람 만료 일시 지정(최대: 요청 일시로부터 6개월 이내) - 필수
         * yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
         * </pre>
         */
        @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "최초열람마감시간(yyyy-MM-dd'T'HH:mm:ss)", example = "2023-12-31T10:00:00")
        @Size(min = 19, max = 19, message = "최초열람마감시간(yyyy-MM-dd'T'HH:mm:ss)")
        private String readExpiresAt;

        /**
         * <pre>
         * 재열람 만료 일시 지정
         * 최소: readExpiredAt 이후의 시각
         * 최대값: 9999-12-31'T'23:59:59, null 값이면 무제한
         * 비고: DX0 상품인 경우 최대값은 요청일로부터 6개월 이내
         * </pre>
         */
        @Schema(title = "재열람 만료 일시(yyyy-MM-dd'T'HH:mm:ss)", example = "2023-12-31T13:00:00")
        @Size(max = 19, message = "재열람 만료 일시(yyyy-MM-dd'T'HH:mm:ss)")
        private String reviewExpiresAt;

        /**
         * <pre>
         * 알림톡 내용에 개인정보 제거 여부
         * default: false
         * </pre>
         */
        @Schema(title = "알림톡 내용에 개인정보 제거 여부", example = " ", defaultValue = "false", allowableValues = {"true", "false"})
        @Builder.Default
        private Boolean useNonPersonalizedNotification = false;

        /**
         * 수신자 CI
         */
        @Schema(title = "받는이 CI", example = " ")
        @Size(max=88, message = "수신자 CI(max=88)")
        private String ci;

        /**
         * <pre>
         * 수신자 전화번호
         * ci 미전송시 필수
         * </pre>
         */
        @Schema(title = "수신자 전화번호", example = "01012345678")
        @Pattern(regexp = "^$|^\\d{11}$", message = "수신자 전화번호(max=11)")
        private String phoneNumber;

        /**
         * <pre>
         * 수신자 이름
         * ci 미전송시 필수
         * </pre>
         */
        @Schema(title = "수신자 이름", example = "김페이")
        @Size(max = 26, message = "수신자 이름(max=26)")
        private String name;

        /**
         * <pre>
         * 수신자 생년월일 (YYYY-MM-DD 형식)
         * ci 미전송시 필수
         * </pre>
         */
        @Schema(requiredMode = Schema.RequiredMode.AUTO, title = "수신자 생년월일 (YYYYMMDD 형식)", example = "19801101")
        @Pattern(regexp = "^$|^(19\\d{2}|20\\d{2})(0[1-9]|1[0-2])(0[1-9]|[1-2]\\d|3[0-1])$", message = "수신자 생년월일(YYYYMMDD)")
        private String birthday;

        /**
         * <pre>
         * 문서매핑용 식별자 - 최대 40자
         * </pre>
         */
        @Schema(requiredMode = Schema.RequiredMode.AUTO, title = "문서매핑용 식별자", example = " ")
        @Size(max=40, message = "문서매핑용 식별자(max=40)")
        private String externalId;
    }

    @Schema(name = "Content", description = "문서 원문 웹링크 또는 HTML")
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @SuperBuilder
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public static class Content {
        /**
         * <pre>
         * 본인인증 후 사용자에게 보여줄 웹페이지 주소
         * D10 상품 사용시 필수
         * 1000자 이하의 URL 형식
         * </pre>
         */
        @Schema(title = "본인인증 후 사용자에게 보여줄 웹페이지 주소", example = "http://ipAddress/api/kakaopay/v1/ott")
        @Size(max = 1000, message = "본인인증후 사용자에게 보여줄 페이지 주소는 필수입니다(max=1000)")
        private String link;

        /**
         * <pre>
         * HTML 전문
         * D11 상품 사용시 필수(최대 64KB)
         */
        @Schema(title = "HTML 전문", example = " ")
        @Size(max = 65536, message = "HTML 전문(max=64KB)")
        private String html;
    }

    //------------------- ValidToken ------------------------------------------------------------------------------------------------
    @Schema(name = "ValidTokenRequest DTO", description = "카카오톡 전자문서 토큰 유효성 검증 파라메터 DTO")
    @Data
    @SuperBuilder
    @NoArgsConstructor
    @AllArgsConstructor
    @EqualsAndHashCode(callSuper = false)
    public static class ValidTokenRequest extends CmmEnsRequestDTO {
        /**
         * 문서 고유 ID, 34자로 고정
         */
        @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서 고유 ID, 34자로 고정", example = " ")
        @Size(min = 34, max = 34, message = "문서 고유 ID는 필수입니다(34자)")
        private String envelopeId;

        /**
         * 카카오톡 전자문서 서버에서 생성한 일회용 토큰 : 필수
         */
        @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "카카오톡 전자문서 서버에서 생성한 일회용 토큰", example = "CON-cc375944ae3d11ecb91e42193199ee3c")
        @NotEmpty(message = "카카오톡 전자문서 서버 토큰은 필수입니다")
        private String token;
    }

    @Schema(name = "ValidTokenResponse DTO", description = "카카오톡 토큰 검증 response DTO")
    @Data
    @SuperBuilder
    @NoArgsConstructor
    @AllArgsConstructor
    @EqualsAndHashCode(callSuper = true)
    public static class ValidTokenResponse extends KkotalkErrorDTO implements IApiResponse {
        /**
         * 문서 고유 ID, 34자로 고정
         */
        private String envelopeId;

        /**
         * <pre>
         * 문서매핑용 식별자 - 최대 40자
         * </pre>
         */
        private String externalId;

        /**
         * <pre>
         * 진행상태 : 토큰검증시 필수
         * 수신,미열람|열람|최초열람만료일시 또는 재열람 만료일시 초과
         * RECEIVE|READ|EXPIRED
         * </pre>
         * @see ApiConstants.KkotalkDocStatus
         */
        private ApiConstants.KkotalkDocStatus status;

        /**
         * <pre>
         * 문서 송신 일시 - 토큰검증시 필수
         * yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
         * </
         */
        private String sentAt;

        /**
         * <pre>
         * 문서 수신 일시 - 토큰검증시 필수
         * yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
         * </pre>
         */
        private String receivedAt;

        /**
         * <pre>
         * 문서 열람 일시
         * yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
         * </pre>
         */
        private String readAt;

        /**
         * <pre>
         * 문서 열람 인증 일시
         * yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
         * </pre>
         */
        private String authenticatedAt;

        /**
         * <pre>
         * 토큰 검증 일시
         * yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
         * </pre>
         */
        private String ottVerifiedAt;

        /**
         * <pre>
         * 사용자의 알림톡 수신 가능 여부
         * </pre>
         */
        private Boolean isNotificationUnavailable;

        /**
         * <pre>
         * 사용자의 알림톡 수신 일시
         * yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
         * </pre>
         */
        private String userNotifiedAt;

        /**
         * 문서 발송하기 API 요청 시 전달한 페이로드
         */
        private String payload;
    }
    //------------------ ValidToken ----------------------------------------------------------------------

    //------------------ DocStatus ----------------------------------------------------------------------
    @Schema(name = "EnvelopeStatusResponse DTO", description = "카카오톡 상태조회 response DTO")
    @Data
    @SuperBuilder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    @EqualsAndHashCode(callSuper = true)
    public static class EnvelopeStatusResponse extends ValidTokenResponse implements IApiResponse {
        /**        /**
         * <pre>
         * 문서 열람 만료 일시
         * yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
         * </pre>
         */
        private String readExpiredAt;

        /**        /**
         * <pre>
         * 유통정보의 수신 시각
         * 공인전자주소 활성화와 문서 수신이 모두 완료된 시각
         * yyyy-MM-dd'T'HH:mm:ss 형식 > DateUtils.getTimeTOfNow()
         * </pre>
         */
        private String distributionReceivedAt;
    }
    //------------------ DocStatus ----------------------------------------------------------------------


    //------------------ SendResponse ----------------------------------------------------------------------
    @Schema(name = "EnvelopeRes DTO", description = "문서발송 응답 DTO")
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @SuperBuilder
    @EqualsAndHashCode(callSuper = false)
    //@JsonInclude(JsonInclude.Include.NON_EMPTY)
    public static class EnvelopeRes extends KkotalkErrorDTO{
        /**
         * 문서 고유 ID, 34자로 고정
         */
        @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서 고유 ID, 34자로 고정", example = " ")
        @Size(min = 34, max = 34, message = "문서 고유 ID는 필수입니다(34자)")
        private String envelopeId;

        /**
         * <pre>
         * 문서매핑용 식별자 - 최대 40자
         * </pre>
         */
        private String externalId;
    }

    @Schema(name = "KkotalkErrorResponse DTO", description = "카카오톡 에러 응답 DTO")
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @SuperBuilder
    public static class KkotalkErrorDTO {
        /**
         * 에러코드
         */
        private String errorCode;

        /**
         * 에러 메세지
         */
        private String errorMessage;

        /**
         * 트래킹(Tracking) ID
         */
        private String edocGtid;
    }


    @Schema(name = "SendResponse DTO", description = "문서발송 응답 DTO")
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @SuperBuilder
    @EqualsAndHashCode(callSuper = false)
    public static class SendResponse extends KkotalkErrorDTO {
        /**
         * 문서 고유 ID, 34자로 고정 - 필수
         */
        private String envelopeId;

        /**
         * <pre>
         * 문서매핑용 식별자 - 최대 40자
         * </pre>
         */
        private String externalId;
    }

    //-------------------------------------------------------------------------------------

    @Schema(name = "EnvelopeId DTO", description = "EnvelopeId DTO")
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @SuperBuilder
    @EqualsAndHashCode(callSuper = false)
    public static class EnvelopeId extends CmmEnsRequestDTO{
        /**
         * 문서 고유 ID, 34자로 고정
         */
        @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "문서 고유 ID, 34자로 고정", example = " ")
        @Size(min = 34, max = 34, message = "문서 고유 ID는 필수입니다(34자)")
        private String envelopeId;
    }

}
