package incheon.ags.ias.linkData.service.impl;

import incheon.ags.ias.linkData.mapper.LinkDataMapper;
import incheon.ags.ias.linkData.service.LinkDataService;
import incheon.ags.ias.linkData.vo.LinkDataSearchVO;
import incheon.ags.ias.linkData.vo.LinkDataVO;
import incheon.ags.ias.linkData.web.dto.LinkDataRequestDTO;
import incheon.com.cmm.exception.BusinessException;
import incheon.com.file.service.ComFileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

@Slf4j
@Service("linkDataService")
@RequiredArgsConstructor
public class LinkDataServiceImpl extends EgovAbstractServiceImpl implements LinkDataService {
    private final LinkDataMapper linkDataMapper;
    private final ComFileService comFileService;
    
    @Value("${Globals.comfile.storage.path:../upload}")
    private String uploadPath;

    @Override
    public List<Map<String,Object>> selectLinkDataList(LinkDataSearchVO linkDataSearchVO) throws Exception{
        return linkDataMapper.selectLinkDataList(linkDataSearchVO);
    }

    @Override
    public LinkDataVO selectLinkDataDetail(LinkDataVO linkDataVO) throws Exception {
        return linkDataMapper.selectLinkDataDetail(linkDataVO);
    }

    @Override
    public List<Map<String,Object>> selectSysList() throws Exception {
        return linkDataMapper.selectSysList();
    }

    @Override
    public
    List<Map<String,Object>> selectMetDataWithLinkId(LinkDataVO linkDataVO) throws Exception {
        return linkDataMapper.selectMetDataWithLinkId(linkDataVO);
    }

    @Override
    public List<Map<String,Object>> selectMetDataDmndHeader(LinkDataVO linkDataVO) throws Exception {
        return linkDataMapper.selectMetDataDmndHeader(linkDataVO);
    }

    @Override
    public List<Map<String,Object>> selectMetDataDmndParam(LinkDataVO linkDataVO) throws Exception{
        return linkDataMapper.selectMetDataDmndParam(linkDataVO);
    }

    @Override
    public List<Map<String,Object>> selectClctDalySmryList(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectClctDalySmryList(linkDataSearchVO);
    }

    @Override
    public List<Map<String,Object>> selectClctIntgHstryList(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectClctIntgHstryList(linkDataSearchVO);
    }

    @Override
    public int insertLinkData(LinkDataVO linkDataVO) throws Exception {
        return linkDataMapper.insertLinkData(linkDataVO);
    }

    @Override
    public int updateLinkData(LinkDataVO linkDataVO) throws Exception {
        return linkDataMapper.updateLinkData(linkDataVO);
    }

    @Override
    public int selectLinkDataCnt(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectLinkDataCnt(linkDataSearchVO);
    }

    @Override
    public int selectDalySmryTotPrcsCnt(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectDalySmryTotPrcsCnt(linkDataSearchVO);
    }

    @Override
    public int selectDalySmryTotScsCnt(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectDalySmryTotScsCnt(linkDataSearchVO);
    }

    @Override
    public int selectDalySmryTotFailCnt(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectDalySmryTotFailCnt(linkDataSearchVO);
    }

    @Override
    public int selectClctHstryTotCnt(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectClctHstryTotCnt(linkDataSearchVO);
    }

    @Override
    public int selectDalyScsRpbltyAvg(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectDalyScsRpbltyAvg(linkDataSearchVO);
    }

