package incheon.ags.pss.edit.web;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
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.multipart.MultipartFile;
import org.springframework.util.StringUtils;
import java.util.Set;

import de.huxhorn.sulky.ulid.ULID;
import incheon.com.cmm.api.DefaultApiResponse;
import incheon.com.cmm.ResponseCode;
import incheon.com.cmm.context.RequestContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import incheon.ags.pss.edit.service.FileUploadHistoryService;
import incheon.ags.pss.edit.vo.FileUploadHistoryVO;
import incheon.ags.pss.edit.util.UploadFileValidator;

/**
 * 3D 모델 등 즉시 업로드 컨트롤러
 * @author hj
 */
@Controller
@RequiredArgsConstructor
@Slf4j
@RequestMapping("/pss/edit/upload")
public class FileUploadHistoryController {

    private final FileUploadHistoryService historyService;
    
    @Value("${Globals.pss.upload.path}")
    private String uploadPath;
    
    private Path absoluteUploadPath;
    
    private final ULID ulid = new ULID();

    @PostConstruct
    public void init() {
        this.absoluteUploadPath = Paths.get(uploadPath).toAbsolutePath().normalize();
        
        log.info("파일 업로드 절대 경로: {}", this.absoluteUploadPath);
    }
    
    /**
     * 3D 모델 파일 업로드 (업로드 즉시 History DB 저장)
     */
    @PostMapping("/model.do")
    public ResponseEntity<DefaultApiResponse> uploadModelFile(
            @RequestParam("file") MultipartFile file,
            @RequestParam("bizNo") Long bizNo,
            @RequestParam("fileTypeCd") String fileTypeCd
        ) throws Exception {

        try {
            // 허용 확장자만 업로드 가능
            String ext = UploadFileValidator.requireAllowedExtension(file, Set.of("glb", "ifc", "zip"));
            // 확장자 위변조 방지: 실제 파일 포맷(콘텐츠) 최소 검증
            UploadFileValidator.requireValidContent(file, ext);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(
                    DefaultApiResponse.error(ResponseCode.INPUT_ERROR.getCode(), e.getMessage(), "INVALID_FILE_CONTENT")
            );
        }

        // --- 1. 파일 저장 로직 (YYYY/MM) ---
        String year = String.valueOf(LocalDate.now().getYear());
        String month = String.format("%02d", LocalDate.now().getMonthValue());
        Path absoluteDirPath = absoluteUploadPath.resolve(year).resolve(month);
        
        log.info("absoluteDirPath: {}", absoluteDirPath);
        
        log.info("uploadPath: {}", uploadPath);

        // 1-2. 디렉토리 생성
        if (!Files.exists(absoluteDirPath)) {
            Files.createDirectories(absoluteDirPath);
        }
        
        String orgnlFileNm = file.getOriginalFilename();
        
        // 1-3. 저장 파일명 생성 (ULID.확장자)
        String extension = StringUtils.getFilenameExtension(orgnlFileNm);
        String strgFileNm = ulid.nextValue().toString() +
                              (StringUtils.hasText(extension) ? "." + extension : "");
        
        // 1-4. 파일 저장
        Path filePath = absoluteDirPath.resolve(strgFileNm);
        file.transferTo(filePath.toFile());
        
        //DB에 저장할 상대 경로
        String relativePath = year + "/" + month + "/" + strgFileNm;
        
        // --- 2. DB 이력 저장 (빌더 패턴) ---
        FileUploadHistoryVO hist = FileUploadHistoryVO.builder()
            .bizNo(bizNo)
            .fileTypeCd(fileTypeCd)
            .trgtUrl("/resources/pss/"+relativePath)
            .orgnlFileNm(orgnlFileNm)
            .strgFileNm(strgFileNm)
            .flpth("/incheon-geo-platform/upload/pss/"+relativePath) // 상대 경로 저장
            .filesiz(file.getSize())
            .contsType(file.getContentType())
            .uldStcd("CMPT")
            .build();
        hist.setLOGIN_USER_ID(RequestContext.getCurrentUserId());
        
        historyService.insertFileUploadHistory(hist);
        
        // --- 3. 프론트엔드로 파일 정보 반환 ---
        String urlPath = "/resources/pss/" + relativePath; 
        
        Map<String, Object> fileInfoMap = Map.of(
            "flpth", urlPath, 
            "fileNm", orgnlFileNm,
            "filesiz", file.getSize()
        );

        return ResponseEntity.ok(
                DefaultApiResponse.success(fileInfoMap, "모델 파일이 서버에 업로드되었습니다.")
            );
    }
}