package cokr.xit.ens.modules.common.ctgy.sys.mng.service;

import cokr.xit.ens.core.aop.EnsResponseVO;
import cokr.xit.ens.core.config.redis.CacheKey;
import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.core.utils.CmmnUtil;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.OrgMng;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.repository.OrgMngRepository;
import cokr.xit.ens.modules.common.ctgy.sys.mng.model.OrgMngDTO;
import cokr.xit.ens.modules.common.ctgy.sys.mng.model.OrgMngSearchDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class OrgMngService {

    private final OrgMngRepository orgMngRepository;

    public EnsResponseVO<List<OrgMng>> findAllBySearchDTO(OrgMngSearchDTO searchDTO) {
        return EnsResponseVO.<List<OrgMng>>okBuilder()
                .resultInfo(orgMngRepository.findAllFetchBySearchDTO(searchDTO))
                .build();

    }

//    @Cacheable(value = CacheKey.ORGMNG, key = "#orgCd")
    public EnsResponseVO<OrgMng> find(String orgCd) {
        try {
            return EnsResponseVO.<OrgMng>okBuilder()
                    .resultInfo(orgMngRepository.findById(orgCd).orElseThrow(() -> new EnsException(EnsErrCd.ERR404, String.format("기관코드(%s)와 일치하는 자료가 없습니다.", orgCd))))
                    .build();
        } catch (EnsException e) {
            return EnsResponseVO.<OrgMng>errBuilder()
                    .errCode(e.getErrCd())
                    .errMsg(e.getMessage())
                    .build();
        }
    }


    public EnsResponseVO add(OrgMngDTO dto) {
        try {
            final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
            Set<ConstraintViolation<OrgMngDTO>> list = validator.validate(dto);
            if (list.size() > 0) {
                return EnsResponseVO.errRsltBuilder()
                        .errCode(EnsErrCd.ERR410)
                        .errMsg("유효하지 않은 요청값 입니다.")
                        .resultInfo(list.stream()
                                .map(row -> String.format("%s [ %s ]", row.getMessageTemplate(), row.getPropertyPath()))
                                .collect(Collectors.toList()))
                        .build();
            }
            if ("Y".equals(dto.getKkoBpCsignYn())) {
                if (CmmnUtil.isEmpty(dto.getKkoBpPrepayApi()) || CmmnUtil.isEmpty(dto.getKkoBpPayResultApi()))
                    return EnsResponseVO.errRsltBuilder()
                            .errCode(EnsErrCd.ERR410)
                            .errMsg("납부요청 위탁여부(kkoBpCsignYn)가 Y 일 경우 \"납부가능조회API\"와 \"납부결과API\"의 URL은 필수 입니다.")
                            .build();
            }
            orgMngRepository.findById(dto.getOrgCd()).ifPresent(orgmng -> {
                throw new EnsException(EnsErrCd.ERR540, String.format("이미 등록된 기관코드(%s) 입니다.", dto.getOrgCd()));
            });


            orgMngRepository.save(OrgMng.builder()
                            .orgCd(dto.getOrgCd())
                            .orgNm(dto.getOrgNm())
//                    .subOrgId(null)
                            .kkoMdAccessToken(dto.getKkoMdAccessToken())
                            .kkoMdContractUuid(dto.getKkoMdContractUuid())
                            .kkoBpBillerCode(dto.getKkoBpBillerCode())
                            .kkoBpAuthorization(dto.getKkoBpAuthorization())
                            .kkoBpCsignYn(dto.getKkoBpCsignYn())
                            .kkoBpUrlApi(dto.getKkoBpUrlApi())
                            .kkoBpNoticeApi(dto.getKkoBpNoticeApi())
                            .kkoBpPrepayApi(dto.getKkoBpPrepayApi())
                            .kkoBpPayresultApi(dto.getKkoBpPayResultApi())
                            .kkoAtBsid(dto.getKkoAtBsid())
                            .kkoAtPasswd(dto.getKkoAtPasswd())
                            .kkoAtSenderKey(dto.getKkoAtSenderKey())
                            .niceCdSiteCode(dto.getNiceCdSiteCode())
                            .niceCdSitePw(dto.getNiceCdSitePw())
                            .niceCdClientId(dto.getNiceCdClientId())
                            .niceCdClientSercet(dto.getNiceCdClientSercet())
                            .nvStXNaverClientId(dto.getNvStXNaverClientId())
                            .nvStXNaverClientSecret(dto.getNvStXNaverClientSecret())
                            .nvStOrgId(dto.getNvStOrgId())
                            .nvBpPartnerId(dto.getNvBpPartnerId())
                            .nvBpClientId(dto.getNvBpClientId())
                            .nvBpClientSecret(dto.getNvBpClientSecret())
                            .nvBpNoticeApi(dto.getNvBpNoticeApi())
                            .nvBpPrepayApi(dto.getNvBpPrepayApi())
                            .nvBpPayresultApi(dto.getNvBpPayresultApi())
                            .nvBpPaycancelApi(dto.getNvBpPaycancelApi())
                            .ktStAccessToken(dto.getKtStAccessToken())
                            .ktStServiceCd(dto.getKtStServiceCd())
                            .ktStServiceKey(dto.getKtStServiceKey())
                            .ktStClientId(dto.getKtStClientId())
                            .ktStClientSecret(dto.getKtStClientId())
                            .build()
            );

            return EnsResponseVO.okBuilder().build();
        } catch (EnsException e) {
            return EnsResponseVO.errBuilder()
                    .errCode(e.getErrCd())
                    .errMsg(e.getMessage())
                    .build();
        } catch (Exception e) {
            return EnsResponseVO.errRsltBuilder()
                    .errCode(EnsErrCd.ERR999)
                    .errMsg(e.getMessage())
                    .build();
        }

    }

//    @CachePut(value = CacheKey.ORGMNG, key = "#dto.orgCd")
    public EnsResponseVO modify(OrgMngDTO dto) {
        try {
            final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
            Set<ConstraintViolation<OrgMngDTO>> list = validator.validate(dto);
            if (list.size() > 0) {
                return EnsResponseVO.errRsltBuilder()
                        .errCode(EnsErrCd.ERR410)
                        .errMsg("유효하지 않은 요청값 입니다.")
                        .resultInfo(list.stream()
                                .map(row -> String.format("%s [ %s ]", row.getMessageTemplate(), row.getPropertyPath()))
                                .collect(Collectors.toList()))
                        .build();
            }
            if ("Y".equals(dto.getKkoBpCsignYn())) {
                if (CmmnUtil.isEmpty(dto.getKkoBpPrepayApi()) || CmmnUtil.isEmpty(dto.getKkoBpPayResultApi()))
                    return EnsResponseVO.errRsltBuilder()
                            .errCode(EnsErrCd.ERR410)
                            .errMsg("납부요청 위탁여부(kkoBpCsignYn)가 Y 일 경우 \"납부가능조회API\"와 \"납부결과API\"의 URL은 필수 입니다.")
                            .build();
            }
            OrgMng orgMng = orgMngRepository.findById(dto.getOrgCd()).orElseThrow(() -> new EnsException(EnsErrCd.ERR404, String.format("기관코드(%s)와 일치하는 자료가 없습니다.", dto.getOrgCd())));


            orgMng.setOrgNm(dto.getOrgNm());
//            orgMng.setSubOrgId(null);
            orgMng.setKkoMdAccessToken(dto.getKkoMdAccessToken());
            orgMng.setKkoMdContractUuid(dto.getKkoMdContractUuid());
            orgMng.setKkoBpBillerCode(dto.getKkoBpBillerCode());

            orgMng.setKkoBpAuthorization(dto.getKkoBpAuthorization());
            orgMng.setKkoBpCsignYn(dto.getKkoBpCsignYn());
            orgMng.setKkoBpUrlApi(dto.getKkoBpUrlApi());
            orgMng.setKkoBpNoticeApi(dto.getKkoBpNoticeApi());
            orgMng.setKkoBpPrepayApi(dto.getKkoBpPrepayApi());
            orgMng.setKkoBpPayresultApi(dto.getKkoBpPayResultApi());

            orgMng.setKkoAtBsid(dto.getKkoAtBsid());
            orgMng.setKkoAtPasswd(dto.getKkoAtPasswd());
            orgMng.setKkoAtSenderKey(dto.getKkoAtSenderKey());

            orgMng.setNiceCdSiteCode(dto.getNiceCdSiteCode());
            orgMng.setNiceCdSitePw(dto.getNiceCdSitePw());
            orgMng.setNiceCdClientId(dto.getNiceCdClientId());
            orgMng.setNiceCdClientSercet(dto.getNiceCdClientSercet());

            orgMng.setNvStXNaverClientId(dto.getNvStXNaverClientId());
            orgMng.setNvStXNaverClientSecret(dto.getNvStXNaverClientSecret());
            orgMng.setNvStOrgId(dto.getNvStOrgId());

            orgMng.setKtStAccessToken(dto.getKtStAccessToken());
            orgMng.setKtStServiceCd(dto.getKtStServiceCd());
            orgMng.setKtStServiceKey(dto.getKtStServiceKey());
            orgMng.setKtStClientId(dto.getKtStClientId());
            orgMng.setKtStClientSecret(dto.getKtStClientSecret());

            return EnsResponseVO.okBuilder().resultInfo(orgMng).build();
        } catch (EnsException e) {
            return EnsResponseVO.errBuilder()
                    .errCode(e.getErrCd())
                    .errMsg(e.getMessage())
                    .build();
        }
    }

//    @CacheEvict(value = CacheKey.ORGMNG, key = "#orgCd")
    public EnsResponseVO delete(String orgCd) {
        try {
            OrgMng orgMng = orgMngRepository.findById(orgCd).orElseThrow(() -> new EnsException(EnsErrCd.ERR404, String.format("기관코드(%s)와 일치하는 자료가 없습니다.", orgCd)));

            orgMngRepository.delete(orgMng);

            return EnsResponseVO.okBuilder().build();
        } catch (EnsException e) {
            return EnsResponseVO.errBuilder()
                    .errCode(e.getErrCd())
                    .errMsg(e.getMessage())
                    .build();
        }
    }

}
