package cn.meowrain.aioj.backend.fileservice.controller;

import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 本地文件访问控制器
 *
 * @author meowrain
 * @since 2026-01-10
 */
@Slf4j
@RestController
@ConditionalOnProperty(prefix = "file-config", name = "use-cloud", havingValue = "false", matchIfMissing = true)
public class FileAccessController {

    @Value("${file-config.local.base-path:uploads}")
    private String basePath;

    @Value("${file-config.local.domain:http://localhost:10013}")
    private String domain;

    @Value("${server.servlet.context-path:}")
    private String contextPath;

    @GetMapping("/file/**")
    @Operation(summary = "访问本地文件")
    public void accessFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String requestURI = request.getRequestURI();
        // 去除 context-path 和 /file 前缀，获取相对路径
        String prefix = contextPath + "/file";
        String filePath = requestURI.substring(prefix.length());

        // 移除开头的斜杠（如果有）
        if (filePath.startsWith("/")) {
            filePath = filePath.substring(1);
        }

        if (StrUtil.isBlank(filePath)) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }

        // 使用 Paths.get 自动处理路径分隔符
        Path targetPath = Paths.get(basePath, filePath).normalize();

        // 安全检查：防止路径遍历攻击
        if (!targetPath.startsWith(Paths.get(basePath).normalize())) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            return;
        }

        if (!Files.exists(targetPath)) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        String contentType = Files.probeContentType(targetPath);
        if (StrUtil.isBlank(contentType)) {
            contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
        }

        response.setContentType(contentType);
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
                "inline; filename=\"" + targetPath.getFileName().toString() + "\"");

        Files.copy(targetPath, response.getOutputStream());
    }
}
