package go.kr.project.common.service.impl;

import egovframework.constant.FileContentTypeConstants;
import egovframework.filter.XssUtil;
import egovframework.util.FileUtil;
import go.kr.project.common.mapper.HtmlEditorMapper;
import go.kr.project.common.model.FileVO;
import go.kr.project.common.model.HtmlEditorFileVO;
import go.kr.project.common.service.HtmlEditorService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * packageName    : go.kr.project.common.service.impl
 * fileName       : HtmlEditorServiceImpl
 * author         : 개발자
 * date           : 2025-05-23
 * description    : HTML 에디터 관련 비즈니스 로직을 처리하는 서비스 구현체
 * ===========================================================
 * DATE              AUTHOR             NOTE
 * -----------------------------------------------------------
 * 2025-05-23        개발자       최초 생성
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HtmlEditorServiceImpl extends EgovAbstractServiceImpl implements HtmlEditorService {

    private final HtmlEditorMapper htmlEditorMapper;
    private final FileUtil fileUtil;
    private final XssUtil xssUtil;

    /**
     * 파일 정보를 조회합니다.
     * 
     * @param fileId 파일 ID
     * @return 파일 정보
     */
    @Override
    public HtmlEditorFileVO selectHtmlEditorFile(String fileId) {
        return htmlEditorMapper.selectHtmlEditorFile(fileId);
    }

    /**
     * 모듈에 첨부된 파일 목록을 조회합니다.
     * 
     * @param moduleId 모듈 ID
     * @return 파일 목록
     */
    @Override
    public List<HtmlEditorFileVO> selectHtmlEditorFileListByModuleId(String moduleId) {
        return htmlEditorMapper.selectHtmlEditorFileListByModuleId(moduleId);
    }

    /**
     * 파일 목록을 조회합니다.
     * 
     * @param vo 검색 조건을 담은 VO 객체
     * @return 파일 목록
     */
    @Override
    public List<HtmlEditorFileVO> selectHtmlEditorFileList(HtmlEditorFileVO vo) {
        return htmlEditorMapper.selectHtmlEditorFileList(vo);
    }

    /**
     * 파일 목록의 총 개수를 조회합니다.
     * 
     * @param vo 검색 조건을 담은 VO 객체
     * @return 파일 목록의 총 개수
     */
    @Override
    public int selectHtmlEditorFileListTotalCount(HtmlEditorFileVO vo) {
        return htmlEditorMapper.selectHtmlEditorFileListTotalCount(vo);
    }

    /**
     * 파일 정보를 삭제합니다.
     * 
     * @param fileId 파일 ID
     * @return 삭제된 행의 수
     */
    @Override
    @Transactional
    public int deleteHtmlEditorFile(String fileId) {
        // 파일 정보 조회
        HtmlEditorFileVO fileVO = htmlEditorMapper.selectHtmlEditorFile(fileId);
        int result = htmlEditorMapper.deleteHtmlEditorFile(fileId);

        if (result > 0 && fileVO != null) {
            // FileVO로 변환
            FileVO fileInfo = new FileVO();
            fileInfo.setOriginalFileNm(fileVO.getOriginalFileNm());
            fileInfo.setStoredFileNm(fileVO.getStoredFileNm());
            fileInfo.setFilePath(fileVO.getFilePath());
            fileInfo.setFileSize(fileVO.getFileSize());
            fileInfo.setFileExt(fileVO.getFileExt());

            // 실제 파일 삭제
            fileUtil.deleteFile(fileInfo);
        }

        return result;
    }

    /**
     * 모듈에 첨부된 파일 정보를 삭제합니다.
     * 
     * @param moduleId 모듈 ID
     * @return 삭제된 행의 수
     */
    @Override
    @Transactional
    public int deleteHtmlEditorFileByModuleId(String moduleId) {
        // 모듈에 첨부된 파일 목록 조회
        List<HtmlEditorFileVO> fileList = htmlEditorMapper.selectHtmlEditorFileListByModuleId(moduleId);
        int result = htmlEditorMapper.deleteHtmlEditorFileByModuleId(moduleId);

        if (result > 0 && !fileList.isEmpty()) {
            for (HtmlEditorFileVO fileVO : fileList) {
                // FileVO로 변환
                FileVO fileInfo = new FileVO();
                fileInfo.setOriginalFileNm(fileVO.getOriginalFileNm());
                fileInfo.setStoredFileNm(fileVO.getStoredFileNm());
                fileInfo.setFilePath(fileVO.getFilePath());
                fileInfo.setFileSize(fileVO.getFileSize());
                fileInfo.setFileExt(fileVO.getFileExt());

                // 실제 파일 삭제
                fileUtil.deleteFile(fileInfo);
            }
        }

        return result;
    }

    /**
     * 파일을 다운로드합니다.
     * 
     * @param fileId 다운로드할 파일의 ID
     * @param request HTTP 요청 객체
     * @param response HTTP 응답 객체
     */
    @Override
    public void downloadHtmlEditorFile(String fileId, HttpServletRequest request, HttpServletResponse response) {
        // 파일 정보 조회
        HtmlEditorFileVO fileVO = htmlEditorMapper.selectHtmlEditorFile(fileId);

        if (fileVO == null) {
            throw new RuntimeException("파일 정보를 찾을 수 없습니다: " + fileId);
        }

        // FileVO로 변환
        FileVO fileInfo = new FileVO();
        fileInfo.setOriginalFileNm(fileVO.getOriginalFileNm());
        fileInfo.setStoredFileNm(fileVO.getStoredFileNm());
        fileInfo.setFilePath(fileVO.getFilePath());
        fileInfo.setFileSize(fileVO.getFileSize());
        fileInfo.setFileExt(fileVO.getFileExt());

        // ContentType 설정 (파일 확장자에 따라 MIME 타입 추정)
        String fileExt = fileVO.getFileExt().toLowerCase();
        String contentType = FileContentTypeConstants.getContentType(fileExt);

        fileInfo.setContentType(contentType);

        // FileUtil을 사용하여 파일 다운로드
        try {
            fileUtil.downloadFile(fileInfo, request, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 파일 업로드 처리를 수행합니다.
     * 
     * @param file 업로드할 파일
     * @param moduleId 모듈 ID (선택적)
     * @param fileType 파일 타입 (image, video 등)
     * @param rgtr 등록자
     * @return 업로드된 파일 정보
     */
    @Override
    @Transactional
    public HtmlEditorFileVO uploadHtmlEditorFile(MultipartFile file, String moduleId, String fileType, String rgtr) {
        if (file == null || file.isEmpty()) {
            throw new RuntimeException("업로드할 파일이 없습니다.");
        }

        List<MultipartFile> files = new ArrayList<>();
        files.add(file);

        List<HtmlEditorFileVO> uploadedFiles = uploadHtmlEditorFiles(files, moduleId, fileType, rgtr);

        if (uploadedFiles.isEmpty()) {
            throw new RuntimeException("파일 업로드에 실패했습니다.");
        }

        return uploadedFiles.get(0);
    }

    /**
     * 여러 파일 업로드 처리를 수행합니다.
     * 
     * @param files 업로드할 파일 목록
     * @param moduleId 모듈 ID (선택적)
     * @param fileType 파일 타입 (image, video 등)
     * @param rgtr 등록자
     * @return 업로드된 파일 정보 목록
     */
    @Override
    @Transactional
    public List<HtmlEditorFileVO> uploadHtmlEditorFiles(List<MultipartFile> files, String moduleId, String fileType, String rgtr) {
        List<HtmlEditorFileVO> result = new ArrayList<>();

        if (files == null || files.isEmpty()) {
            return result;
        }

        // 빈 파일 제거
        List<MultipartFile> validFiles = new ArrayList<>();
        for (MultipartFile file : files) {
            if (!file.isEmpty()) {
                validFiles.add(file);
            }
        }

        if (validFiles.isEmpty()) {
            return result;
        }

        // FileUtil을 사용하여 파일 업로드
        List<FileVO> uploadedFiles;
        try {
            // 설정 파일에서 하위 디렉토리 경로 가져오기
            String subDir = fileUtil.getSubDir("html-editor");
            uploadedFiles = fileUtil.uploadFiles(validFiles, subDir);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        for (FileVO uploadedFile : uploadedFiles) {
            // 파일 ID 생성
            String fileId = htmlEditorMapper.generateFileId();

            // 파일 정보 VO 생성
            HtmlEditorFileVO fileVO = new HtmlEditorFileVO();
            fileVO.setFileId(fileId);
            fileVO.setModuleId(moduleId);
            fileVO.setOriginalFileNm(uploadedFile.getOriginalFileNm());
            fileVO.setStoredFileNm(uploadedFile.getStoredFileNm());
            fileVO.setFilePath(uploadedFile.getFilePath());
            fileVO.setFileSize(uploadedFile.getFileSize());
            fileVO.setFileExt(uploadedFile.getFileExt());
            fileVO.setFileType(fileType);
            fileVO.setUseYn("Y");
            fileVO.setRgtr(rgtr);
            fileVO.setMdfr(rgtr);

            // 파일 정보 DB 등록
            htmlEditorMapper.insertHtmlEditorFile(fileVO);

            result.add(fileVO);
        }

        return result;
    }

    /**
     * 파일 정보를 수정합니다.
     * 
     * @param vo 수정할 파일 정보를 담은 VO 객체
     * @return 수정된 행의 수
     */
    @Override
    @Transactional
    public int updateHtmlEditorFile(HtmlEditorFileVO vo) {
        return htmlEditorMapper.updateHtmlEditorFile(vo);
    }
}
