package quant.rich.emoney.util;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;

import lombok.extern.slf4j.Slf4j;

/**
 * 资源解析器，用于在不同运行状况（JAR 包、WAR 包及 IDE 调试状态）下读写本地资源
 */
@Slf4j
public class SmartResourceResolver {
    
    private static RunningFrom runningFrom;
    
    static {
        if (isRunningFromJar()) {
            runningFrom = RunningFrom.JAR;
        }
        else if (isRunningFromWar()) {
            runningFrom = RunningFrom.WAR;
        }
        else {
            runningFrom = RunningFrom.IDE;
        }
    }
    
    /**
     获取资源
    <p>
      <ul>
        <li>JAR
          <ul>
            <li>优先以 jar 文件所在目录为基准，寻找相对路径外部文件</li>
            <li>当外部文件不存在时，读取 classpath，即 jar 内部资源文件</li>
          </ul>
        </li>
        <li>WAR 只获取 classpath 文件，即 /WEB-INF/classes/ 下文件</li>
        <li>IDE 只获取源文件，即 src/main/resources/ 下文件</li>
      </ul></p>
     * @param relativePath 相对路径
     * @param writable 是否一定可写
     * @return
     * @throws IOException 
     */
    public static InputStream loadResource(String relativePath) throws IOException {
        Path externalPath = resolveExternalPath(relativePath);

        if (externalPath != null && Files.exists(externalPath)) {
            log.debug("Load resource externally: {}", externalPath);
            return Files.newInputStream(externalPath);
        }

        // 否则回退到 classpath（JAR、WAR、IDE）
        InputStream in = SmartResourceResolver.class.getClassLoader().getResourceAsStream(relativePath);
        if (in != null) {
            log.debug("Load resource within internal classpath: {}", relativePath);
            return in;
        }

        throw new FileNotFoundException("Cannot find resources: " + relativePath);
    }
    
    public static void saveText(String relativePath, String content) throws IOException {
        Path outputPath = resolveExternalPath(relativePath);
        Files.createDirectories(outputPath.getParent()); // 确保目录存在
        Files.writeString(outputPath, content, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
        log.debug("Write resources externally success: {}", outputPath);
    }

    private static Path resolveExternalPath(String relativePath) {
        try {
            Path basePath;
            if (runningFrom == RunningFrom.JAR) {
                basePath = Paths.get(SmartResourceResolver.class.getProtectionDomain()
                        .getCodeSource().getLocation().toURI()).getParent();
                return basePath.resolve(relativePath).normalize();
            } else if (runningFrom == RunningFrom.WAR) {
                basePath = Paths.get(SmartResourceResolver.class.getProtectionDomain()
                        .getCodeSource().getLocation().toURI()); // e.g., WEB-INF/classes/
                return basePath.resolve(relativePath).normalize();
            } else {
                // IDE 环境：返回 src/main/resources 下真实文件
                return Paths.get("src/main/resources", relativePath).normalize();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static boolean isRunningFromJar() {
        String path = SmartResourceResolver.class.getResource(
                SmartResourceResolver.class.getSimpleName() + ".class").toString();
        return path.startsWith("jar:");
    }

    private static boolean isRunningFromWar() {
        String path = SmartResourceResolver.class.getResource(
                SmartResourceResolver.class.getSimpleName() + ".class").toString();
        return path.contains("/WEB-INF/classes/");
    }
    
    private static enum RunningFrom {
        JAR,
        WAR,
        IDE
    }
}
