package cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.presentation;

import cokr.xit.ens.core.exception.EnsException;
import cokr.xit.ens.core.exception.code.EnsErrCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.code.NvEpCtgyIdCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.code.NvEpCtgyTypeCd;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.model.NvPayAbleReqData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.model.NvPayNoticeRespData;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.nv.service.process.model.config.notice.ProductItem;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.PayUseSysController;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.code.PayUseSysResCd;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.utility.RandomString;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Tag(name = "NvPayUseSysSampleController")
@Slf4j
@RequiredArgsConstructor
@RestController
public class NvPayUseSysSampleController implements PayUseSysController<ResponseEntity, Map<String, Object>> {

    @Value("${contract.naver.pay.easy.api.validate.host}")
    private String BILL_HOST;
    @Value("${contract.naver.pay.easy.api.validate.prepay}")
    private String BILL_PAYABLE_URL;

    private Gson gson = new Gson();


    //    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
//            @Content(mediaType = "application/json", examples = {
//                    @ExampleObject(name = "Sample Example..."
//                            , summary = "청구서링크생성 정보"
//                            , value = "{}")
//            })
//    })
    @Operation(summary = "청구서링크생성 정보 샘플")
    @PostMapping(value = "/bill/nv/ep/sample/gnrUrl", produces = MediaType.APPLICATION_JSON_VALUE)
    @Override
    public ResponseEntity gnrUrl(Map<String, Object> param) {
        throw new EnsException(EnsErrCd.SERVICE_NOT_SUPPORTED, EnsErrCd.SERVICE_NOT_SUPPORTED.getCodeNm());
    }

    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
            @Content(mediaType = "application/json", examples = {
                    @ExampleObject(name = "Sample Example..."
                            , summary = "납부(결제)정보"
                            , value = "{\"data\":{\"billerUserKey\":\"빌러유저키\"}}")
            })
    })
    @Operation(summary = "납부(결제)정보 샘플")
    @PostMapping(value = "/bill/nv/ep/sample/paynotice", produces = MediaType.APPLICATION_JSON_VALUE)
    @Override
    public ResponseEntity<Map<String, Object>> payNotice(@RequestBody Map<String, Object> param) {
        log.info("[Request Data] {}", param.toString());
        Map<String, Object> reqData = (Map<String, Object>) param.getOrDefault("data", new HashMap<>());



        /* ============================================
        * [정상 응답코드]
        *   OK 
        * [실패 응답코드]
        *   NOT_FOUND_PAYDATA   
        *   PAYDATA_FIND_FAILED   
        ============================================ */
        PayUseSysResCd resCd = PayUseSysResCd.OK;

        
        final String productName = "테스트 상품 - " + RandomString.make(7);
        final int taxScopeAmount = 100;   
        final int taxExScopeAmount = 0;   
        final Integer environmentDepositAmount = null; 
        final int totalPayAmount = taxScopeAmount + taxExScopeAmount + (environmentDepositAmount == null ? 0 : environmentDepositAmount); 
        final List<ProductItem> productItemList = Arrays.asList(ProductItem.builder()
                .categoryType(NvEpCtgyTypeCd.ETC)
                .categoryId(NvEpCtgyIdCd.ETC_ETC.getCode())
                .uid((String) reqData.get("billerUserKey"))
                .name(productName)
                .payReferrer(null)
                .startDate(null)
                .endDate(null)
                .sellerId(null)
                .count(1)
                .build());
        final int productCount = productItemList.stream().map(productItem -> productItem.getCount()).reduce(Integer::sum).get();
        NvPayNoticeRespData data = NvPayNoticeRespData.builder()
                .productName(productName)
                .productCount(productCount)
                .totalPayAmount(totalPayAmount)
                .taxScopeAmount(taxScopeAmount)
                .taxExScopeAmount(taxExScopeAmount)
                .environmentDepositAmount(environmentDepositAmount)
                .productItems(productItemList)
                .returnUrl(BILL_HOST + BILL_PAYABLE_URL)
                .purchaserName(null)
                .purchaserBirthday(null)
                .build();
        Map<String, Object> result = new HashMap<>();
        result.put("res_code", resCd.getCode());
        result.put("message", resCd.getCodeNm());
        result.put("data", data);

        return new ResponseEntity<Map<String, Object>>(result, HttpStatus.OK);
    }


    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
            @Content(mediaType = "application/json", examples = {
                    @ExampleObject(name = "Sample Example..."
                            , summary = "납부(결제)가능여부"
                            , value = "{\"data\":{\"billerUserKey\":\"빌러유저키\",\"productName\":\"\",\"totalPayAmount\":1000,\"taxScopeAmount\":1000,\"taxExScopeAmount\":null}}")
            })
    })
    @Operation(summary = "납부(결제)가능여부 샘플")
    @PostMapping(value = "/bill/nv/ep/sample/payable", produces = MediaType.APPLICATION_JSON_VALUE)
    @Override
    public ResponseEntity<Map<String, Object>> payAble(@RequestBody Map<String, Object> param) {

        Map<String, NvPayAbleReqData> data = gson.fromJson(gson.toJson(param), new TypeToken<Map<String, NvPayAbleReqData>>() {
        }.getType());

        log.info("[Request Data] {}", data.toString());


        /* ============================================
        * [정상 응답코드]
        *   OK 
        * [실패 응답코드]
        *   NO_AMOUNT_PAYABLE   
        *   OVERPAYABLE_AMOUNT  
        *   NO_TARGET_PAYABLE   
        *   EXPIRED_DATE        
        *   FAILED_CHECK_INFO   
        ============================================ */
        PayUseSysResCd resCd = PayUseSysResCd.OK;

        
        Map<String, Object> result = new HashMap<>();
        result.put("res_code", resCd.getCode());
        result.put("message", resCd.getCodeNm());
        result.put("data", null);


        return new ResponseEntity<Map<String, Object>>(result, HttpStatus.OK);
    }


    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
            @Content(mediaType = "application/json", examples = {
                    @ExampleObject(name = "Sample Example..."
                            , summary = "납부(결제)결과"
                            , value = "{\"code\":\"Success\",\"message\":\"detail message(optional)\",\"body\":{\"paymentId\":\"네이버페이 결제번호\",\"detail\":{\"productName\":\"샘플상품\",\"merchantId\":\"loginId\",\"merchantName\":\"가맹점명\",\"cardNo\":\"465887**********\",\"admissionYmdt\":\"20170201151722\",\"payHistId\":\"20170201NP1043587781\",\"totalPayAmount\":1000,\"primaryPayAmount\":1000,\"npointPayAmount\":0,\"giftCardAmount\":0,\"taxScopeAmount\":1000,\"taxExScopeAmount\":0,\"environmentDepositAmount\":0,\"primaryPayMeans\":\"CARD\",\"merchantPayKey\":\"청구서UID\",\"merchantUserKey\":\"빌러유저키\",\"cardCorpCode\":\"C0\",\"paymentId\":\"20170201NP1043587746\",\"admissionTypeCode\":\"01\",\"settleExpectAmount\":971,\"payCommissionAmount\":29,\"admissionState\":\"SUCCESS\",\"tradeConfirmYmdt\":\"20170201152510\",\"cardAuthNo\":\"17545616\",\"cardInstCount\":0,\"usedCardPoint\":false,\"bankCorpCode\":\"\",\"bankAccountNo\":\"\",\"settleExpected\":false,\"extraDeduction\":false,\"useCfmYmdt\":\"20180703\"}}}")
            })
    })
    @Operation(summary = "납부(결제)결과 샘플")
    @PostMapping(value = "/bill/nv/ep/sample/payresult", produces = MediaType.APPLICATION_JSON_VALUE)
    @Override
    public ResponseEntity<Map<String, Object>> payResult(@RequestBody Map<String, Object> param) {
        log.info("[Request Data] {}", param.toString());

        PayUseSysResCd resCd = PayUseSysResCd.OK;

        
        Map<String, Object> result = new HashMap<>();
        result.put("res_code", resCd.getCode());
        result.put("message", resCd.getCodeNm());
        result.put("data", null);

        return new ResponseEntity<Map<String, Object>>(result, HttpStatus.OK);
    }


    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
            @Content(mediaType = "application/json", examples = {
                    @ExampleObject(name = "Sample Example..."
                            , summary = "결제취소정보"
                            , value = "{\"code\":\"Success\",\"message\":\"detail message(optional)\",\"body\":{\"responseCount\":1,\"totalCount\":1,\"totalPageCount\":1,\"currentPageNumber\":1,\"list\":[{\"cardAuthNo\":\"00000000\",\"bankAccountNo\":\"\",\"bankCorpCode\":\"\",\"paymentId\":\"20170000NP1000229665\",\"cardCorpCode\":\"C0\",\"cardInstCount\":0,\"usedCardPoint\":false,\"settleInfo\":{\"primaryCommissionAmount\":30,\"npointCommissionAmount\":20,\"giftCardCommissionAmount\":0,\"primarySettleAmount\":470,\"npointSettleAmount\":480,\"giftCardSettleAmount\":0,\"totalSettleAmount\":850,\"totalCommissionAmount\":50,\"settleCreated\":true},\"merchantName\":\"나의가맹점\",\"productName\":\"나의상품\",\"payHistId\":\"20170000NP1000229668\",\"merchantId\":\"MID12345\",\"admissionYmdt\":\"20170914163930\",\"tradeConfirmYmdt\":\"20170915163956\",\"totalPayAmount\":1000,\"merchantPayKey\":\"orderKey-91516397\",\"merchantUserKey\":\"빌러유저키\",\"admissionTypeCode\":\"01\",\"primaryPayMeans\":\"CARD\",\"admissionState\":\"SUCCESS\",\"primaryPayAmount\":500,\"npointPayAmount\":500,\"giftCardPayAmount\":0,\"taxScopeAmount\":1000,\"taxExScopeAmount\":0,\"environmentDepositAmount\":0,\"cardNo\":\"123456**********\",\"extraDeduction\":false,\"useCfmYmdt\":\"20180703\"}]}}")
            })
    })
    @Operation(summary = "결제취소정보 샘플")
    @PostMapping(value = "/bill/nv/ep/sample/cancelresult", produces = MediaType.APPLICATION_JSON_VALUE)
    @Override
    public ResponseEntity<Map<String, Object>> payCancel(@RequestBody Map<String, Object> param) {
        log.info("[Request Data] {}", param.toString());

        PayUseSysResCd resCd = PayUseSysResCd.OK;

        
        Map<String, Object> result = new HashMap<>();
        result.put("res_code", resCd.getCode());
        result.put("message", resCd.getCodeNm());
        result.put("data", null);

        return new ResponseEntity<Map<String, Object>>(result, HttpStatus.OK);
    }

}