    @Override
    public long selectDalyPrcsHrAvg(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectDalyPrcsHrAvg(linkDataSearchVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteLinkData(LinkDataVO linkDataVO) throws Exception {
        // 자식 테이블 먼저 삭제 (FK 제약)
        linkDataMapper.deleteLinkMetdataByLinkId(linkDataVO.getLinkId());
        linkDataMapper.deleteLinkMetdataDmndByLinkId(linkDataVO.getLinkId());
        return linkDataMapper.deleteLinkData(linkDataVO);
    }

    @Override
    public List<Map<String,Object>> selectLinkDataHoprHstryList(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectLinkDataHoprHstryList(linkDataSearchVO);
    }

    @Override
    public int insertLinkDataHoprHstry(LinkDataVO linkDataVO) throws Exception {
        return linkDataMapper.insertLinkDataHoprHstry(linkDataVO);
    }

    @Override
    public int selectLinkDataHoprHstryTotCnt(LinkDataSearchVO linkDataSearchVO) throws Exception {
        return linkDataMapper.selectLinkDataHoprHstryTotCnt(linkDataSearchVO);
    }

    /**
     * Metadata CUD 통합 처리
     * @return 총 처리된 건수 (생성 + 수정 + 삭제)
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int processMetadataCUD(LinkDataRequestDTO.MetadataCUD metadata, String linkId) throws Exception {
        int totalCount = 0;
        
        // DELETE 처리
        if (!metadata.getDelete().isEmpty()) {
            for (String metdataSn : metadata.getDelete()) {
                LinkDataVO deleteVO = new LinkDataVO();
                deleteVO.setMetdataSn(Long.valueOf(metdataSn));
                
                int deleteResult = linkDataMapper.deleteLinkDataSettingMetData(deleteVO);
                if (deleteResult <= 0) {
                    throw new BusinessException("메타데이터 삭제에 실패했습니다. (SN: " + metdataSn + ")");
                }
                totalCount += deleteResult;
            }
        }
        
        // UPDATE 처리
        if (!metadata.getUpdate().isEmpty()) {
            for (LinkDataRequestDTO.MetadataItem item : metadata.getUpdate()) {
                LinkDataVO updateVO = new LinkDataVO();
                updateVO.setMetdataSn(Long.valueOf(item.getMetdataSn()));
                updateVO.setLinkId(linkId);
                updateVO.setSortSeq(Long.valueOf(item.getSortSeq()));
                updateVO.setMetdataNm(item.getMetdataNm());
                updateVO.setMetdataPhysNm(item.getMetdataPhysNm());
                updateVO.setMetdataExpln(item.getMetdataExpln());
                updateVO.setMetdataTyNm(item.getMetdataTyNm());
                updateVO.setMetdataLenCnt(Long.valueOf(item.getMetdataLenCnt()));
                updateVO.setMetdataEsntlYn(item.getMetdataEsntlYn());
                updateVO.setMetdataDfltNm(item.getMetdataDfltNm());

                int updateResult = linkDataMapper.updateLinkDataSettingMetData(updateVO);
                if (updateResult <= 0) {
                    throw new BusinessException("메타데이터 수정에 실패했습니다. (항목명: " + item.getMetdataNm() + ")");
                }
                totalCount += updateResult;
            }
        }

        // CREATE 처리
        if (!metadata.getCreate().isEmpty()) {
            for (LinkDataRequestDTO.MetadataItem item : metadata.getCreate()) {
                LinkDataVO insertVO = new LinkDataVO();
                insertVO.setLinkId(linkId);
                insertVO.setSortSeq(Long.valueOf(item.getSortSeq()));
                insertVO.setMetdataNm(item.getMetdataNm());
                insertVO.setMetdataPhysNm(item.getMetdataPhysNm());
                insertVO.setMetdataExpln(item.getMetdataExpln());
                insertVO.setMetdataTyNm(item.getMetdataTyNm());
                insertVO.setMetdataLenCnt(Long.valueOf(item.getMetdataLenCnt()));
                insertVO.setMetdataEsntlYn(item.getMetdataEsntlYn());
                insertVO.setMetdataDfltNm(item.getMetdataDfltNm());

                int insertResult = linkDataMapper.insertLinkDataSettingMetData(insertVO);
                if (insertResult <= 0) {
                    throw new BusinessException("메타데이터 생성에 실패했습니다. (항목명: " + item.getMetdataNm() + ")");
                }
                totalCount += insertResult;
            }
        }
        
        return totalCount;
    }

    /**
     * API Data CUD 통합 처리
     * @return 총 처리된 건수 (생성 + 수정 + 삭제)
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int processApiDataCUD(LinkDataRequestDTO.ApiDataCUD apiData, String linkId, String linkTypeCd) throws Exception {
        int totalCount = 0;
        
        // DELETE 처리
        if (!apiData.getDelete().isEmpty()) {
            for (String dmndSn : apiData.getDelete()) {
                LinkDataVO deleteVO = new LinkDataVO();
                deleteVO.setLinkMetdataDmndSn(Long.valueOf(dmndSn));
                
                int deleteResult = linkDataMapper.deleteLinkDataSettingApiData(deleteVO);
                if (deleteResult <= 0) {
                    throw new BusinessException("API 데이터 삭제에 실패했습니다. (SN: " + dmndSn + ")");
                }
                totalCount += deleteResult;
            }
        }
        
        // UPDATE 처리
        if (!apiData.getUpdate().isEmpty()) {
            for (LinkDataRequestDTO.ApiDataItem item : apiData.getUpdate()) {
                LinkDataVO updateVO = new LinkDataVO();
                updateVO.setLinkMetdataDmndSn(Long.valueOf(item.getLinkMetdataDmndSn()));
                updateVO.setLinkId(linkId);
                updateVO.setLinkTypeCd(linkTypeCd);
                updateVO.setDmndTypeCd(item.getDmndTypeCd());
                updateVO.setDmndKeyNm(item.getDmndKeyNm());
                updateVO.setDmndVlNm(item.getDmndVlNm());
                updateVO.setDmndTyNm(item.getDmndTyNm());
                updateVO.setDmndEsntlYn(item.getDmndEsntlYn());

                int updateResult = linkDataMapper.updateLinkDataSettingApiData(updateVO);
                if (updateResult <= 0) {
                    throw new BusinessException("API 데이터 수정에 실패했습니다. (키: " + item.getDmndKeyNm() + ")");
                }
                totalCount += updateResult;
            }
        }
        
        // CREATE 처리
        if (!apiData.getCreate().isEmpty()) {
            for (LinkDataRequestDTO.ApiDataItem item : apiData.getCreate()) {
                LinkDataVO insertVO = new LinkDataVO();
                insertVO.setLinkId(linkId);
                insertVO.setLinkTypeCd(linkTypeCd);
                insertVO.setDmndTypeCd(item.getDmndTypeCd());
                insertVO.setDmndKeyNm(item.getDmndKeyNm());
                insertVO.setDmndVlNm(item.getDmndVlNm());
                insertVO.setDmndTyNm(item.getDmndTyNm());
                insertVO.setDmndEsntlYn(item.getDmndEsntlYn());

                int insertResult = linkDataMapper.insetLinkDataSettingApiData(insertVO);
                if (insertResult <= 0) {
                    throw new BusinessException("API 데이터 생성에 실패했습니다. (키: " + item.getDmndKeyNm() + ")");
                }
                totalCount += insertResult;
            }
        }
        
        return totalCount;
    }
}
