package com.oqpo.api.service.sttlmng;


import com.oqpo.api.entity.loanmng.LoanMgntBaseInfoEntity;
import com.oqpo.api.entity.loanmng.LoanMgntDtlHstEntity;
import com.oqpo.api.entity.oper.UserMngEntity;
import com.oqpo.api.entity.rtnmng.RtnProcInfoPtclEntity;
import com.oqpo.api.entity.settmng.StlMgntBaseInfoEntity;
import com.oqpo.api.entity.settmng.StlMgntDtlPtclEntity;
import com.oqpo.api.entity.stinfo.StoreBaseInfoEntity;
import com.oqpo.api.entity.stockmng.WhsProcInfoPtclEntity;
import com.oqpo.api.enums.*;
import com.oqpo.api.mapper.loanmng.DsptMngMapper;
import com.oqpo.api.mapper.oper.UserMngMapper;
import com.oqpo.api.mapper.stinfo.StoreBaseInfoMapper;
import com.oqpo.api.mapper.sttlmng.SttlReqMapper;
import com.oqpo.api.service.CommonService;
import com.oqpo.api.util.DateUtil;
import com.oqpo.api.util.StringUtil;
import com.oqpo.api.web.dto.request.GridRequest;
import com.oqpo.api.web.dto.request.loanmng.ApproveDsptRequest;
import com.oqpo.api.web.dto.request.sttlmng.SttlReqData;
import com.oqpo.api.web.dto.request.sttlmng.SttlReqProcData;
import com.oqpo.api.web.dto.request.sttlmng.SttlReqProcRequest;
import com.oqpo.api.web.dto.request.sttlmng.SttlReqRequest;
import com.oqpo.api.web.dto.response.GridResponse;
import com.oqpo.api.web.dto.response.loanmng.StlDtlListResponse;
import com.oqpo.api.web.dto.response.sttlmng.SttlMngInfoResponse;
import com.oqpo.api.web.dto.response.sttlmng.SttlReqResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SttlReqService extends CommonService {

    @Autowired
    private SttlReqMapper sttlReqMapper;

    @Autowired
    private UserMngMapper userMngMapper;

    @Autowired
    private StoreBaseInfoMapper storeBaseInfoMapper;

    @Autowired
    private DsptMngMapper dsptMngMapper;

    /*
      정산요청 그리드 리스트 조회
     */
    public GridResponse selectSttlReqGridList(String sBrandId, String sStoreId, String sSpplyId, String sItemNm, String fromDt, String toDt, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();

        fromDt = fromDt == null ? null : fromDt.replace(".", "");
        toDt = toDt == null ? null : toDt.replace(".", "");

        int gridRecords = sttlReqMapper.selectSttlReqGridCnt(sBrandId, sStoreId, sSpplyId, sItemNm, fromDt, toDt);
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<StlMgntDtlPtclEntity> entities = sttlReqMapper.selectSttlReqGridList(sBrandId, sStoreId, sSpplyId, sItemNm, fromDt, toDt, gridRequest);
        List<Object> gridRows = entities.stream()
                .map(m -> StlDtlListResponse.builder()
                        .viewCd("R")
                        .sttlMgntUnqNo(m.getSttlMgntUnqNo())        /* 정산관리고유번호 */
                        .sttlMgntDtlNo(m.getSttlMgntDtlNo())        /* 정산관리상세번호 */
                        .brandId(m.getBrandId())
                        .brandNm(m.getBrandNm())
                        .storeId(m.getStoreId())
                        .storeNm(m.getStoreNm())
                        .spplyId(m.getSpplyId())
                        .spplyNm(m.getSpplyNm())
                        .loanDvsn(m.getLoanDvsn())                  /* 여신구분 : 선불/후불/무정산 */
                        .loanDvsnNm(m.getLoanDvsnNm())
                        .sttlStCd(m.getSttlStCd())                  /* 정산상태코드 */
                        .sttlStNm(m.getSttlStNm())                  /* 정산상태명 */
                        .itemId(m.getItemId())
                        .itemNm(m.getItemNm())
                        .unit(m.getUnit())
                        .unitAmt(m.getUnitAmt())
                        .podrQty(m.getPodrQty())                    /* 발주수량 */
                        .dlvQty(m.getDlvQty())                      /* 납품수량 */
                        .whsColQty(m.getWhsColQty())                /* 입고/수거수량 */
                        .whsColDt(m.getWhsColDt())                  /* 입고/수거일자 */
                        .whsColAmt(m.getWhsColAmt())                /* 입고/수거금액 */
                        .sttlDvsn(m.getSttlDvsn())                  /* 정산구분 : 수거/입고 */
                        .sttlDvsnNm(m.getSttlDvsnNm())              /* 정산구분명 */
                        .podrUnqNo(m.getPodrUnqNo())                /* 구매발주고유번호 */
                        .podrDtlNo(m.getPodrDtlNo())                /* 구매발주상세번호 */
                        .mgntUnqNo(m.getMgntUnqNo())                /* 입고/반품관리고유번호 */
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

    /* 정산요청 */
    @Transactional
    public SttlReqResponse requestSttl(String userId, SttlReqRequest sttlReqRequest) throws Exception {
        // 사용자 정보 조회
        UserMngEntity user = userMngMapper.selectUserInfo(userId);

        // 정산관리고유번호(STTL_MGNT_UNQ_NO) 채번
        String sttlMgntUnqNo = fnGetDealNo(37, "");

        List<SttlReqData> sttlReqDataList = sttlReqRequest.getSttlReqDataList();
        int idx = 1; // 정산관리상세번호
        long sttlReqAmt = 0; // 정산요청금액
        for (SttlReqData item : sttlReqDataList) {
            // 기존 정산 요청건인 경우 정산상태를 체크한다.
            if (!StringUtil.isEmpty(item.getSttlMgntUnqNo()) && !StringUtil.isEmpty(item.getSttlMgntDtlNo())) {
                StlMgntDtlPtclEntity dtlPtcl = sttlReqMapper.selectStlMgntDtlPtcl(item.getSttlMgntUnqNo(), item.getSttlMgntDtlNo());
                // 정산요청/정산확정된 경우 제외함
                if (SttlStCd.STTL_REQ.getCd().equals(dtlPtcl.getSttlStCd()) || SttlStCd.STTL_CONFIRM.getCd().equals(dtlPtcl.getSttlStCd())) {
                    continue;
                }
            }
            // 입고/수거에 따라 데이터 조회
            if (SttlDvsn.WHS.getCd().equals(item.getSttlDvsn())) {
                WhsProcInfoPtclEntity procInfo = sttlReqMapper.selectWhsProcInfoPtcl(item.getMgntUnqNo());
                // 입고 데이터 업데이트
                procInfo.setSttlMgntUnqNo(sttlMgntUnqNo);
                procInfo.setSttlMgntDtlNo(idx + "");
                sttlReqMapper.updateWhsProcInfoPtcl4SttlReq(userId, procInfo);

                // 정산요청금액
                sttlReqAmt += procInfo.getWhsAmt(); // 입고금액

                // 정산관리상세내역 저장
                StlMgntDtlPtclEntity entity = new StlMgntDtlPtclEntity();
                entity.setSttlMgntUnqNo(sttlMgntUnqNo); // 정산관리고유번호
                entity.setSttlMgntDtlNo(idx + ""); // 정산관리상세번호
                entity.setBrandId(procInfo.getBrandId()); // 브랜드아이디
                entity.setWhsMgntUnqNo(procInfo.getWhsMgntUnqNo()); // 입고관리고유번호
                entity.setStoreId(procInfo.getStoreId()); // 매장아이디
                entity.setSpplyId(procInfo.getSpplyId()); // TODO 공급사아이디
                entity.setItemId(procInfo.getItemId()); // 품목아이디
                entity.setItemNm(procInfo.getItemNm()); // 품목명
                entity.setUnit(procInfo.getUnit()); // 단위
                entity.setUnitAmt(procInfo.getUnitAmt().longValue()); // 단가금액
                entity.setPodrQty(procInfo.getPodrQty()); // 발주수량
                entity.setDlvQty(procInfo.getDlvQty()); // 납품수량
                entity.setWhsQty(procInfo.getWhsQty()); // 입고수량
                entity.setDlvCmpltDt(procInfo.getDlvCmpltDt()); // 납품완료일자
                entity.setWhsAmt(procInfo.getWhsAmt().longValue()); // 입고금액
                entity.setSttlDvsn(SttlDvsn.WHS.getCd()); // 정산구분 - 입고
                entity.setPchPodrUnqNo(procInfo.getPchPodrUnqNo()); // 구매발주고유번호
                entity.setPchPodrDtlNo(procInfo.getPchPodrDtlNo()); // 구매발주상세번호
                entity.setPchReqUnqNo(procInfo.getPchReqUnqNo()); // 구매요청고유번호
                entity.setPchReqDtlNo(procInfo.getPchReqDtlNo()); // 구매요청상세번호
                sttlReqMapper.insertStlMgntDtlPtcl(userId, entity);
            } else if (SttlDvsn.RTN.getCd().equals(item.getSttlDvsn())) {
                RtnProcInfoPtclEntity procInfo = sttlReqMapper.selectRtnProcInfoPtcl(item.getMgntUnqNo());

                // 수거 데이터 업데이트
                procInfo.setSttlMgntUnqNo(sttlMgntUnqNo);
                procInfo.setSttlMgntDtlNo(idx + "");
                sttlReqMapper.updateRtnProcInfoPtcl4SttlReq(userId, procInfo);

                // 정산요청금액
                sttlReqAmt += procInfo.getColAmt(); // 수거금액

                // 정산관리상세내역 저장
                StlMgntDtlPtclEntity entity = new StlMgntDtlPtclEntity();
                entity.setSttlMgntUnqNo(sttlMgntUnqNo); // 정산관리고유번호
                entity.setSttlMgntDtlNo(idx + ""); // 정산관리상세번호
                entity.setBrandId(procInfo.getBrandId()); // 브랜드아이디
                entity.setRtnMgntUnqNo(procInfo.getRtnMgntUnqNo()); // 반품관리고유번호
                entity.setStoreId(procInfo.getStoreId()); // 매장아이디
                entity.setSpplyId(procInfo.getSpplyId()); // TODO 공급사아이디
                entity.setItemId(procInfo.getItemId()); // 품목아이디
                entity.setItemNm(procInfo.getItemNm()); // 품목명
                entity.setUnit(procInfo.getUnit()); // 단위
                entity.setUnitAmt(procInfo.getUnitAmt()); // 단가금액
                entity.setPodrQty(procInfo.getRtnOdrQty()); // 발주수량
                entity.setDlvQty(procInfo.getColReqQty()); // 납품수량
                entity.setWhsQty(null); // 입고수량
                entity.setColQty(procInfo.getColQty()); // 수거수량
                entity.setColDt(procInfo.getColDt()); // 수거일자
                entity.setColAmt(procInfo.getColAmt()); // 수거금액
                entity.setSttlDvsn(SttlDvsn.RTN.getCd()); // 정산구분 - 수거
                entity.setRtnPodrUnqNo(procInfo.getRtnPodrUnqNo()); // 반품발주고유번호
                entity.setRtnPodrDtlNo(procInfo.getRtnPodrDtlNo()); // 반품발주상세번호
                entity.setRtnReqUnqNo(procInfo.getRtnReqUnqNo()); // 반품요청고유번호
                entity.setRtnReqDtlNo(procInfo.getRtnReqDtlNo()); // 반품요청상세번호
                sttlReqMapper.insertStlMgntDtlPtcl(userId, entity);
            }
            idx++;
        }
        // 정산관리기본정보 저장
        StlMgntBaseInfoEntity baseInfo = new StlMgntBaseInfoEntity();
        baseInfo.setSttlMgntUnqNo(sttlMgntUnqNo);
        baseInfo.setBrandId(sttlReqRequest.getBrandId());
        baseInfo.setStoreId(sttlReqRequest.getStoreId());
        baseInfo.setSpplyId(sttlReqRequest.getSpplyId()); // TODO 공급사아이디
        baseInfo.setSttlStCd(SttlStCd.TEMP_SAVE.getCd());
        baseInfo.setSttlReqAmt(sttlReqAmt);
        baseInfo.setSttlRegMgrId(userId);
        baseInfo.setSttlRegMgrNm(user.getUserNm());
        if (!StringUtil.isEmpty(sttlReqRequest.getStoreId())) {
            baseInfo.setSttlTargetCd(SttlTargetCd.STORE_STTL.getCd()); // 매장정산
        } else if (!StringUtil.isEmpty(sttlReqRequest.getSpplyId())) {
            baseInfo.setSttlTargetCd(SttlTargetCd.SUPPLY_STTL.getCd()); // 공급사정산
        }
        sttlReqMapper.insertStlMgntBaseInfo(userId, baseInfo);
        return SttlReqResponse.toDTO(baseInfo);
    }

    /* 정산요청  처리 */
    @Transactional
    public void procSttlRequest(String userId, SttlReqProcRequest sttlReqProcRequest) throws Exception {

        if (!StringUtil.isEmpty(sttlReqProcRequest.getStoreId())) { // 매장 정산
            procSttlRequest4Store(userId, sttlReqProcRequest);
        } else if (!StringUtil.isEmpty(sttlReqProcRequest.getSpplyId())) { // 공급사 정산
            // 공급사 정산은 후불로 조치한다.
            procSttlRequest4Spply(userId, sttlReqProcRequest);
        }
    }

    private void procSttlRequest4Spply(String userId, SttlReqProcRequest sttlReqProcRequest) throws Exception {
        StlMgntBaseInfoEntity baseInfo = new StlMgntBaseInfoEntity();
        baseInfo.setSttlMgntUnqNo(sttlReqProcRequest.getSttlMgntUnqNo());
        baseInfo.setSttlStCd(SttlStCd.STTL_REQ.getCd());
        baseInfo.setSttlReqDt(sttlReqProcRequest.getSttlReqDt().replace(".", ""));
        baseInfo.setSttlDt(null);
        baseInfo.setSttlAmt(null);
        sttlReqMapper.updateStlMgntBaseInfo4SttlReqProc(userId, baseInfo);
    }

    private void procSttlRequest4Store(String userId, SttlReqProcRequest sttlReqProcRequest) throws Exception {
        // 매장 정산타입 조회
        StoreBaseInfoEntity storeInfo = storeBaseInfoMapper.selectStoreInfo(sttlReqProcRequest.getBrandId(), sttlReqProcRequest.getStoreId());

        long sttlAmt = 0; // 정산금액
        // 정산타입에 따라
        if (LoanDvsn.PRE_PAYMENT.getCd().equals(storeInfo.getLoanDvsn())) {
            // 1. 선불
            // 정산관리상세내역 처리
            List<SttlReqProcData> list = sttlReqProcRequest.getSttlReqDataList();
            for (SttlReqProcData item : list) {
                // 정산관리상세내역 조회
                StlMgntDtlPtclEntity dtlPtcl = sttlReqMapper.selectStlMgntDtlPtcl(sttlReqProcRequest.getSttlMgntUnqNo(), item.getSttlMgntDtlNo());
                // 정산금액
                sttlAmt += dtlPtcl.getWhsColAmt();

                // 정산구분에 따라 처리 (STTL_DVSN)
                if (SttlDvsn.WHS.getCd().equals(dtlPtcl.getSttlDvsn())) { // 입고
                    // 입고처리정보내역 업데이트
                    sttlReqMapper.updateWhsProcInfoPtcl4SttlReqProc(userId, dtlPtcl);
                } else if (SttlDvsn.RTN.getCd().equals(dtlPtcl.getSttlDvsn())) { // 수거
                    // 반품처리정보내역 업데이트
                    sttlReqMapper.updateRtnProcInfoPtcl4SttlReqProc(userId, dtlPtcl);
                }
            }

            // 여신관리기본정보(매장) 차감 : loan_mgnt_base_info
            // 매장의 여신관리기본정보 조회 - 없으면 에러 처리
            LoanMgntBaseInfoEntity loanBase = dsptMngMapper.selectLoanMgntBaseInfo(sttlReqProcRequest.getBrandId(), sttlReqProcRequest.getStoreId());
            long trscBfBal = loanBase.getAcctBal();
            long trscAfBal = loanBase.getAcctBal() - sttlAmt;       // 잔액에서 입고/수거금액 차감
            long useAmtTotal = loanBase.getUseAmtTotal() - sttlAmt; // 사용금액합계에서 입고/수거금액 차감

            loanBase.setAcctBal(trscAfBal);
            loanBase.setUseAmtTotal(useAmtTotal);
            sttlReqMapper.updateLoanMgntBaseInfo4SttlReqProc(userId, loanBase);

            // 여신관리상세이력 등록 (지급/대체/정산지급)
            // 여신관리상세이력 등록
            LoanMgntDtlHstEntity hstEntity = new LoanMgntDtlHstEntity();
            hstEntity.setLoanMgntUnqNo(storeInfo.getLoanMgntUnqNo());
            hstEntity.setLoanRegDt(DateUtil.getCurrentDate());
            hstEntity.setLoanRegTm(DateUtil.getCurrentTime());
            hstEntity.setDpstPayDvsn(DpstPayDvsn.PAYMENT.getCd());
            hstEntity.setMediaDvsn(MediaDvsn.SETTLMENT.getCd());
            hstEntity.setPayType(PayType.STTL_PAY.getCd());
            hstEntity.setTrscAmt(sttlAmt); // 거래금액
            hstEntity.setPaymAmt(sttlAmt); // 지급금액
            hstEntity.setTrscBfBal(trscBfBal);
            hstEntity.setTrscAfBal(trscAfBal);
            dsptMngMapper.insertLoanMgntDtlHst(userId, hstEntity);

        } else if (LoanDvsn.POST_PAYMENT.getCd().equals(storeInfo.getLoanDvsn())) {
            // 2. 후불
            // 정산상태코드만 변경하고 매장에서 정상확정시 여신처리를 한다.
        }

        // 정산관리기본정보 업데이트 (정산상태코드)
        // 정산타입에 따라
        if (LoanDvsn.PRE_PAYMENT.getCd().equals(storeInfo.getLoanDvsn())) {
            StlMgntBaseInfoEntity baseInfo = new StlMgntBaseInfoEntity();
            baseInfo.setSttlMgntUnqNo(sttlReqProcRequest.getSttlMgntUnqNo());
            baseInfo.setSttlStCd(SttlStCd.STTL_CONFIRM.getCd());
            baseInfo.setSttlReqDt(sttlReqProcRequest.getSttlReqDt().replace(".", ""));
            baseInfo.setSttlDt(DateUtil.getCurrentDate());
            baseInfo.setSttlAmt(sttlAmt);
            sttlReqMapper.updateStlMgntBaseInfo4SttlReqProc(userId, baseInfo);
        } else if (LoanDvsn.POST_PAYMENT.getCd().equals(storeInfo.getLoanDvsn())) {
            StlMgntBaseInfoEntity baseInfo = new StlMgntBaseInfoEntity();
            baseInfo.setSttlMgntUnqNo(sttlReqProcRequest.getSttlMgntUnqNo());
            baseInfo.setSttlStCd(SttlStCd.STTL_REQ.getCd());
            baseInfo.setSttlReqDt(sttlReqProcRequest.getSttlReqDt().replace(".", ""));
            baseInfo.setSttlDt(null);
            baseInfo.setSttlAmt(null);
            sttlReqMapper.updateStlMgntBaseInfo4SttlReqProc(userId, baseInfo);
        }
    }

    /* 정산요청 정보 조회 */
    public SttlMngInfoResponse selectSttlReqInfo(String sttlMgntUnqNo) throws Exception {
        StlMgntBaseInfoEntity entity = sttlReqMapper.selectStlMgntBaseInfo(sttlMgntUnqNo);
        return SttlMngInfoResponse.toDTO(entity);
    }

    /*
      정산대상내역 그리드 리스트 조회
     */
    public GridResponse selectStlDtlGridList(String sttlMgntUnqNo, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();

        List<StlMgntDtlPtclEntity> entities = sttlReqMapper.selectStlMgntDtlPtclList(sttlMgntUnqNo);
        int gridRecords = entities.size();
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<Object> gridRows = entities.stream()
                .map(m -> StlDtlListResponse.builder()
                        .viewCd("R")
                        .sttlMgntUnqNo(m.getSttlMgntUnqNo())
                        .sttlMgntDtlNo(m.getSttlMgntDtlNo())
                        .brandId(m.getBrandId())
                        .brandNm(m.getBrandNm())
                        .whsMgntUnqNo(m.getWhsMgntUnqNo())
                        .rtnMgntUnqNo(m.getRtnMgntUnqNo())
                        .storeId(m.getStoreId())
                        .storeNm(m.getStoreNm())
                        .itemId(m.getItemId())
                        .itemNm(m.getItemNm())
                        .unit(m.getUnit())
                        .unitAmt(m.getUnitAmt())
                        .podrQty(m.getPodrQty())
                        .dlvQty(m.getDlvQty())
                        .whsQty(m.getWhsQty())
                        .colQty(m.getColQty())
                        .whsColQty(m.getWhsColQty())        /* 입고/수거수량 */
                        .dlvCmpltDt(m.getDlvCmpltDt())
                        .colDt(m.getColDt())
                        .whsColDt(m.getWhsColDt())          /* 입고/수거일자 */
                        .whsAmt(m.getWhsAmt())
                        .colAmt(m.getColAmt())
                        .whsColAmt(m.getWhsColAmt())        /* 입고/수거금액 */
                        .sttlDvsn(m.getSttlDvsn())
                        .sttlDvsnNm(m.getSttlDvsnNm())
                        .podrUnqNo(m.getPodrUnqNo())        /* 발주번호 */
                        .podrDtlNo(m.getPodrDtlNo())        /* 발주항번 */
                        .pchReqUnqNo(m.getPchReqUnqNo())
                        .pchReqDtlNo(m.getPchReqDtlNo())
                        .rtnPodrUnqNo(m.getRtnPodrUnqNo())
                        .rtnPodrDtlNo(m.getRtnPodrDtlNo())
                        .rtnReqUnqNo(m.getRtnReqUnqNo())
                        .rtnReqDtlNo(m.getRtnReqDtlNo())
                        .sysRegDttm(m.getSysRegDttm())
                        .sysRegId(m.getSysRegId())
                        .sysChgDttm(m.getSysChgDttm())
                        .sysChgId(m.getSysChgId())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

}
