package incheon.ags.drm.service.impl;

import incheon.ags.drm.mapper.DrmBbsMapper;
import incheon.ags.drm.service.DrmBbsService;
import incheon.ags.drm.vo.DrmBbsCmntVO;
import incheon.ags.drm.vo.DrmBbsFileVO;
import incheon.ags.drm.vo.DrmBbsVO;
import incheon.ags.mrb.analysis.web.SpatialAnalysisController;
import lombok.RequiredArgsConstructor;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;

@Service("drmBbsService")
@RequiredArgsConstructor
public class DrmBbsServiceImpl extends EgovAbstractServiceImpl implements DrmBbsService {

    private static final Logger logger = LoggerFactory.getLogger(SpatialAnalysisController.class);
    private final DrmBbsMapper drmBbsMapper;

    // OS별 절대 경로 주입
    @Value("${drm.upload.base-path.win}")
    private String winFilePath;
    @Value("${drm.upload.base-path.linux}")
    private String linuxFilePath;
    // OS에 따라 경로를 결정
    private String getOsDependentBasePath() {
        String rawOsName = System.getProperty("os.name");
        String osName = (rawOsName != null) ? rawOsName.toLowerCase() : "linux";

        if (osName.contains("win")) {
            return this.winFilePath;
        } else {
            return this.linuxFilePath;
        }
    }
    public Path getFilePath () throws Exception {
        // OS에 따라 baseDir 문자열을 획득
        String baseDirString = getOsDependentBasePath();
        Path baseDir = Paths.get(baseDirString);

        // 분류에 따른 하위 폴더 경로 설정
        String subPath = "ags/drm/bbs";

        /* 저장 디렉토리 경로 생성 */
        // baseDir (절대 경로)와 subPath를 결합합니다. (OS 독립적)
        Path dirPath = baseDir.resolve(subPath);

        // 디렉토리 생성
        if (!Files.exists(dirPath)) {
            Files.createDirectories(dirPath);
        }

        // 최종 파일 경로 반환
        return dirPath;
    }

