package incheon.uis.ums.file.web;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.egovframe.rte.fdl.property.EgovPropertyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import incheon.com.cmm.service.ResultVO;
import incheon.uis.ums.file.dto.AttachUploadRequestDTO;
import incheon.uis.ums.file.service.CmtFileService;
import incheon.uis.ums.file.vo.CmtFileVO;
import incheon.uis.ums.mapper.ConstructionSeqMapper;
import incheon.uis.ums.service.DynamicModelService;
import incheon.uis.ums.service.UisAttachFileService;
import incheon.uis.ums.util.UisConstructionNumberGenerator;
import incheon.uis.ums.util.UisFileUtils;
import incheon.uis.ums.web.UisBaseController;

/**
 * 공통 파일 관리 Controller
 */
@Controller
@RequestMapping("/uis/file")
public class CmtFileController  extends UisBaseController {


    public CmtFileController( ConstructionSeqMapper constructionSeqMapper
            , UisConstructionNumberGenerator constructionNumberGenerator
            , DynamicModelService dynamicModelService
            , EgovPropertyService propertyService
            , CmtFileService cmtFileService
            , UisFileUtils uisFileUtils
            , UisAttachFileService uisAttachFileService) {
        super(constructionSeqMapper, constructionNumberGenerator, dynamicModelService);
        this.propertyService = propertyService;
        this.cmtFileService = cmtFileService;
        this.uisFileUtils =uisFileUtils;
        this.uisAttachFileService = uisAttachFileService;
    }

    @Autowired
    protected EgovPropertyService propertyService;

    @Autowired
    private CmtFileService cmtFileService;

    @Autowired
    private UisFileUtils uisFileUtils;

    @Autowired
    private UisAttachFileService uisAttachFileService;
    
