package com.dbnt.sims.fipTarget.service;



import com.dbnt.sims.config.BaseService;
import com.dbnt.sims.fipTarget.mapper.FipTargetMapper;
import com.dbnt.sims.fipTarget.model.PartInfo;
import com.dbnt.sims.fipTarget.model.PartInfo.PartInfoId;
import com.dbnt.sims.fipTarget.model.PartInfoFile;
import com.dbnt.sims.fipTarget.model.PartInfoFile.PartInfoFileId;
import com.dbnt.sims.fipTarget.model.PartWork;
import com.dbnt.sims.fipTarget.model.PartWork.PartWorkId;
import com.dbnt.sims.fipTarget.model.PartWorkFile;
import com.dbnt.sims.fipTarget.model.PartWorkFile.PartWorkFileId;
import com.dbnt.sims.fipTarget.model.VulnFile;
import com.dbnt.sims.fipTarget.model.VulnFile.VulnFileId;
import com.dbnt.sims.fipTarget.model.Vulnerable;
import com.dbnt.sims.fipTarget.repository.PartInfoFileRepository;
import com.dbnt.sims.fipTarget.repository.PartInfoRepository;
import com.dbnt.sims.fipTarget.repository.PartWorkFileRepository;
import com.dbnt.sims.fipTarget.repository.PartWorkRepository;
import com.dbnt.sims.fipTarget.repository.VulnFileRepository;
import com.dbnt.sims.fipTarget.repository.VulnRepository;
import com.dbnt.sims.util.ParamMap;

import lombok.RequiredArgsConstructor;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;

@Service
@RequiredArgsConstructor
public class FipTargetService extends BaseService {
	@Value("${spring.servlet.multipart.location}")
	  protected String locationPath;

	private final PartInfoRepository partInfoRepository;
	private final PartInfoFileRepository partInfoFileRepository;
	private final PartWorkRepository partWorkRepository;
	private final PartWorkFileRepository partWorkFileRepository;
	private final VulnRepository vulnRepository;
	private final VulnFileRepository vulnFileRepository;
	private final FipTargetMapper fipTargetMapper;
	
	@Transactional
	public void savePartInfo(PartInfo partInfo) {
		PartInfo dbPart = partInfoRepository.findFirstByOrderByPiSeqDesc();
			if(dbPart == null) {
				partInfo.setPiSeq(1);
				partInfo.setVersionNo(1);
				partInfoRepository.save(partInfo);
			} else {
				partInfo.setPiSeq(dbPart.getPiSeq()+1);
				partInfo.setVersionNo(1);
				partInfoRepository.save(partInfo);
			}
		saveUploadFiles(partInfo.getPiSeq(),partInfo.getVersionNo(), partInfo.getMultipartFileList());
	}
	
	private void saveUploadFiles(Integer piSeq,Integer versionNo, List<MultipartFile> multipartFileList) {
		PartInfoFile lastFileInfo = partInfoFileRepository.findTopByPiSeqAndVersionNoOrderByFileSeqDesc(piSeq,versionNo);
	    int fileSeq = lastFileInfo==null?1:(lastFileInfo.getFileSeq()+1);
		    if(multipartFileList == null || multipartFileList.isEmpty()) {
		    	if(lastFileInfo == null || lastFileInfo.getOrigNm() == null ) {
		    		PartInfoFile fileInfo = new PartInfoFile();
		    		fileInfo.setFileSeq(fileSeq);
		    		fileInfo.setPiSeq(piSeq);	 
		    		fileInfo.setVersionNo(versionNo);
		    		partInfoFileRepository.save(fileInfo);
		    	}
			      
		    } else {
		    	for(MultipartFile file : multipartFileList){
				      String saveName = UUID.randomUUID().toString();
				      String path = locationPath+File.separator+"publicFile"+File.separator;
				      saveFile(file, new File(path+File.separator+saveName));
			
				      String originalFilename = file.getOriginalFilename();
				      int extnIdx = originalFilename.lastIndexOf(".");
				      PartInfoFile fileInfo = new PartInfoFile();
				      fileInfo.setFileSeq(fileSeq++);
				      fileInfo.setPiSeq(piSeq);	 
				      fileInfo.setVersionNo(versionNo);
				      fileInfo.setOrigNm(originalFilename.substring(0, extnIdx));
				      fileInfo.setFileExtn(originalFilename.substring(extnIdx+1));
				      fileInfo.setConvNm(saveName);
				      fileInfo.setFileSize(calculationSize(file.getSize()));
				      fileInfo.setFilePath(path);
				      partInfoFileRepository.save(fileInfo);
				    }
		    }
		
	  }

