package incheon.ags.drm.web;

import incheon.ags.drm.service.DrmBbsService;
import incheon.ags.drm.service.agsDrmService;
import incheon.ags.drm.service.impl.DrmBbsServiceImpl;
import incheon.ags.drm.service.impl.agsDrmServiceImpl;
import incheon.ags.drm.vo.DrmContentVO;
import incheon.ags.mrb.analysis.web.SpatialAnalysisController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

@RestController
public class agsDrmFileDownloadController {

    private static final Logger logger = LoggerFactory.getLogger(SpatialAnalysisController.class);
    private final agsDrmService agsDrmService;
    private final DrmBbsService drmBbsService;

    public agsDrmFileDownloadController(agsDrmService agsDrmService, DrmBbsService drmBbsService) {
        this.agsDrmService = agsDrmService;
        this.drmBbsService = drmBbsService;
    }

    @GetMapping("/ags/drm/content/{contsId}/{type}")
    public ResponseEntity<Resource> downloadContentFile(
            @PathVariable Long contsId,
            @PathVariable String type
    ) {
        try {
            // 파일 정보 조회
            DrmContentVO contentVO = agsDrmService.searchContentDetail(contsId);

            // 파일의 실제 절대 경로
            Path filePath = ((agsDrmServiceImpl) agsDrmService).getFilePath(contentVO.getContsClsf(), contentVO.getContsFileNm());

            // 파일 경로 변환 (Spring Resource 객체)
            Resource resource = new UrlResource(filePath.toUri());
            if (!resource.exists() || !resource.isReadable()) {
                throw new FileNotFoundException("File not found or unreadable: " + contentVO.getContsFileNm());
            }

            // Content-Type (MIME Type) 결정 및 설정
            String contentType = getContentType(filePath, contentVO.getContsFileNm());

            // 파일명 인코딩
            String encodedFileName = URLEncoder.encode(contentVO.getContsFileNm(), StandardCharsets.UTF_8.toString())
                    .replaceAll("\\+", "%20");

            String dispositionType;
            if (type != null && type.equalsIgnoreCase("attachment")) {
                dispositionType = "attachment"; // 다운로드 강제
            } else {
                dispositionType = "inline";     // 브라우저 표시 (기본값 또는 'inline' 입력 시)
            }

            String contentDispositionHeader =
                    dispositionType + "; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName;

            return ResponseEntity.ok()
                    // 정확한 MIME Type 설정
                    .contentType(MediaType.parseMediaType(contentType))
                    // inline으로 설정하여 브라우저가 화면에 바로 표출하도록 지시 (3D 모델, 파노라마 필수)
                    .header(HttpHeaders.CONTENT_DISPOSITION, contentDispositionHeader)
                    // 파일 리소스를 응답 본문에 담아 전송
                    .body(resource);

        } catch (FileNotFoundException e) {
            // 파일이 없으면 404 Not Found
            logger.error("시스템 오류가 발생했습니다: {}", "콘텐츠 파일 조회", e);
            return ResponseEntity.notFound().build();
        } catch (Exception e) {
            // 기타 오류 발생 시 서버 오류(500) 응답
            logger.error("시스템 오류가 발생했습니다: {}", "콘텐츠 파일 조회", e);
            return ResponseEntity.internalServerError().build();
        }
    }

    // 파일 경로와 파일명을 기반으로 Content-Type(MIME Type) 결정
    private String getContentType(Path filePath, String fileName) throws IOException {
        String contentType = Files.probeContentType(filePath);

        // probeContentType이 타입을 유추하지 못하는 경우 (FBX, HDR 등)
        if (contentType == null) {
            String lowerCaseFileName = fileName.toLowerCase();

            if (lowerCaseFileName.endsWith(".fbx")) { return "application/octet-stream"; }
            if (lowerCaseFileName.endsWith(".hdr") || lowerCaseFileName.endsWith(".exr")) { return "application/octet-stream"; }
            if (lowerCaseFileName.endsWith(".obj")) { return "model/obj"; }
            if (lowerCaseFileName.endsWith(".mtl")) { return "model/mtl"; }

            return "application/octet-stream";
        }

        return contentType;
    }

    @GetMapping("/ags/drm/bbsFile/{saveName}/{originalName}")
    public ResponseEntity<Resource> downloadBbsFile (
            @PathVariable String saveName,
            @PathVariable String originalName
    ) {
        try {
            // 파일의 실제 절대 경로
            Path dirPath = ((DrmBbsServiceImpl) drmBbsService).getFilePath();
            Path filePath = dirPath.resolve(saveName);

            // 파일 경로 변환
            Resource resource = new UrlResource(filePath.toUri());
            if (!resource.exists() || !resource.isReadable()) {
                throw new FileNotFoundException("BBS File not found or unreadable: " + saveName);
            }

            // MIME Type 결정 및 설정
            String fileType = Files.probeContentType(filePath);
            if (fileType == null) {
                fileType = "application/octet-stream"; // 일반적인 이진 파일
            }

            // 파일명 인코딩
            String encodedFileName = URLEncoder.encode(originalName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
            String contentDispositionHeader = "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName;

            return ResponseEntity.ok()
                    // MIME Type 설정
                    .contentType(MediaType.parseMediaType(fileType))
                    // attachment로 설정하여 강제 다운로드
                    .header(HttpHeaders.CONTENT_DISPOSITION, contentDispositionHeader)
                    // 파일 리소스를 응답 본문에 담아 전송
                    .body(resource);

        } catch (FileNotFoundException e) {
            // 파일이 없으면 404 Not Found
            logger.error("시스템 오류가 발생했습니다: {}", "게시글 첨부파일 다운로드", e);
            return ResponseEntity.notFound().build();
        } catch (Exception e) {
            // 기타 오류 발생 시 서버 오류(500) 응답
            logger.error("시스템 오류가 발생했습니다: {}", "게시글 첨부파일 다운로드", e);
            return ResponseEntity.internalServerError().build();
        }
    }
}
