package incheon.ags.pss.edit.web;

import java.util.List;
import java.util.Locale;

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.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.util.StringUtils;

import incheon.ags.pss.edit.service.ModelService;
import incheon.ags.pss.edit.vo.ModelVO;
import incheon.com.cmm.api.DefaultApiResponse;
import incheon.com.cmm.ResponseCode;
import incheon.ags.pss.edit.util.UploadFileValidator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 안건지도 3D 모델 관리 컨트롤러
 * @author hj
 */
@Controller
@RequiredArgsConstructor
@Slf4j
@RequestMapping("/pss/edit/model")
public class ModelController {

    private final ModelService modelService;

    @Value("${Globals.pss.upload.path}")
    private String uploadPath;

    private Path absoluteUploadPath;

    @PostConstruct
    public void init() {
        this.absoluteUploadPath = Paths.get(uploadPath).toAbsolutePath().normalize();
        log.info("모델 업로드 절대 경로: {}", this.absoluteUploadPath);
    }

    @GetMapping("/list.do")
    public ResponseEntity<DefaultApiResponse> selectModelList(Long bizNo) throws Exception {
    	List<ModelVO> list = modelService.selectModelList(bizNo);
         
		return ResponseEntity.ok(
				DefaultApiResponse.success(list, "조회되었습니다.")
		);
    }
    
    @PostMapping("/insert.do")
    public ResponseEntity<DefaultApiResponse> insertModel(ModelVO vo) throws Exception {
        try {
            validateReferencedModel(vo);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(
                    DefaultApiResponse.error(ResponseCode.INPUT_ERROR.getCode(), e.getMessage(), "INVALID_FILE_CONTENT")
            );
        }

         modelService.insertModel(vo);
         
         return ResponseEntity.ok(
                 DefaultApiResponse.success(vo.getMdlNo(), "저장되었습니다.")
             );
    }

    @PostMapping("/update.do")
    public ResponseEntity<DefaultApiResponse> updateModel(ModelVO vo) throws Exception {
        try {
            validateReferencedModel(vo);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(
                    DefaultApiResponse.error(ResponseCode.INPUT_ERROR.getCode(), e.getMessage(), "INVALID_FILE_CONTENT")
            );
        }

         modelService.updateModel(vo);
         
         return ResponseEntity.ok(
                 DefaultApiResponse.success(vo, "수정되었습니다.")
             );
    }

    @PostMapping("/delete.do")
    public ResponseEntity<DefaultApiResponse> deleteModel(String mdlNo) throws Exception {
    	modelService.deleteModel(mdlNo);
         
      	return ResponseEntity.ok(
    			DefaultApiResponse.success(null, "삭제되었습니다.")
		);
    }

    private void validateReferencedModel(ModelVO vo) {
        if (vo == null) return;

        // 외부 URL 업로드/등록은 허용하지 않음
        if (StringUtils.hasText(vo.getTrgtUrl())) {
            String trgtUrl = vo.getTrgtUrl().trim();
            if (looksLikeExternalUrl(trgtUrl)) {
                throw new IllegalArgumentException("외부 URL 기반 파일 등록은 허용되지 않습니다.");
            }

            Path local = toLocalUploadPath(trgtUrl);
            String ext = inferExtension(trgtUrl, vo.getFileNm());
            UploadFileValidator.requireValidLocalFile(local, ext);
        }

        if (StringUtils.hasText(vo.getFlpth())) {
            String flpth = vo.getFlpth().trim();
            Path local = toLocalUploadPath(flpth);
            String ext = inferExtension(flpth, vo.getFileNm());
            UploadFileValidator.requireValidLocalFile(local, ext);
        }
    }

    private boolean looksLikeExternalUrl(String pathOrUrl) {
        String s = (pathOrUrl == null ? "" : pathOrUrl.trim()).toLowerCase(Locale.ROOT);
        return s.startsWith("http://") || s.startsWith("https://");
    }

    private Path toLocalUploadPath(String flpthOrUrl) {
        String s = (flpthOrUrl == null ? "" : flpthOrUrl.trim());

        if (s.startsWith("/resources/pss/")) {
            s = s.substring("/resources/pss/".length());
        }
        if (s.startsWith("/incheon-geo-platform/upload/pss/")) {
            s = s.substring("/incheon-geo-platform/upload/pss/".length());
        }

        while (s.startsWith("/") || s.startsWith("\\")) {
            s = s.substring(1);
        }

        Path local = absoluteUploadPath.resolve(s).normalize();
        if (!local.startsWith(absoluteUploadPath)) {
            throw new IllegalArgumentException("파일 경로가 올바르지 않습니다.");
        }
        return local;
    }

    private String inferExtension(String pathOrUrl, String fileNm) {
        String ext = org.springframework.util.StringUtils.getFilenameExtension(StringUtils.hasText(fileNm) ? fileNm : pathOrUrl);
        if (!StringUtils.hasText(ext)) {
            throw new IllegalArgumentException("파일 확장자가 없습니다.");
        }
        return ext.toLowerCase(Locale.ROOT).trim();
    }
}
