package com.oqpo.api.service.system;

import com.oqpo.api.entity.CodeEntity;
import com.oqpo.api.exception.GlobalException;
import com.oqpo.api.mapper.system.CodeMapper;
import com.oqpo.api.service.CommonService;
import com.oqpo.api.web.dto.request.GridRequest;
import com.oqpo.api.web.dto.request.code.SaveCodeRequest;
import com.oqpo.api.web.dto.response.GridResponse;
import com.oqpo.api.web.dto.response.code.CodeDtlResponse;
import com.oqpo.api.web.dto.response.code.CodeInfoResponse;
import com.oqpo.api.web.dto.response.code.CodeSearchListResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@Slf4j
public class CodeService extends CommonService {
    @Autowired
    private CodeMapper codeMapper;

   // @Cacheable(value = "codeList", key = "'OQKeyIs' + #userId")
    public List<CodeEntity> codeList(String userId) throws Exception {
        List<CodeEntity> entities = codeMapper.selectCodeList();
        entities.forEach(entity -> {
            entity.setCodeDtlList(codeMapper.selectCodeDtlList(entity.getCodeCd()));
        });
        return entities;
    }

    /*
        코드관리 - 코드 검색
     */
    public CodeSearchListResponse searchCodeList(String sCodeNm, String sCodeTpCd, String sUseYn) throws Exception {
        List<CodeEntity> entities = codeMapper.selectSearchCodeList(sCodeNm, sCodeTpCd, sUseYn);
        return CodeSearchListResponse.toDTO(entities);
    }

    /*
       코드 헤더 정보 조회
     */
    public CodeInfoResponse selectCodeInfo(String codeCd) throws Exception {
        return CodeInfoResponse.toDTO(codeMapper.selectCodeInfo(codeCd));
    }

    /*
      코드 상세 리스트 조회
     */
    public GridResponse codeDtlGridList(String codeCd, String useYn, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();
        int gridRecords = codeMapper.selectCodeDtlGridListCnt(codeCd);
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<CodeEntity> entities = codeMapper.selectCodeDtlGridList(codeCd, useYn, gridRequest);
        List<Object> gridRows = entities.stream()
                .map(m -> CodeDtlResponse.builder()
                        .viewCd("R")
                        .codeCd(m.getCodeCd())
                        .codeDtlCd(m.getCodeDtlCd())
                        .viewNum(m.getViewNum())
                        .codeDtlNm(m.getCodeDtlNm())
                        .codeDesc(m.getCodeDesc())
                        .useYn(m.getUseYn())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

    /*
       코드 중목체크
     */
    public  String selectCodeDupYn(String codeCd) throws Exception {
        return codeMapper.selectCodeDupYn(codeCd);
    }

    /*
      코드관리 - 저장
     */
    @CacheEvict(value = {"codeList"}, allEntries = true)
    @Transactional
    public void saveCode(String userId, SaveCodeRequest saveCodeRequest) throws Exception {
        try {
            // 기본정보 저장
            CodeEntity entity = new CodeEntity();
            entity.setCodeCd(saveCodeRequest.getCodeCd());
            entity.setCodeTpCd(saveCodeRequest.getCodeTpCd());
            entity.setCodeNm(saveCodeRequest.getCodeNm());
            entity.setUseYn(saveCodeRequest.getUseYn());

            if ("C".equals(saveCodeRequest.getViewCd())) {
                codeMapper.insertCodeInfo(userId, entity);
            } else if ("U".equals(saveCodeRequest.getViewCd())) {
                codeMapper.updateCodeInfo(userId, entity);
            }

            //  코드 상세 정보 저장
            // 신규건
            List<CodeEntity> gridInsertData = saveCodeRequest.toCodeEntities(saveCodeRequest.getGridInsertData());
            if (gridInsertData.size() > 0) {
                codeMapper.insertCodeDtl(userId, gridInsertData) ;
            }
            // 수정건
            List<CodeEntity> gridUpdateData = saveCodeRequest.toCodeEntities(saveCodeRequest.getGridUpdateData());
            if (gridUpdateData.size() > 0) {
                codeMapper.updateCodeDtl(userId, gridUpdateData) ;
            }
            // 삭제건
            List<CodeEntity> gridDeleteData = saveCodeRequest.toCodeEntities(saveCodeRequest.getGridDeleteData());
            if (gridDeleteData.size() > 0) {
                codeMapper.deleteCodeDtl(entity.getCodeCd(), gridDeleteData) ;
            }
        } catch (GlobalException e) {
            e.getStackTrace();
            throw new GlobalException(e.getSystemMessageCode());
        } catch (Exception e) {
            e.getStackTrace();
            throw new RuntimeException();
        }
    }
}
