package cokr.xit.ens.modules.common.ctgy.intgrnbill.support;

import cokr.xit.ens.core.aop.EnsResponseVO;
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.intgrnbill.support.entity.Bill;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.entity.QBill;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.trigger.PaymentTriggerService;
import cokr.xit.ens.modules.common.ctgy.intgrnbill.support.service.trigger.PaymentTriggerServiceFactory;
import cokr.xit.ens.modules.common.ctgy.sys.mng.domain.QOrgMng;
import com.querydsl.jpa.impl.JPAQueryFactory;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

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

@Tag(name = "PaymentTriggerController")
@Slf4j
@RestController
@RequiredArgsConstructor
public class PaymentTriggerController {

    private final JPAQueryFactory query;
    private final PaymentTriggerServiceFactory paymentTriggerServiceFactory;

    @CrossOrigin(origins = "*")
//    @CrossOrigin(origins = {"http://localhost:8080", "https://localhost:8080"})  
//    @CrossOrigin(originPatterns = {"http:**", "https:**"})  
    @Parameters({
            @Parameter(name = "paySe", example = "kko", required = true, in = ParameterIn.PATH),
            @Parameter(name = "billUid", example = "청구서UID", required = true, in = ParameterIn.PATH)
    })
    @Operation(summary = "납부(결제)정보 요청")
    @GetMapping(value = "/bill/pay/trg/{paySe}/{billUid}/payinf", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity payInfo(@PathVariable String paySe, @PathVariable String billUid) {

        EnsResponseVO<Map<String, Object>> result = null;
        try {
           
            if (Arrays.stream(PaymentTriggerServiceFactory.PTriggerPaySe.values()).noneMatch(pTriggerPaySe -> pTriggerPaySe.name().equals(paySe)))
                throw new EnsException(EnsErrCd.INVALID_REQUEST_URL, EnsErrCd.INVALID_REQUEST_URL.getCodeNm());
            final PaymentTriggerServiceFactory.PTriggerPaySe pTriggerPaySe = PaymentTriggerServiceFactory.PTriggerPaySe.valueOf(paySe);

            
            Bill bill = Optional.ofNullable(query.selectFrom(QBill.bill).leftJoin(QBill.bill.orgMng, QOrgMng.orgMng).fetchJoin().where(QBill.bill.billUid.eq(billUid)).fetchOne())
                    .filter(entity -> entity != null)
                    .map(entity -> {
                        if (entity.getPaidAt()) {
                            throw new EnsException(EnsErrCd.PAYMENT_ALREADY_CMPLTED
                                    , String.format("%s\n  -.결제수단: %s\n  -.결제일시: %s"
                                    , EnsErrCd.PAYMENT_ALREADY_CMPLTED.getCodeNm(), entity.getPaidType().getCodeNm(), entity.getPaidDt()));
                        }
                        return entity;
                    })
                    .orElseThrow(() -> new EnsException(EnsErrCd.NO_DATA_FOUND, "청구 자료를 찾을 수 없습니다."));
            
            if (CmmnUtil.isEmpty(bill.getOrgMng()))
                throw new EnsException(EnsErrCd.NO_DATA_FOUND, "청구결제 위탁기관을 찾을 수 없습니다.");

            
            Map<PaymentTriggerService.PTriggerDataKeys, Object> param = new HashMap<>();
            param.put(PaymentTriggerService.PTriggerDataKeys.bill, bill);
            param.put(PaymentTriggerService.PTriggerDataKeys.billUid, billUid);

            
            result = EnsResponseVO.<Map<String, Object>>okBuilder()
                    .resultInfo(paymentTriggerServiceFactory.getService(pTriggerPaySe).payInfo(param))
                    .build();
        } catch (EnsException e) {
            result = EnsResponseVO.<Map<String, Object>>errBuilder()
                    .errCode(e.getErrCd())
                    .errMsg(e.getMessage())
                    .build();
        }


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