	public List<PartInfo> selectPartInfoList(PartInfo partInfo) {
		return fipTargetMapper.selectPartInfoList(partInfo);
	}

	public Integer selectPartInfoListCnt(PartInfo partInfo) {
		return fipTargetMapper.selectPartInfoListCnt(partInfo);
	}

	public ParamMap selectWorkTypeTotal(PartInfo partInfo) {
		return fipTargetMapper.selectWorkTypeTotal(partInfo);
	}

	public PartInfo selectPartInfo(PartInfo partInfo) {
		return fipTargetMapper.selectPartInfo(partInfo);
	}

	public List<PartInfoFile> selectPartInfoFile(PartInfo partInfo) {
		return fipTargetMapper.selectPartInfoFile(partInfo);
	}
	
	@Transactional
	public void updatePartInfo(PartInfo partInfo, List<Integer> deleteFileSeq) {
		PartInfo dbPart = partInfoRepository.findById(new PartInfoId(partInfo.getPiSeq(), partInfo.getVersionNo())).orElse(null);
		PartInfo partTmp = new PartInfo();
		partTmp.setPiSeq(dbPart.getPiSeq());
		partTmp.setVersionNo(dbPart.getVersionNo()+1);
		partTmp.setMgtOrgan(partInfo.getMgtOrgan());
		partTmp.setLandPolice(partInfo.getLandPolice());
		partTmp.setPiUserSeq(partInfo.getPiUserSeq());
		partTmp.setRentType(partInfo.getRentType());
		partTmp.setRentPrice(partInfo.getRentPrice());
		partTmp.setUtilityType(partInfo.getUtilityType());
		partTmp.setUtilityPrice(partInfo.getUtilityPrice());
		partTmp.setTerminalNm(partInfo.getTerminalNm());
		partTmp.setMpWorkType(partInfo.getMpWorkType());
		partTmp.setMpPeopleCnt(partInfo.getMpPeopleCnt());
		partTmp.setMpDescription(partInfo.getMpDescription());
		partTmp.setPlWorkType(partInfo.getPlWorkType());
		partTmp.setPlPeopleCnt(partInfo.getPlPeopleCnt());
		partTmp.setPlDescription(partInfo.getPlDescription());
		partTmp.setWrtUserSeq(partInfo.getWrtUserSeq());
		partTmp.setWrtNm(partInfo.getWrtNm());
		partTmp.setWrtPart(partInfo.getWrtPart());
		partTmp.setWrtOrgan(partInfo.getWrtOrgan());
		partTmp.setWrtDt(partInfo.getWrtDt());
		partInfoRepository.save(partTmp);
		//업데이트하는 버전 파일조회
		List<PartInfoFile> fileList = partInfoFileRepository.findByPiSeqAndVersionNoOrderByFileSeqAsc(partInfo.getPiSeq(),partInfo.getVersionNo());
		if(fileList.get(0).getOrigNm() != null) {
			for(PartInfoFile fileInfo : fileList){
				PartInfoFile tmpFile = new PartInfoFile();
				tmpFile.setFileSeq(fileInfo.getFileSeq());
				tmpFile.setPiSeq(fileInfo.getPiSeq());
				tmpFile.setVersionNo(partTmp.getVersionNo());
				tmpFile.setOrigNm(fileInfo.getOrigNm());
				tmpFile.setConvNm(fileInfo.getConvNm());
				tmpFile.setFileExtn(fileInfo.getFileExtn());
				tmpFile.setFileSize(fileInfo.getFileSize());
				tmpFile.setFilePath(fileInfo.getFilePath());
				partInfoFileRepository.save(tmpFile);
			}
		}
		//수정시 삭제한 파일삭제
		if(deleteFileSeq!=null && deleteFileSeq.size()>0){
		      deletePartInfoFile(partTmp.getPiSeq(),partTmp.getVersionNo(), deleteFileSeq);
		}
		//파일업로드
			saveUploadFiles(partTmp.getPiSeq(),partTmp.getVersionNo(), partInfo.getMultipartFileList());
	}
	
