package com.dbnt.faisp.main.fpiMgt.affair.service;


import com.dbnt.faisp.config.BaseService;
import com.dbnt.faisp.config.FileInfo;
import com.dbnt.faisp.main.fpiMgt.affair.mapper.AffairMapper;
import com.dbnt.faisp.main.fpiMgt.affair.model.*;
import com.dbnt.faisp.main.fpiMgt.affair.repository.*;
import com.dbnt.faisp.main.hashTag.service.HashTagService;
import com.dbnt.faisp.main.userInfo.model.UserInfo;
import com.dbnt.faisp.main.userInfo.service.UserAlarmService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class AffairService extends BaseService { // 견문보고
  private final UserAlarmService userAlarmService;
  private final HashTagService hashTagService;
  private final AffairBoardRepository affairBoardRepository;
  private final AffairFileRepository affairFileRepository;
  private final AffairRatingRepository affairRatingRepository;
  private final HashTagLinkRepository hashTagLinkRepository;
  private final AffairMapper affairMapper;

  public List<AffairBoard> selectAffairBoardList(AffairBoard affair){
    return affairMapper.selectAffairBoardList(affair);
  }
  public Integer selectAffairBoardListCnt(AffairBoard affair){
    return affairMapper.selectAffairBoardCnt(affair);
  }

  public AffairBoard selectAffairBoard(Integer affairKey){
    AffairBoard affair = affairBoardRepository.findById(affairKey).orElse(null);
    if(affair != null){
      affair.setHashTags(affairMapper.selectHashTags(affairKey));
      affair.setFileList(affairFileRepository.findByAffairKey(affairKey));
      affair.setRateList(affairRatingRepository.findByAffairKeyOrderByRatingOrganAsc(affairKey));
    }
    return affair;
  }
  @Transactional
  public Integer saveAffairBoard(AffairBoard affair, List<Integer> deleteFileSeq){
    Integer affairKey = affairBoardRepository.save(affair).getAffairKey();
    if(!affair.getHashTags().isEmpty()){
      saveHashTagLink(affairKey, affair.getHashTags().split(" "));
    }
    if(deleteFileSeq != null && deleteFileSeq.size()>0){
      deleteAffairFile(affairKey, deleteFileSeq);
    }
    if(affair.getMultipartFileList()!=null){
      saveUploadFiles(affairKey, affair.getMultipartFileList());
    }

    AffairRating rating = affairRatingRepository.findById(new AffairRating.AffairRatingId(affairKey,affair.getWrtOrgan())).orElse(null);
    if(rating == null){
      rating = new AffairRating();
      rating.setAffairKey(affairKey);
      rating.setRatingOrgan(affair.getWrtOrgan());
    }
    rating.setAffairStatus(affair.getAffairStatus());
    affairRatingRepository.save(rating);

    if(affair.getAffairStatus().equals("DST002")){
      //작성완료일 때 계장 결재 사용자에게 알림 발송.
      userAlarmService.sendAlarmToApprvUser(affairKey, affair.getWrtOrgan(), "APC003", 30, "견문보고에 결재대기 문서가 있습니다.");
      userAlarmService.sendAlarmToApprvUser(affairKey, affair.getWrtOrgan(), "APC004", 30, "견문보고에 결재대기 문서가 있습니다.");
    }
    return affairKey;
  }

  private void saveHashTagLink(Integer affairKey, String[] hashTagAry){
    hashTagLinkRepository.deleteByAffairKey(affairKey);
    for(String tagNm : hashTagAry){
      HashTagLink hashTagLink = new HashTagLink();
      hashTagLink.setAffairKey(affairKey);
      hashTagLink.setTagKey(hashTagService.selectTagKey(tagNm));
      hashTagLinkRepository.save(hashTagLink);
    }
  }
  private void deleteAffairFile(Integer affairKey, List<Integer> deleteFileSeq) {
    List<AffairFile> affairFileList = affairFileRepository.findByAffairKey(affairKey);
    for(AffairFile file: affairFileList){
      if(deleteFileSeq.contains(file.getFileSeq())){
        deleteStoredFile(new File(file.getSavePath(), file.getConvNm()));
        affairFileRepository.delete(file);
      }
    }
  }
  private void saveUploadFiles(Integer affairKey, List<MultipartFile> multipartFileList){
    AffairFile lastFileInfo = affairFileRepository.findTopByAffairKeyOrderByFileSeqDesc(affairKey).orElse(null);
    int fileSeq = lastFileInfo==null?1:(lastFileInfo.getFileSeq()+1);
    for(MultipartFile file : multipartFileList){
      String saveName = UUID.randomUUID().toString();
      String path = locationPath+File.separator+"affair"+File.separator;
      saveFile(file, new File(path+File.separator+saveName));

      String originalFilename = file.getOriginalFilename();
      int extnIdx = originalFilename.lastIndexOf(".");
      AffairFile fileInfo = new AffairFile();
      fileInfo.setAffairKey(affairKey);
      fileInfo.setFileSeq(fileSeq++);
      fileInfo.setOrigNm(originalFilename.substring(0, extnIdx));
      fileInfo.setFileExtn(originalFilename.substring(extnIdx+1));
      fileInfo.setConvNm(saveName);
      fileInfo.setFileSize(calculationSize(file.getSize()));
      fileInfo.setSavePath(path);
      affairFileRepository.save(fileInfo);
    }
  }

  @Transactional
  public Integer affairStateChange(UserInfo loginUser, List<AffairRating> ratingList) {
    for(AffairRating rating : ratingList){
      AffairRating savedRating = affairRatingRepository.findById(new AffairRating.AffairRatingId(rating.getAffairKey(), loginUser.getOgCd())).orElse(null);
      if(savedRating != null){
        if(rating.getHeadApprv() == null){
          savedRating.setSectionNm(loginUser.getUserNm());
          savedRating.setSectionApprvDt(LocalDateTime.now());
          savedRating.setSectionApprv(rating.getSectionApprv());
          savedRating.setSectionEtc(rating.getSectionEtc());
          savedRating.setAffairStatus(rating.getSectionApprv());
          switch (rating.getSectionApprv()){
            case "DST004":
              userAlarmService.sendAlarmToApprvUser(savedRating.getAffairKey(), savedRating.getRatingOrgan(), "APC001", 30, "견문보고에 결재대기 문서가 있습니다.");
              userAlarmService.sendAlarmToApprvUser(savedRating.getAffairKey(), savedRating.getRatingOrgan(), "APC002", 30, "견문보고에 결재대기 문서가 있습니다.");
              break;
            case "DST003":
              AffairBoard affairBoard = affairBoardRepository.findById(rating.getAffairKey()).orElse(new AffairBoard());
              userAlarmService.sendAlarmToWrtUser(savedRating.getAffairKey(), affairBoard.getWrtUserSeq(), 30, affairBoard.getTitle()+" 문서가 반려되었습니다.");
              break;
          }
        }else{
          savedRating.setHeadNm(loginUser.getUserNm());
          savedRating.setHeadApprvDt(LocalDateTime.now());
          savedRating.setHeadApprv(rating.getHeadApprv());
          savedRating.setHeadEtc(rating.getHeadEtc());
          savedRating.setAffairRate(rating.getAffairRate());
          savedRating.setOrganUp(rating.getOrganUp()==null?"F":rating.getOrganUp());
          savedRating.setAffairStatus(rating.getHeadApprv());
          if(savedRating.getOrganUp().equals("T")){
            List<String> organList = loginUser.getUpOrganCdList();
            String upOrgan = organList.get(organList.indexOf(savedRating.getRatingOrgan())-1);
            AffairRating upRating = new AffairRating();
            upRating.setRatingOrgan(upOrgan);
            upRating.setAffairKey(savedRating.getAffairKey());
            upRating.setAffairStatus("DST002");
            affairRatingRepository.save(upRating);

            // 상보시 상위관서 계장 결재권한 사용자에게 알림 생성
            userAlarmService.sendAlarmToApprvUser(savedRating.getAffairKey(), upOrgan, "APC003", 30, "견문보고에 결재대기 문서가 있습니다.");
            userAlarmService.sendAlarmToApprvUser(savedRating.getAffairKey(), upOrgan, "APC004", 30, "견문보고에 결재대기 문서가 있습니다.");
          }

          AffairBoard affairBoard = affairBoardRepository.findById(rating.getAffairKey()).orElse(new AffairBoard());
          switch (rating.getHeadApprv()){
            case "DST006":
              userAlarmService.sendAlarmToWrtUser(savedRating.getAffairKey(), affairBoard.getWrtUserSeq(), 30, affairBoard.getTitle()+" 문서가 승인되었습니다.");
              break;
            case "DST005":
              userAlarmService.sendAlarmToWrtUser(savedRating.getAffairKey(), affairBoard.getWrtUserSeq(), 30, affairBoard.getTitle()+" 문서가 반려되었습니다.");
              break;
          }
        }
        affairRatingRepository.save(savedRating);
      }
    }
    return ratingList.size()>1?0:ratingList.get(0).getAffairKey();
  }

  public FileInfo selectAffairFile(Integer parentKey, Integer fileSeq) {
    return affairFileRepository.findById(new AffairFile.AffairFileId(parentKey, fileSeq)).orElse(null);
  }
  
  public List<TypeStatistics> selectStatusTotal(TypeStatistics typeStatistics) {
	return affairMapper.selectStatusTotal(typeStatistics);
  }
  
  public List<TypeStatistics> selecType1ListCnt(TypeStatistics typeStatistics) {
	return affairMapper.selecType1ListCnt(typeStatistics);
  }
  
  public List<TypeStatistics> selecType2ListCnt(TypeStatistics typeStatistics) {
	return affairMapper.selecType2ListCnt(typeStatistics);
  }
  
  public List<TypeStatistics> selecType3ListCnt(TypeStatistics typeStatistics) {
	return affairMapper.selecType3ListCnt(typeStatistics);
  }
  
  public List<TypeStatistics> selecType4ListCnt(TypeStatistics typeStatistics) {
	return affairMapper.selecType4ListCnt(typeStatistics);
  }
  public List<TypeStatistics> selectRatingStatusTotal(TypeStatistics typeStatistics) {
	return affairMapper.selectRatingStatusTotal(typeStatistics);
  }
  public List<TypeStatistics> selectSangboTotal(TypeStatistics typeStatistics) {
	return affairMapper.selectSangboTotal(typeStatistics);
  }
  public List<TypeStatistics> selectArrCntList(TypeStatistics typeStatistics) {
	return affairMapper.selectArrCntList(typeStatistics);
  }
}
