package com.dbnt.faisp.main.faStatistics.crackdownsStatus.service;


import com.dbnt.faisp.config.BaseService;
import com.dbnt.faisp.config.FileInfo;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.mapper.CrackdownStatusMapper;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.CaptinPhotoFile;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.CaptinPhotoVersion;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.crackdownStatus.CrackdownStatus;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.crackdownStatus.CrackdownStatusVersion;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.fishingBoat.FishingBoat;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.fishingBoat.FishingBoatVersion;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.fishingBoat.Violation;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.fishingBoat.ViolationVersion;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.processResult.ProcessResult;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.processResult.ProcessResultVersion;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.sailor.Sailor;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.model.sailor.SailorVersion;
import com.dbnt.faisp.main.faStatistics.crackdownsStatus.repository.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
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.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class FishingBoatService extends BaseService {

  private final CrackdownStatusMapper crackdownStatusMapper;
  private final CrackdownStatusRepository crackdownStatusRepository;
  private final CrackdownStatusVersionRepository crackdownStatusVersionRepository;
  private final FishingBoatRepository fishingBoatRepository;
  private final FishingBoatVersionRepository fishingBoatVersionRepository;
  private final ViolationRepository violationRepository;
  private final ViolationVersionRepository violationVersionRepository;
  private final ProcessResultRepository processResultRepository;
  private final ProcessResultVersionRepository processResultVersionRepository;
  private final SailorRepository sailorRepository;
  private final SailorVersionRepository sailorVersionRepository;
  private final CaptionPhotoFileRepository captionPhotoFileRepository;
  private final CaptionPhotoVersionRepository captionPhotoVersionRepository;

  public List<CrackdownStatus> selectFishingBoatList(CrackdownStatus crackdownStatus){
    return crackdownStatusMapper.selectFishingBoatList(crackdownStatus);
  }
  public Integer selectFishingBoatListCnt(CrackdownStatus crackdownStatus){
    return crackdownStatusMapper.selectFishingBoatListCnt(crackdownStatus);
  }
  public CrackdownStatus selectCrackdownStatus(Integer cdsKey) {
    CrackdownStatus crackdownStatus = crackdownStatusRepository.findById(cdsKey).orElse(null);
    crackdownStatus.setFishingBoat(fishingBoatRepository.findByCdsKey(cdsKey).orElse(new FishingBoat()));
    crackdownStatus.setFishingBoatVersionList(crackdownStatusMapper.selectFishingBoatVersionList(crackdownStatus.getFishingBoat().getFbKey()));
    crackdownStatus.setProcessResult(processResultRepository.findByCdsKey(cdsKey).orElse(new ProcessResult()));
    if(crackdownStatus.getFishingBoat()!=null){
      crackdownStatus.setViolationList(violationRepository.findByFbKey(crackdownStatus.getFishingBoat().getFbKey()));
      crackdownStatus.setSailorList(sailorRepository.findByFbKey(crackdownStatus.getFishingBoat().getFbKey()));
      for(Sailor sailor: crackdownStatus.getSailorList()){
        if(sailor.getPosition().equals("POS001")){
          // 선장의 첨부파일 첨부
          sailor.setFileList(captionPhotoFileRepository.findBySailorKeyOrderByFileSeqAsc(sailor.getSailorKey()));
        }
      }
    }
    return crackdownStatus;
  }

  @Transactional
  public Integer saveCrackdownStatus(CrackdownStatus crackdownStatus, List<MultipartFile> sailorFiles) {
    Integer cdsKey, fbKey;
    if (crackdownStatus.getCdsKey()==null || crackdownStatus.getCdsKey().equals(0)){
      // 최초 등록시 단속현황, 처리현황, 선원정보를 같이 등록.
      // 단속현황, 단속현황버전 저장.
      crackdownStatus = setWriteInfo(crackdownStatus);
      cdsKey = crackdownStatusRepository.save(crackdownStatus).getCdsKey();
      CrackdownStatusVersion crackdownStatusVersion = new CrackdownStatusVersion();
      BeanUtils.copyProperties(crackdownStatus, crackdownStatusVersion);
      crackdownStatusVersion.setVersionNo(1);
      crackdownStatusVersionRepository.save(crackdownStatusVersion);
      // 어선정보, 어선정보버전 저장.
      FishingBoat fishingBoat = crackdownStatus.getFishingBoat();
      fishingBoat.setCdsKey(cdsKey);
      fbKey = fishingBoatRepository.save(fishingBoat).getFbKey();
      FishingBoatVersion fishingBoatVersion = new FishingBoatVersion();
      BeanUtils.copyProperties(fishingBoat, fishingBoatVersion);
      fishingBoatVersion.setVersionNo(1);
      fishingBoatVersionRepository.save(fishingBoatVersion);
      // 위반사항, 위반사항버전 저장.
      List<Violation> violationList = crackdownStatus.getViolationList();
      List<ViolationVersion> violationVersionList = new ArrayList<>();
      int i = 1;
      for(Violation violation: violationList){
        violation.setViolationKey(i++);
        violation.setFbKey(fbKey);

        ViolationVersion violationVersion = new ViolationVersion();
        BeanUtils.copyProperties(violation, violationVersion);
        violationVersion.setVersionNo(1);
        violationVersionList.add(violationVersion);
      }
      violationRepository.saveAll(violationList);
      violationVersionRepository.saveAll(violationVersionList);
      // 처리현황, 처리현황버전 저장.
      ProcessResult processResult = crackdownStatus.getProcessResult();
      ProcessResultVersion processResultVersion = new ProcessResultVersion();
      processResult.setCdsKey(cdsKey);
      BeanUtils.copyProperties(processResult, processResultVersion);
      processResultVersion.setVersionNo(1);
      Integer prKey = processResultRepository.save(processResult).getPrKey();
      processResultVersion.setPrKey(prKey);
      processResultVersionRepository.save(processResultVersion);
      // 선원정보, 선원정보버전 저장.
      List<Sailor> sailorList = crackdownStatus.getSailorList();
      for(Sailor sailor: sailorList){
        sailor.setFbKey(fbKey);

        SailorVersion sailorVersion = new SailorVersion();

        Integer sailorKey = sailorRepository.save(sailor).getSailorKey();

        BeanUtils.copyProperties(sailor, sailorVersion);
        sailorVersion.setVersionNo(1);
        sailorVersion.setSailorKey(sailorKey);
        Integer versionNo = sailorVersionRepository.save(sailorVersion).getVersionNo();
        if(sailor.getPosition().equals("POS001")){
          //선장은 사진이 같이 업로드 됨.
          if(sailorFiles.size()>0) {
            saveCaptainPhoto(sailorKey, versionNo, sailorFiles);
          }
        }
      }

    }else{
      // 업데이트시에는 어선정보만 수정.
      cdsKey = crackdownStatus.getCdsKey();
      FishingBoat fishingBoat = crackdownStatus.getFishingBoat();
      FishingBoatVersion newInfo = new FishingBoatVersion();
      fishingBoat.setCdsKey(cdsKey);
      fishingBoat.setWrtDt(LocalDateTime.now());
      BeanUtils.copyProperties(fishingBoat, newInfo);
      FishingBoatVersion lastFishingBoatVersion = fishingBoatVersionRepository.findTop1ByFbKeyOrderByVersionNoDesc(crackdownStatus.getFishingBoat().getFbKey()).orElse(null);
      newInfo.setVersionNo(lastFishingBoatVersion.getVersionNo()+1);
      fishingBoatRepository.save(fishingBoat);
      fishingBoatVersionRepository.save(newInfo);
      // 위반사항
      List<Violation> violationList = crackdownStatus.getViolationList();
      List<ViolationVersion> violationVersionList = new ArrayList<>();
      int i=1;
      ViolationVersion lastViolationVersion = violationVersionRepository.findTop1ByFbKeyOrderByVersionNoDesc(fishingBoat.getFbKey()).orElse(null);
      for(Violation violation: violationList){
        violation.setFbKey(fishingBoat.getFbKey());
        violation.setViolationKey(i++);
        ViolationVersion violationVersion = new ViolationVersion();
        BeanUtils.copyProperties(violation, violationVersion);
        violationVersion.setVersionNo(lastViolationVersion.getVersionNo()+1);
        violationVersionList.add(violationVersion);
      }
      violationRepository.saveAll(violationList);
      violationVersionRepository.saveAll(violationVersionList);
    }
    return cdsKey;
  }

  public Integer checkCaseNum(String caseNum) {
    return crackdownStatusRepository.findTop1ByCaseNum(caseNum).orElse(null)==null?0:1;
  }

  public FishingBoatVersion selectFishingBoatVersion(Integer fbKey, Integer versionNo) {
    FishingBoatVersion fishingBoat = fishingBoatVersionRepository.findById(new FishingBoatVersion.FishingBoatVersionId(fbKey, versionNo)).orElse(null);
    fishingBoat.setViolationList(violationVersionRepository.findByFbKeyAndVersionNoOrderByViolationKeyAsc(fbKey, versionNo));
    return fishingBoat;
  }

  public FileInfo selectSailorFile(Integer sailorKey, Integer fileSeq) {
    return captionPhotoFileRepository.findById(new CaptinPhotoFile.CaptinPhotoFileId(sailorKey, fileSeq)).orElse(null);
  }

  private CrackdownStatus setWriteInfo(CrackdownStatus crackdownStatus){
    FishingBoat fishingBoat = crackdownStatus.getFishingBoat();
    fishingBoat.setWrtDt(LocalDateTime.now());

    crackdownStatus.setWrtOrgan(fishingBoat.getWrtOrgan());
    crackdownStatus.setWrtPart(fishingBoat.getWrtPart());
    crackdownStatus.setWrtUserSeq(fishingBoat.getWrtUserSeq());
    crackdownStatus.setWrtUserNm(fishingBoat.getWrtUserNm());
    crackdownStatus.setWrtUserGrd(fishingBoat.getWrtUserGrd());
    crackdownStatus.setWrtDt(LocalDateTime.now());

    crackdownStatus.getProcessResult().setWrtOrgan(fishingBoat.getWrtOrgan());
    crackdownStatus.getProcessResult().setWrtPart(fishingBoat.getWrtPart());
    crackdownStatus.getProcessResult().setWrtUserSeq(fishingBoat.getWrtUserSeq());
    crackdownStatus.getProcessResult().setWrtUserNm(fishingBoat.getWrtUserNm());
    crackdownStatus.getProcessResult().setWrtUserGrd(fishingBoat.getWrtUserGrd());
    crackdownStatus.getProcessResult().setWrtDt(LocalDateTime.now());

    for(Sailor sailor: crackdownStatus.getSailorList()){
      sailor.setWrtOrgan(fishingBoat.getWrtOrgan());
      sailor.setWrtPart(fishingBoat.getWrtPart());
      sailor.setWrtUserSeq(fishingBoat.getWrtUserSeq());
      sailor.setWrtUserNm(fishingBoat.getWrtUserNm());
      sailor.setWrtUserGrd(fishingBoat.getWrtUserGrd());
      sailor.setWrtDt(LocalDateTime.now());
    }
    return crackdownStatus;
  }

  @Value("${file.dir.sailor}")
  protected String sailorPath;

  private void saveCaptainPhoto(Integer sailorKey, Integer versionNo, List<MultipartFile> fileList){
    int fileSeq = 1;
    for(MultipartFile file : fileList){
      String saveName = UUID.randomUUID().toString();
      String path = locationPath+ File.separator+sailorPath+File.separator;
      saveFile(file, new File(path+File.separator+saveName));

      String originalFilename = file.getOriginalFilename();
      int extnIdx = originalFilename.lastIndexOf(".");
      CaptinPhotoFile fileInfo = new CaptinPhotoFile();
      fileInfo.setSailorKey(sailorKey);
      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);
      CaptinPhotoVersion versionInfo = new CaptinPhotoVersion();
      BeanUtils.copyProperties(fileInfo, versionInfo);
      versionInfo.setVersionNo(versionNo);
      captionPhotoFileRepository.save(fileInfo);
      captionPhotoVersionRepository.save(versionInfo);
    }
  }
}