	private void deletePartInfoFile(Integer piSeq,Integer versionNo, List<Integer> deleteFileSeq) {
	    List<PartInfoFile> partInfoFileList = partInfoFileRepository.findByPiSeqAndVersionNoOrderByFileSeqAsc(piSeq,versionNo);
	    for(PartInfoFile file: partInfoFileList){
	      if(deleteFileSeq.contains(file.getFileSeq())){
	        deleteStoredFile(new File(file.getFilePath(), file.getConvNm()));
	        partInfoFileRepository.deleteById(new PartInfoFileId(file.getFileSeq(),piSeq,versionNo));
	      }
	    }
	  }

	public List<PartInfo> selectPartInfoSeq(PartInfo partInfo) {
		return fipTargetMapper.selectPartInfoSeq(partInfo);
	}

	public PartInfo selectPartInfoHistoryView(PartInfo partInfo) {
		return fipTargetMapper.selectPartInfoHistoryView(partInfo);
	}

	public List<PartInfoFile> selectPartInfoFileHistoryView(PartInfo partInfo) {
		return fipTargetMapper.selectPartInfoFileHistoryView(partInfo);
	}
	
	@Transactional
	public void deletePartInfo(PartInfo partInfo) {
		//외사실적 파일,데이터삭제
		List<PartWorkFile> partWorkFileList = partWorkFileRepository.findByPiSeq(partInfo.getPiSeq());
		if(partWorkFileList != null) {
			for(PartWorkFile file: partWorkFileList){
		        deleteStoredFile(new File(file.getFilePath(), file.getConvNm()));
		        partWorkFileRepository.deleteByPwSeqAndPiSeq(file.getPwSeq(),file.getPiSeq());
			}
		}
		partWorkRepository.deleteByPiSeq(partInfo.getPiSeq());
		//외사분실운영현황파일삭제
		List<PartInfoFile> partInfoFileList= selectPartInfoFile(partInfo);
		for(PartInfoFile file: partInfoFileList){
		      if(file.getOrigNm() != null){
		        deleteStoredFile(new File(file.getFilePath(), file.getConvNm()));
		      }
		}
		partInfoFileRepository.deleteByPiSeq(partInfo.getPiSeq());
		partInfoRepository.deleteByPiSeq(partInfo.getPiSeq());
		
	}

	public PartInfoFile selectPartInfoFileDown(Integer fileSeq, Integer piSeq, Integer versionNo) {
		return partInfoFileRepository.findById(new PartInfoFileId(fileSeq, piSeq,versionNo)).orElse(null);
	}

	public String selectPartInfoFirstId(PartInfo partInfo) {
		return fipTargetMapper.selectPartInfoFirstId(partInfo.getPiSeq());
	}

	public List<ParamMap> selectTerminalName(PartWork partWork) {
		return fipTargetMapper.selectTerminalName(partWork);
	}
	
	@Transactional
	public void savePartWork(PartWork partWork) {
		PartWork dbPart = partWorkRepository.findTopByPiSeqOrderByPwSeqDesc(partWork.getPiSeq());
		if(dbPart == null) {
			partWork.setPwSeq(1);
			partWorkRepository.save(partWork);
		} else {
			partWork.setPwSeq(dbPart.getPwSeq()+1);
			partWorkRepository.save(partWork);
		}
		if(partWork.getMultipartFileList()!= null){
			saveFilesUpload(partWork.getPwSeq(),partWork.getPiSeq(), partWork.getMultipartFileList());			
		}
	}
	