    /**
     * 파일 시퀀스로 이미지 표시
     * @param fileSeq 파일순서
     * @return 이미지 파일
     */
    @GetMapping("/image.do")
    public ResponseEntity<Resource> getImageByFileSeq(@RequestParam("fileSeq") BigDecimal fileSeq) {

        try {
            // 1. 파일 정보 조회
            CmtFileVO fileInfo = cmtFileService.getFileBySeq(fileSeq);

            if (fileInfo == null) {
                throw new FileNotFoundException("[ERROR] File not found in DB. fileSeq: " + fileSeq);
            }

            // 2. 실제 파일 경로 생성
            Path filePath = uisFileUtils.getFullPath(fileInfo.getFldrPathNm(), fileInfo.getSrvrStrgFileNm());

            // 3. 파일 존재 확인
            if (!Files.exists(filePath)) {
                throw new FileNotFoundException("Image file not found: " + filePath);
            }

            File file = filePath.toFile();

            // 파일 리소스 생성
            Resource resource = new FileSystemResource(file);

            // 파일 확장자에 따른 Content-Type 설정
            String contentType = uisFileUtils.getImageContentType(file.getName());

            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + file.getName() + "\"")
                    .body(resource);

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 파일 시퀀스로 파일 다운로드
     * @param fileSeq 파일순서
     * @return 다운로드 파일
     */
    @GetMapping("/download.do")
    public ResponseEntity<Resource> downloadFileByFileSeq(@RequestParam("fileSeq") BigDecimal fileSeq) {

        try {
            // 1. 파일 정보 조회
            CmtFileVO fileInfo = cmtFileService.getFileBySeq(fileSeq);

            if (fileInfo == null) {
                throw new FileNotFoundException("[ERROR] File not found in DB. fileSeq: " + fileSeq);
            }

            // 2. 실제 파일 경로 생성
            Path filePath = uisFileUtils.getFullPath(fileInfo.getFldrPathNm(), fileInfo.getSrvrStrgFileNm());

            // 3. 파일 존재 확인
            if (!Files.exists(filePath)) {
                throw new FileNotFoundException("File not found: " + filePath);
            }

            // 4. 파일 읽기 권한 확인
            if (!Files.isReadable(filePath)) {
                throw new IOException("File is not readable: " + filePath);
            }

            File file = filePath.toFile();

            // 파일 리소스 생성
            Resource resource = new FileSystemResource(file);

            // 원본 파일명 (DB에 저장된 원본 파일명 사용)
            String originalFilename = fileInfo.getDwnldFileNm(); // 또는 적절한 필드명

            // 파일명 인코딩 (한글 파일명 처리)
            String encodedFilename = uisFileUtils.encodeFilename(originalFilename);

            // 파일 확장자에 따른 Content-Type 설정
            String contentType = uisFileUtils.getContentType(originalFilename);

            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFilename + "\"")
                    .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(file.length()))
                    .body(resource);

        } catch (FileNotFoundException e) {
            throw new RuntimeException("파일을 찾을 수 없습니다.", e);
        } catch (IOException e) {
            throw new RuntimeException("파일 처리 중 오류가 발생했습니다.", e);
        }
    }

    /**
     * 파일 업로드
     * multiple.do 로 통합해서 사용함 (호출 X)
     * @param file 업로드할 파일
     * @param rmrkCn 비고내용 (선택)
     * @return 업로드된 파일 정보
     */
    @PostMapping("/upload.do")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> uploadFile(
            @RequestParam("file") MultipartFile file,
            @RequestParam("gubun") String gubun,
            @RequestParam("entity") String entity,
            @RequestParam(value = "rmrkCn", required = false) String rmrkCn,
            HttpServletRequest request) {

        Map<String, Object> result = new HashMap<>();

        try {
            // 1. 파일 유효성 검사
            if (file == null || file.isEmpty()) {
                result.put("success", false);
                result.put("message", "업로드할 파일이 없습니다.");
                return ResponseEntity.badRequest().body(result);
            }

            // 2. 파일 크기 제한 (예: 10MB)
            long maxFileSize = propertyService.getLong("Globals.posblAtchFileSize");
            //long maxFileSize = 10 * 1024 * 1024; // 10MB
            if (file.getSize() > maxFileSize) {
                result.put("success", false);
                result.put("message", "파일 크기는 " + maxFileSize/1048576 + "MB를 초과할 수 없습니다.");
                return ResponseEntity.badRequest().body(result);
            }


            // 4. 파일 저장
            CmtFileVO fileVO = uisFileUtils.saveUploadedFile(file, entity, request);

            // 5. DB에 파일 정보 저장
            int insertResult = cmtFileService.insertFile(fileVO);

            if (insertResult > 0) {
                result.put("success", true);
                result.put("message", "파일이 성공적으로 업로드되었습니다.");
                result.put("fileSeq", fileVO.getFileSeq());
                result.put("fileName", fileVO.getDwnldFileNm());
                result.put("fileSize", fileVO.getOrgnlFileSz());
                return ResponseEntity.ok(result);
            }else{
                result.put("success", false);
                result.put("message", "파일 정보 저장에 실패했습니다.");
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
            }

        } catch (DataAccessException dae) {
            // DB 계열(중요)
            result.put("success", false);
            result.put("message", "서버 처리 중 오류가 발생했습니다.");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);

        } catch (IOException ioe) {
            // 파일 I/O 계열(중요)
            result.put("success", false);
            result.put("message", "파일 처리 중 오류가 발생했습니다.");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);

        } catch (RuntimeException re) {
            // 예상 못 한 런타임
            result.put("success", false);
            result.put("message", "서버 처리 중 오류가 발생했습니다.");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }

    /**
     * 다중 파일 업로드
     * @param files 업로드할 파일 목록
     * @param gubun 업로드할 파일 목록
     * @param entity 업로드할 파일 목록
     * @param prntIdn 연결할 idn
     * @param rmrkCn 비고내용 (선택)
     * @return 업로드된 파일 정보 목록
     */
    @PostMapping("/upload/multiple.do")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> uploadMultipleFiles(
    		@RequestPart("files") MultipartFile[] files,
            @RequestPart(value="attachAttr") AttachUploadRequestDTO attachAttr,
            HttpServletRequest request) {

        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> uploadedFiles = new ArrayList<>();
        List<String> errors = new ArrayList<>();

        try {
            if (files == null || files.length == 0) {
                result.put("success", false);
                result.put("message", "업로드할 파일이 없습니다.");
                return ResponseEntity.badRequest().body(result);
            }

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

                //파일 업로드
                ResultVO resultVO =  uisAttachFileService.saveFileandAttach(file, attachAttr, request);

                //결과
                if(resultVO.getResultCode() > -1) {
                    Map<String, Object> fileInfo = new HashMap<>();
                    fileInfo.put("fileName", file.getOriginalFilename());
                    uploadedFiles.add(fileInfo);
                }else {
                	errors.add(resultVO.getResultMessage());
                }
            }

            result.put("success", uploadedFiles.size() > 0);
            result.put("uploadedCount", uploadedFiles.size());
            result.put("uploadedFiles", uploadedFiles);

            if (!errors.isEmpty()) {
                result.put("errors", errors);
                result.put("message", uploadedFiles.size() + "개 파일 업로드 성공, " + errors.size() + "개 실패");
                result.put("success", uploadedFiles.size() > 0);
                result.put("partial", true);
            } else {
                result.put("message", "모든 파일이 성공적으로 업로드되었습니다.");
                result.put("success", true);
                result.put("partial", false);
            }

            return ResponseEntity.ok(result);

        } catch (DataAccessException dae) {
            result.put("success", false);
            result.put("message", "서버 처리 중 오류가 발생했습니다.");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);

        } catch (RuntimeException re) {
            result.put("success", false);
            result.put("message", "서버 처리 중 오류가 발생했습니다.");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
        }
    }



}