    @Override
    public DrmBbsVO selectBbsShp(Long bbsShpId) throws Exception {
        return drmBbsMapper.selectBbsShp(bbsShpId);
    }
    @Override
    public List<DrmBbsVO> selectBbsCttList(DrmBbsVO drmBbsVO) throws Exception {
        return drmBbsMapper.selectBbsCttList(drmBbsVO);
    }
    @Override
    public int selectBbsCttListCnt(DrmBbsVO drmBbsVO) throws Exception {
        return drmBbsMapper.selectBbsCttListCnt(drmBbsVO);
    }
    @Override
    public void registerBbsCtt(DrmBbsVO drmBbsVO, List<MultipartFile> attachedFiles) throws Exception {
        // insert 후 BBSCTT_ID 값 return
        drmBbsMapper.registerBbsCtt(drmBbsVO);

        if (attachedFiles == null || attachedFiles.isEmpty()) return;

        Long bbsCttId = drmBbsVO.getBbsCttId();
        Path uploadDirPath = getFilePath();
        if (!Files.exists(uploadDirPath)) {
            Files.createDirectories(uploadDirPath);
        }

        for (MultipartFile file : attachedFiles) {

            if (file.isEmpty()) continue;

            // 저장할 파일명 생성 (파일명 중복 방지)
            String originalFileName = file.getOriginalFilename();
            if (originalFileName == null || originalFileName.contains("..")) {
                throw new IllegalArgumentException("부적절한 파일명입니다.");
            }

            // 확장자 획득
            String fileExtension = "";
            int dotIndex = originalFileName.lastIndexOf('.');
            if (dotIndex > 0) {
                fileExtension = originalFileName.substring(dotIndex);
            }

            // 저장 파일명 생성
            String savedFileName = UUID.randomUUID().toString() + fileExtension;
            // 최종 파일 저장 경로
            Path finalFilePath = uploadDirPath.resolve(savedFileName);
            // 파일 저장 (물리적 저장)
            try {
                Files.copy(file.getInputStream(), finalFilePath, StandardCopyOption.REPLACE_EXISTING);

                // 첨부 파일 정보 DB 저장
                DrmBbsFileVO fileVO = new DrmBbsFileVO();
                fileVO.setBbsCttId(bbsCttId);
                fileVO.setOrgnlAtchFileNm(originalFileName);
                fileVO.setSrvrAtchFileNm(savedFileName);
                fileVO.setAtchmnflCpct(file.getSize());
                fileVO.setAtchmnflStrgPath(uploadDirPath.toString());

                drmBbsMapper.registerBbsFile(fileVO);
            } catch (IOException e) {
                // 파일 저장 실패 시 예외 처리
                logger.error("시스템 오류가 발생했습니다: {}", "파일 저장 실패", e);
                throw new RuntimeException("파일 저장 중 시스템 오류가 발생했습니다.", e);
            }
        }
    }
    @Override
    public DrmBbsVO selectBbsCttDetail(Long bbsCttId) throws Exception {
        drmBbsMapper.plusInqCnt(bbsCttId);
        DrmBbsVO resultVO = drmBbsMapper.selectBbsCttDetail(bbsCttId);
        drmBbsMapper.plusTinqCnt(resultVO.getBbsShpId());

        List<DrmBbsFileVO> fileList = drmBbsMapper.selectBbsFileList(bbsCttId);
        resultVO.setFileList(fileList);

        List<DrmBbsCmntVO> cmntList = drmBbsMapper.selectBbsCmntList(bbsCttId);
        resultVO.setCmntList(cmntList);

        return resultVO;
    }
    @Override
    public void registerBbsCmnt(DrmBbsCmntVO drmBbsCmntVO) throws Exception {
        drmBbsMapper.registerBbsCmnt(drmBbsCmntVO);
    }
    @Override
    public void deleteBbsCmnt(Long cmntId) throws Exception {
        drmBbsMapper.deleteBbsCmnt(cmntId);
    }
    @Override
    public void updateBbsCtt(DrmBbsVO drmBbsVO, List<MultipartFile> attachedFiles) throws Exception {
        Long bbsCttId = drmBbsVO.getBbsCttId();

        if (attachedFiles != null && !attachedFiles.isEmpty()) {
            // 기존 첨부파일 삭제 처리
            List<DrmBbsFileVO> existingFiles = drmBbsMapper.selectBbsFileList(bbsCttId);
            for (DrmBbsFileVO existingFile : existingFiles) {
                try {
                    Path filePathToDelete = Paths.get(existingFile.getAtchmnflStrgPath()).resolve(existingFile.getSrvrAtchFileNm());
                    if (Files.exists(filePathToDelete)) { Files.delete(filePathToDelete); }

                } catch (IOException | SecurityException e) {
                    // 파일 삭제 실패 시 경고 (시스템 흐름 유지)
                    logger.error("시스템 오류가 발생했습니다: {}", "물리적 파일 삭제 실패", e);
                }
            }

            // DB 첨부파일들 정보 삭제
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("bbsCttId", drmBbsVO.getBbsCttId());
            drmBbsMapper.deleteBbsFilesExcluding(paramMap);

            Path uploadDirPath = getFilePath();

            for (MultipartFile file : attachedFiles) {
                if (file.isEmpty()) continue;

                // 저장할 파일명 생성 (파일명 중복 방지)
                String originalFileName = file.getOriginalFilename();
                // 확장자 획득
                String fileExtension = "";
                int dotIndex = originalFileName.lastIndexOf('.');
                if (dotIndex > 0) fileExtension = originalFileName.substring(dotIndex);
                // 저장 파일명 생성
                String savedFileName = UUID.randomUUID().toString() + fileExtension;
                // 최종 파일 저장 경로
                Path finalFilePath = uploadDirPath.resolve(savedFileName);
                // 파일 저장 (물리적 저장)
                try {
                    Files.copy(file.getInputStream(), finalFilePath, StandardCopyOption.REPLACE_EXISTING);

                    // 첨부 파일 정보 DB 저장
                    DrmBbsFileVO fileVO = new DrmBbsFileVO();
                    fileVO.setBbsCttId(bbsCttId);
                    fileVO.setOrgnlAtchFileNm(originalFileName);
                    fileVO.setSrvrAtchFileNm(savedFileName);
                    fileVO.setAtchmnflCpct(file.getSize());
                    fileVO.setAtchmnflStrgPath(uploadDirPath.toString());

                    drmBbsMapper.registerBbsFile(fileVO);
                } catch (IOException e) {
                    // 파일 저장 실패 시 예외 처리
                    logger.error("시스템 오류가 발생했습니다: {}", "파일 저장 실패", e);
                    throw new RuntimeException("파일 저장 중 오류가 발생했습니다.", e);
                }
            }
        }

        drmBbsMapper.updateBbsCtt(drmBbsVO);

    }
    @Override
    public void deleteBbsCtt(Long bbsCttId) throws Exception {
        List<DrmBbsFileVO> existingFiles = drmBbsMapper.selectBbsFileList(bbsCttId);
        // 관련 첨부파일 전체 삭제 처리
        for (DrmBbsFileVO existingFile : existingFiles) {
            try {
                Path filePathToDelete = Paths.get(existingFile.getAtchmnflStrgPath())
                                            .resolve(existingFile.getSrvrAtchFileNm())
                                            .normalize();;
                if (Files.exists(filePathToDelete)) {
                    Files.delete(filePathToDelete);
                }
            } catch (IOException | SecurityException e) {
                // 파일 삭제 실패 시 경고 (시스템 흐름 유지)
                logger.error("시스템 오류가 발생했습니다: {}", "물리적 파일 삭제 실패", e);
            }
        }
        drmBbsMapper.deleteTotalBbsFile(bbsCttId);
        drmBbsMapper.deleteTotalBbsCmnt(bbsCttId);
        drmBbsMapper.deleteBbsCtt(bbsCttId);
    }
}