	private void saveFilesUpload(Integer pwSeq,Integer piSeq, List<MultipartFile> multipartFileList) {
		PartWorkFile lastFileInfo = partWorkFileRepository.findTopByPwSeqAndPiSeqOrderByFileSeqDesc(pwSeq,piSeq);
	    int fileSeq = lastFileInfo==null?1:(lastFileInfo.getFileSeq()+1);
	    for(MultipartFile file : multipartFileList){
	        String saveName = UUID.randomUUID().toString();
	        String path = locationPath+File.separator+"publicFile"+File.separator;
	        saveFile(file, new File(path+File.separator+saveName));

	        String originalFilename = file.getOriginalFilename();
	        int extnIdx = originalFilename.lastIndexOf(".");
	        PartWorkFile fileInfo = new PartWorkFile();	        
	        fileInfo.setFileSeq(fileSeq++);
	        fileInfo.setPwSeq(pwSeq);
	        fileInfo.setPiSeq(piSeq);
	        fileInfo.setOrigNm(originalFilename.substring(0, extnIdx));
	        fileInfo.setFileExtn(originalFilename.substring(extnIdx+1));
	        fileInfo.setConvNm(saveName);
	        fileInfo.setFileSize(calculationSize(file.getSize()));
	        fileInfo.setFilePath(path);
	        partWorkFileRepository.save(fileInfo);
	      }
		
	  }

	public List<PartWork> selectPartWorkList(PartWork partWork) {
		return fipTargetMapper.selectPartWorkList(partWork);
	}

	public Integer selectPartWorkListCnt(PartWork partWork) {
		return fipTargetMapper.selectPartWorkListCnt(partWork);
	}

	public PartWork selectPartWorkInfo(PartWork partWork) {
		return fipTargetMapper.selectPartWorkInfo(partWork);
	}

	public List<PartWorkFile> selectPartWorkFile(PartWork partWork) {
		return partWorkFileRepository.findByPwSeqAndPiSeqOrderByFileSeqAsc(partWork.getPwSeq(),partWork.getPiSeq());
	}
	
	@Transactional
	public void updatePartWork(PartWork partWork, List<Integer> deleteFileSeq) {
		PartWork dbParkWork = partWorkRepository.findById(new PartWorkId(partWork.getPwSeq(),partWork.getPiSeq())).orElse(null);
		partWork.setWrtNm(dbParkWork.getWrtNm());
		partWork.setWrtOrgan(dbParkWork.getWrtOrgan());
		partWork.setWrtPart(dbParkWork.getWrtPart());
		partWork.setWrtUserSeq(dbParkWork.getWrtUserSeq());
		partWorkRepository.save(partWork);
		if(deleteFileSeq!=null && deleteFileSeq.size()>0){
		      deletePartWorkFile(partWork, deleteFileSeq);
		}
		if(partWork.getMultipartFileList()!= null){
			saveFilesUpload(partWork.getPwSeq(),partWork.getPiSeq(), partWork.getMultipartFileList());			
		}		
	}
	
    private void deletePartWorkFile(PartWork partWork, List<Integer> deleteFileSeq) {
	    List<PartWorkFile> partWorkFileList = partWorkFileRepository.findByPwSeqAndPiSeq(partWork.getPwSeq(),partWork.getPiSeq());
	    for(PartWorkFile file: partWorkFileList ){
	      if(deleteFileSeq.contains(file.getFileSeq())){
	        deleteStoredFile(new File(file.getFilePath(), file.getConvNm()));
	        partWorkFileRepository.delete(file);
	      }
	    }
	}
    
    @Transactional
	public void deletePartWork(PartWork partWork) {
		//파일삭제
		List<PartWorkFile> partWorkFileList= partWorkFileRepository.findByPwSeqAndPiSeq(partWork.getPwSeq(),partWork.getPiSeq());
		if(partWorkFileList != null) {
			for(PartWorkFile file: partWorkFileList){
			        deleteStoredFile(new File(file.getFilePath(), file.getConvNm()));
			}
		}
		partWorkFileRepository.deleteByPwSeqAndPiSeq(partWork.getPwSeq(),partWork.getPiSeq());
		partWorkRepository.deleteByPwSeqAndPiSeq(partWork.getPwSeq(),partWork.getPiSeq());									
	}

	public PartWorkFile selectPartWorkFileDown(Integer fileSeq, Integer pwSeq, Integer piSeq) {
		return partWorkFileRepository.findById(new PartWorkFileId(fileSeq, pwSeq,piSeq)).orElse(null);
	}

