package com.oqpo.api.service.stockmng;


import com.oqpo.api.entity.oper.UserMngEntity;
import com.oqpo.api.entity.stinfo.ItemEntity;
import com.oqpo.api.entity.stinfo.StoreBaseInfoEntity;
import com.oqpo.api.entity.stockmng.*;
import com.oqpo.api.enums.ChgDvsn;
import com.oqpo.api.enums.IfCode;
import com.oqpo.api.enums.InOutCd;
import com.oqpo.api.enums.SystemMessageCode;
import com.oqpo.api.exception.GlobalException;
import com.oqpo.api.mapper.stinfo.ItemMapper;
import com.oqpo.api.mapper.stockmng.StockMngMapper;
import com.oqpo.api.service.CommonService;
import com.oqpo.api.util.DateUtil;
import com.oqpo.api.web.dto.request.GridRequest;
import com.oqpo.api.web.dto.request.ifmng.BoSaleStoreInfoRequest;
import com.oqpo.api.web.dto.request.ifmng.BoStoreChgInfoRequest;
import com.oqpo.api.web.dto.request.stockmng.ProcStockRequest;
import com.oqpo.api.web.dto.request.stockmng.StockMngCddGridRequest;
import com.oqpo.api.web.dto.request.stockmng.StockMngPassQtyGridRequest;
import com.oqpo.api.web.dto.response.GridResponse;
import com.oqpo.api.web.dto.response.ifmng.BoStoreChgInfoResponse;
import com.oqpo.api.web.dto.response.stockmng.*;
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.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class StockMngService extends CommonService {

    @Autowired
    private StockMngMapper stockMngMapper;

    @Autowired
    private ItemMapper itemMapper;

    /*
      재고관리 그리드 리스트 조회
     */
    public GridResponse selectStockMngGridList(String sBrandId, String sStoreId, String sWhsId, String sLocation,
                                               String sItemStCd, String sItemType, String sItemGubun,
                                               String sItemClass1, String sItemClass2, String sItemClass3,
                                               String sItemClass4, String sItemId, String sItemNm, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();



        int gridRecords = stockMngMapper.selectStockMngGridCnt(sBrandId, sStoreId, sWhsId, sLocation,
                sItemStCd, sItemType, sItemGubun,
                sItemClass1, sItemClass2, sItemClass3, sItemClass4, sItemId, sItemNm);
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<StckMgntBaseInfoEntity> entities = stockMngMapper.selectStockMngGridList(sBrandId, sStoreId, sWhsId, sLocation,
                sItemStCd, sItemType, sItemGubun,
                sItemClass1, sItemClass2, sItemClass3, sItemClass4, sItemId, sItemNm, gridRequest);
        List<Object> gridRows = entities.stream()
                .map(m -> StockMngListResponse.builder()
                        .viewCd("R")
                        .brandId(m.getBrandId() == null ? "" : m.getBrandId())
                        .brandNm(m.getBrandNm() == null ? "" : m.getBrandNm())
                        .storeId(m.getStoreId() == null ? "" : m.getStoreId())
                        .storeNm(m.getStoreNm() == null ? "" : m.getStoreNm())
                        .whsId(m.getWhsId() == null ? "" : m.getWhsId())
                        .whsNm(m.getWhsNm() == null ? "" : m.getWhsNm())
                        .location(m.getLocation() == null ? "" : m.getLocation())
                        .locationNm(m.getLocationNm() == null ? "" : m.getLocationNm())
                        .itemId(m.getItemId() == null ? "" : m.getItemId())
                        .itemNm(m.getItemNm() == null ? "" : m.getItemNm())
                        .unit(m.getUnit() == null ? "" : m.getUnit())
                        .stckQty(m.getStckQty())
                        .prpStckQty(m.getPrpStckQty())
                        .sftStckRt(m.getSftStckRt())
                        .curStckRt(m.getCurStckRt())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

    /*
      재고실사 그리드 리스트 - 엑셀업로드 체크
     */
    public GridResponse selectStockCddGridList(StockMngCddGridRequest stockMngCddGridRequest, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();

        List<StckMgntBaseInfoEntity> entities = stockMngMapper.selectStockCddGridList(stockMngCddGridRequest.getBrandId(), stockMngCddGridRequest.getStoreId(),
                stockMngCddGridRequest.getWhsId(), stockMngCddGridRequest.getLocation(), stockMngCddGridRequest.getGridItemData());
        int gridRecords = entities.size();
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<Object> gridRows = entities.stream()
                .map(m -> StockMngListResponse.builder()
                        .viewCd("R")
                        .brandId(m.getBrandId())
                        .brandNm(m.getBrandNm())
                        .storeId(m.getStoreId())
                        .storeNm(m.getStoreNm())
                        .whsId(m.getWhsId())
                        .whsNm(m.getWhsNm())
                        .location(m.getLocation())
                        .locationNm(m.getLocationNm())
                        .itemId(m.getItemId())
                        .itemNm(m.getItemNm())
                        .unit(m.getUnit())
                        .stckQty(m.getStckQty())
                        .prpStckQty(m.getPrpStckQty())
                        .sftStckRt(m.getSftStckRt())
                        .curStckRt(m.getCurStckRt())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

    /* 재고관리 정보 조회 */
    public StockMngInfoResponse selectStockMngInfo(String brandId, String whsId, String location, String itemId) throws Exception {
        StckMgntBaseInfoEntity entity = stockMngMapper.selectStckMgntBaseInfo(brandId, whsId, location, itemId);
        return StockMngInfoResponse.toDTO(entity);
    }

    /*
      재고이력 그리드 리스트 조회
     */
    public GridResponse selectStockHistGridList(String sBrandId, String sWhsId, String sLocation,
                                                String sItemId, String sInoutCd, 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 = stockMngMapper.selectStockHistGridCnt(sBrandId, sWhsId, sLocation, sItemId, sInoutCd, fromDt, toDt);
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<StckMgntDtlHistEntity> entities = stockMngMapper.selectStockHistGridList(sBrandId, sWhsId, sLocation, sItemId, sInoutCd, fromDt, toDt, gridRequest);
        List<Object> gridRows = entities.stream()
                .map(m -> StockHistListResponse.builder()
                        .viewCd("R")
                        .inoutCd(m.getInoutCd())
                        .inoutNm(m.getInoutNm())
                        .inoutQty(m.getInoutQty())
                        .chgDvsn(m.getChgDvsn())
                        .chgDvsnNm(m.getChgDvsnNm())
                        .relationNo(m.getRelationNo())
                        .sysRegDttm(m.getSysRegDttm())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

    /* 재고 처리 */
    @Transactional
    public void procStock(String userId, ProcStockRequest procStockRequest) throws Exception {
        try {
            // 1-1. 소스 재고 정보 (stck_mgnt_base_info) 업데이트
            StckMgntBaseInfoEntity source = stockMngMapper.selectStckMgntBaseInfo(procStockRequest.getBrandId(), procStockRequest.getSourceWhsId(),
                    procStockRequest.getSourceLocation(), procStockRequest.getItemId());
            source.setStckQty(source.getStckQty() - procStockRequest.getMoveQty()); // 재고수량
            //double curStckRt = Math.round(source.getStckQty() * 100 / source.getPrpStckQty() * 100) / 100.0;
            //source.setCurStckRt(BigDecimal.valueOf(curStckRt)); // 현재고비율((재고수량 * 100) / 적정재고)

            stockMngMapper.updateStckMgntBaseInfo4StckProc(userId, source);

            // 1-2. 소스 이력 등록 (stck_mgnt_dtl_hist)
            StckMgntDtlHistEntity sourceHist = new StckMgntDtlHistEntity();
            sourceHist.setStckMgntDtlNo(fnGetDealNo(32, "")); // 재고관리상세번호
            sourceHist.setBrandId(source.getBrandId());
            sourceHist.setWhsId(source.getWhsId());
            sourceHist.setLocation(source.getLocation());
            sourceHist.setItemId(source.getItemId());
            sourceHist.setItemNm(source.getItemNm());
            sourceHist.setInoutCd(InOutCd.OUT.getCd()); // 출고
            sourceHist.setInoutQty(procStockRequest.getMoveQty());
            sourceHist.setChgDvsn(ChgDvsn.STOCK_MOVE.getCd()); // 재고이동
            stockMngMapper.insertStckMgntDtlHist(userId, sourceHist);

            // 2-1. 타겟 재고 정보 (stck_mgnt_base_info) 업데이트
            StckMgntBaseInfoEntity target = stockMngMapper.selectStckMgntBaseInfo(procStockRequest.getBrandId(), procStockRequest.getTargetWhsId(),
                    procStockRequest.getTargetLocation(), procStockRequest.getItemId());
            if (target == null) {
                target = new StckMgntBaseInfoEntity();
                target.setBrandId(procStockRequest.getBrandId());
                target.setWhsId(procStockRequest.getTargetWhsId());
                target.setLocation(procStockRequest.getTargetLocation());
                target.setItemId(procStockRequest.getItemId());
                target.setItemNm(source.getItemNm()); // 소스와 동일하게
                target.setUnit(source.getUnit()); // 소스와 동일하게
                target.setStckQty(procStockRequest.getMoveQty()); // 재고수량
                target.setPrpStckQty(source.getPrpStckQty()); // 소스와 동일하게
                target.setSftStckRt(source.getSftStckRt()); // 소스와 동일하게
                //curStckRt = Math.round(target.getStckQty() * 100 / target.getPrpStckQty() * 100) / 100.0;
                //target.setCurStckRt(BigDecimal.valueOf(curStckRt)); // 현재고비율((재고수량 * 100) / 적정재고)
                stockMngMapper.insertStckMgntBaseInfo(userId, target);
            } else {
                target.setStckQty(target.getStckQty() + procStockRequest.getMoveQty()); // 재고수량
                //curStckRt = Math.round(target.getStckQty() * 100 / target.getPrpStckQty() * 100) / 100.0;
                //target.setCurStckRt(BigDecimal.valueOf(curStckRt)); // 현재고비율((재고수량 * 100) / 적정재고)
                stockMngMapper.updateStckMgntBaseInfo4StckProc(userId, target);
            }

            // 2-2. 타겟 이력 등록 (stck_mgnt_dtl_hist)
            StckMgntDtlHistEntity targetHist = new StckMgntDtlHistEntity();
            targetHist.setStckMgntDtlNo(fnGetDealNo(32, "")); // 재고관리상세번호
            targetHist.setBrandId(target.getBrandId());
            targetHist.setWhsId(target.getWhsId());
            targetHist.setLocation(target.getLocation());
            targetHist.setItemId(target.getItemId());
            targetHist.setItemNm(target.getItemNm());
            targetHist.setInoutCd(InOutCd.IN.getCd()); // 입고
            targetHist.setInoutQty(procStockRequest.getMoveQty());
            targetHist.setChgDvsn(ChgDvsn.STOCK_MOVE.getCd()); // 재고이동
            stockMngMapper.insertStckMgntDtlHist(userId, targetHist);

        } catch (GlobalException e) {
            e.getStackTrace();
            throw new GlobalException(e.getSystemMessageCode());
        } catch (Exception e) {
            e.getStackTrace();
            throw new RuntimeException();
        }
    }

    public StockMngPassqtyListResponse selectWhsLocOutPassQty(String userId, StockMngPassQtyGridRequest stockMngPassQtyGridRequest) throws Exception {

        List<StckMgntBaseInfoEntity> gridItemList = stockMngPassQtyGridRequest.toCodeEntities(stockMngPassQtyGridRequest.getGridUpdateData());

        List<StckMgntBaseInfoEntity> entities = stockMngMapper.selectWhsLocOutPassQty(stockMngPassQtyGridRequest.getBrandId(),
                stockMngPassQtyGridRequest.getWhsId(), stockMngPassQtyGridRequest.getLocation(), gridItemList);

        return StockMngPassqtyListResponse.toDTO(entities);
    }


    /*
          재고관리 그리드 리스트 조회
         */
    public GridResponse selectPopItemStockMngGridList(String sBrandId, String sWhsId, String sLocation,
                                                String sItemNm, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();

        int gridRecords = stockMngMapper.selectPopItemStockMngGridCnt(sBrandId, sWhsId, sLocation, sItemNm);
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<StckMgntBaseInfoEntity> entities = stockMngMapper.selectPopItemStockMngGridList(sBrandId, sWhsId, sLocation, sItemNm, gridRequest);
        List<Object> gridRows = entities.stream()
                .map(m -> PopItemWhsStockListResponse.builder()
                        .viewCd("R")
                        .brandId(m.getBrandId())
                        .brandNm(m.getBrandNm())
                        .itemId(m.getItemId())
                        .itemNm(m.getItemNm())
                        .unit(m.getUnit())
                        .stckQty(m.getStckQty())
                        .waitQty(m.getWaitQty())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

    /* 바코드 품목 정보 조회 */
    public BarcodeWhsItemInfoResponse selectBarcodeWhsItemMngInfo(String sBrandId, String sWhsId, String sLocation, String sBarcode) throws Exception {
        StckMgntBaseInfoEntity entity = stockMngMapper.selectPopItemStockInfo(sBrandId, sWhsId, sLocation, sBarcode);
        return BarcodeWhsItemInfoResponse.toDTO(entity);
    }

    /* 창고 품목 정보 조회 */
    public GridResponse selectWhsLocationItemList(String brandId, String whsId, String location, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();

        List<StckMgntBaseInfoEntity> entities = stockMngMapper.selectWhsLocationItemList(brandId, whsId, location);
        int gridRecords = entities.size();
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);

        List<Object> gridRows = entities.stream()
                .map(m -> WhsItemInfoResponse.builder()
                        .itemId(m.getItemId())
                        .itemNm(m.getItemNm())
                        .excelQty(m.getExcelQty())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

    /* 창고 품목 정보 조회 */
    public GridResponse selectWhsLocationItemList4Excel(String brandId, String whsId, String location, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();

        List<StckMgntBaseInfoEntity> entities = stockMngMapper.selectWhsLocationItemList(brandId, whsId, location);
        if (entities.size() < 1) {
            entities = new ArrayList<>();
            StckMgntBaseInfoEntity entity = new StckMgntBaseInfoEntity();
            entities.add(entity);
        }

        int gridRecords = entities.size();
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<Object> gridRows = entities.stream()
                .map(m -> WhsItemInfoExcelResponse.builder()
                        .품목번호(m.getItemId())
                        .품목명(m.getItemNm())
                        .실사수량(m.getExcelQty())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }



    /*
   백오피스 판매정보 수신
   */
    @Transactional
    public BoSaleStoreStockResponse ifBoSaveStoreStock(String userId, BoSaleStoreInfoRequest boSaleStoreInfoRequest) throws Exception {

        try {
            String brandCd = boSaleStoreInfoRequest.getBrandCd();
            String storeNo = boSaleStoreInfoRequest.getStoreNo();
            String saleDt = boSaleStoreInfoRequest.getSaleDt() ;
            String baseYm = "";

            if (saleDt == null || saleDt.equals("")) {
                baseYm = DateUtil.getCurrentYearMonth() + "01";
            } else {
                baseYm = saleDt.substring(0,6) + "01";
            }

            StckMgntBaseInfoEntity  whsInfoEntity = stockMngMapper.selectBoWhsInfo(brandCd, storeNo);
            if (whsInfoEntity == null) {
                throw new GlobalException(SystemMessageCode.ERR_BO_STORE);
            }

            List<StckSaleMgntDtlHistEntity> hisList = new ArrayList<StckSaleMgntDtlHistEntity>();
            List<StckMgntBaseInfoEntity> stckList = new ArrayList<StckMgntBaseInfoEntity>();
            List<BoSaleInfoEntity> saleList = boSaleStoreInfoRequest.toCodeEntities(boSaleStoreInfoRequest.getSaleList());

            BoSaleInfoResultEntity boSaleInfo = new BoSaleInfoResultEntity();
            List<BoSaleProcResultEntity > resultList = new ArrayList<BoSaleProcResultEntity>();

            boSaleInfo.setBrandCd(brandCd);
            boSaleInfo.setStoreNo(storeNo);

            int notFindItemCnt = 0 ;

            if (saleList.size() > 0) {
                for (int i = 0 ; i < saleList.size() ; i++ ) {

                    BoSaleProcResultEntity retEntity = new BoSaleProcResultEntity();

                    BoSaleInfoEntity saleEntity = saleList.get(i);
                    ItemEntity itemInfo =   itemMapper.selectOqToItemId(whsInfoEntity.getBrandId(), saleEntity.getMenuCd());

                    if (itemInfo == null || "".equals(itemInfo.getItemId())) {
                        notFindItemCnt = notFindItemCnt + 1 ;
                        retEntity.setMenuCd(saleEntity.getMenuCd());
                        retEntity.setItemId("");
                        retEntity.setProcCd("01");

                    } else {
                        StckSaleMgntDtlHistEntity stckInfo = new StckSaleMgntDtlHistEntity();
                        stckInfo.setBrandId(whsInfoEntity.getBrandId());
                        stckInfo.setWhsId(whsInfoEntity.getWhsId());
                        stckInfo.setLocation(whsInfoEntity.getLocation());
                        stckInfo.setItemId(itemInfo.getItemId());
                        stckInfo.setItemNm(itemInfo.getItemNm());
                        stckInfo.setBaseYm(baseYm);
                        stckInfo.setSaleQty(saleEntity.getSaleCnt());
                        stckInfo.setOqBrandId(brandCd);
                        stckInfo.setOqMenuCd(saleEntity.getMenuCd());
                        hisList.add(stckInfo);

                        StckMgntBaseInfoEntity stckBaseInfo = new StckMgntBaseInfoEntity();
                        stckBaseInfo.setBrandId(whsInfoEntity.getBrandId());
                        stckBaseInfo.setWhsId(whsInfoEntity.getWhsId());
                        stckBaseInfo.setLocation(whsInfoEntity.getLocation());
                        stckBaseInfo.setItemId(itemInfo.getItemId());
                        stckBaseInfo.setStckQty(saleEntity.getSaleCnt());
                        stckList.add(stckBaseInfo);

                        retEntity.setMenuCd(saleEntity.getMenuCd());
                        retEntity.setItemId(itemInfo.getItemId());
                        retEntity.setProcCd("00");
                    }
                    resultList.add(retEntity);
                }

                if (hisList.size() > 0) {
                    stockMngMapper.insertStckSaleMgntDtlHist(userId,hisList );
                    stockMngMapper.insertInOutStckMgntBaseInfo(userId,stckList );
                }
            }

            if (notFindItemCnt > 0 ) {
                if (notFindItemCnt == saleList.size() ) {
                    boSaleInfo.setCode(IfCode.S03.getCd());
                    boSaleInfo.setMessage(IfCode.S03.getName());
                } else {
                    boSaleInfo.setCode(IfCode.S02.getCd());
                    boSaleInfo.setMessage(IfCode.S02.getName());
                }
            } else {
                boSaleInfo.setCode(IfCode.S01.getCd());
                boSaleInfo.setMessage(IfCode.S01.getName());
            }



            return BoSaleStoreStockResponse.toDTO(boSaleInfo, resultList);
        } catch (GlobalException e) {
            e.getStackTrace();
            throw new GlobalException(e.getSystemMessageCode());
        } catch (Exception e) {
            e.getStackTrace();
            throw new RuntimeException();
        }
    }
}