	public List<ParamMap> selecetVulnOrganList(Vulnerable vulnerable) {
		return fipTargetMapper.selecetVulnOrganList(vulnerable);
	}
	
	@Transactional
	public Integer saveVulnerable(Vulnerable vulnerable,  List<Integer> deleteFileSeq) {
		Integer vulnKey = vulnRepository.save(vulnerable).getVulnKey();
		if(deleteFileSeq!=null && deleteFileSeq.size()>0){
		      deleteVulnFile(vulnerable, deleteFileSeq);
		}
		if(vulnerable.getMultipartFileList()!= null){
		      saveVulnerableFiles(vulnKey, vulnerable.getMultipartFileList());
		}
		return vulnKey;
	}
	
	private void saveVulnerableFiles(Integer vulnKey, List<MultipartFile> multipartFileList) {
		VulnFile lastFileInfo = vulnFileRepository.findTopByVulnKeyOrderByFileSeqDesc(vulnKey);
	    int fileSeq = lastFileInfo==null?1:(lastFileInfo.getFileSeq()+1);
	    for(MultipartFile file : multipartFileList){
	      String saveName = UUID.randomUUID().toString();
	      String path = locationPath+File.separator+"publicFile"+File.separator;
	      saveFile(file, new File(path+File.separator+saveName));

	      String originalFilename = file.getOriginalFilename();
	      int extnIdx = originalFilename.lastIndexOf(".");
	      VulnFile fileInfo = new VulnFile();
	      fileInfo.setVulnKey(vulnKey);
	      fileInfo.setFileSeq(fileSeq++);
	      fileInfo.setOrigNm(originalFilename.substring(0, extnIdx));
	      fileInfo.setFileExtn(originalFilename.substring(extnIdx+1));
	      fileInfo.setConvNm(saveName);
	      fileInfo.setFileSize(calculationSize(file.getSize()));
	      fileInfo.setFilePath(path);
	      vulnFileRepository.save(fileInfo);
	    }
	  }
	
	private void deleteVulnFile(Vulnerable vulnerable, List<Integer> deleteFileSeq) {
	    List<VulnFile> VulnFileList = vulnFileRepository.findByVulnKey(vulnerable.getVulnKey());
	    for(VulnFile file: VulnFileList ){
	      if(deleteFileSeq.contains(file.getFileSeq())){
	        deleteStoredFile(new File(file.getFilePath(), file.getConvNm()));
	        vulnFileRepository.delete(file);
	      }
	    }
	}

	public List<ParamMap> selectVulnerableList(Vulnerable vulnerable) {
		return fipTargetMapper.selectVulnerableList(vulnerable);
	}

	public List<Vulnerable> selectVulnInfoList(Vulnerable vulnerable) {
		return fipTargetMapper.selectVulnInfoList(vulnerable);
	}

	public String selectOrganName(String mgtOrgan) {
		return fipTargetMapper.selectOrganName(mgtOrgan);
	}

	public Vulnerable selectVulnInfo(Vulnerable vulnerable) {
		return fipTargetMapper.selectVulnInfo(vulnerable);
	}

	public List<VulnFile> selectVulnFile(Integer vulnKey) {
		return vulnFileRepository.findByVulnKeyOrderByFileSeq(vulnKey);
	}

	public VulnFile selectVulnInfoFileDown(Integer fileSeq, Integer vulnKey) {
		return vulnFileRepository.findById(new VulnFileId(fileSeq, vulnKey)).orElse(null);
	}
	
	@Transactional
	public void deleteVulnerable(Vulnerable vulnerable) {
		//파일삭제
		List<VulnFile> VulnFileList = vulnFileRepository.findByVulnKey(vulnerable.getVulnKey());
		if(VulnFileList != null) {
			for(VulnFile file: VulnFileList){
			        deleteStoredFile(new File(file.getFilePath(), file.getConvNm()));
			}
		}
		vulnFileRepository.deleteByVulnKey(vulnerable.getVulnKey());
		vulnRepository.deleteById(vulnerable.getVulnKey());
	}		
	
	
	
	
	
}
