package com.zhpb.gdyd_zhpb_zgf.service;

import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.file.*;
import java.util.Locale;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * 统一管理文件存储路径，负责在不同运行环境下解析/归一化文件路径。
 */
@Component
public class FilePathResolver {

    private static final Logger logger = LoggerFactory.getLogger(FilePathResolver.class);

    @Value("${file.upload-path:./uploads}")
    private String uploadPathConfig;

    @Value("${file.extract-path:./extracts}")
    private String extractPathConfig;

    private Path absoluteUploadPath;
    private Path absoluteExtractPath;

    @PostConstruct
    public void init() {
        this.absoluteUploadPath = ensureAbsolutePath(uploadPathConfig);
        this.absoluteExtractPath = ensureAbsolutePath(extractPathConfig);
        logger.info("文件上传根目录: {}", absoluteUploadPath);
        logger.info("文件解压根目录: {}", absoluteExtractPath);
    }

    public Path getAbsoluteUploadPath() {
        return absoluteUploadPath;
    }

    public Path getAbsoluteExtractPath() {
        return absoluteExtractPath;
    }

    /**
     * 将绝对路径归一化为可存储的字符串。
     * 如果位于解压目录下，则返回相对路径，便于跨平台迁移。
     */
    public String normalizeForStorage(Path absolutePath) {
        if (absolutePath == null) {
            return null;
        }
        Path normalized = absolutePath.toAbsolutePath().normalize();
        if (isUnder(normalized, absoluteExtractPath)) {
            Path relative = absoluteExtractPath.relativize(normalized);
            return toForwardSlash(relative.toString());
        }
        return toForwardSlash(normalized.toString());
    }

    /**
     * 将数据库中存储的路径转换为当前环境下的绝对路径（不保证文件存在）。
     */
    public Path resolveStoredPath(String storedPath) {
        if (storedPath == null || storedPath.trim().isEmpty()) {
            return null;
        }
        String trimmed = storedPath.trim();
        Path candidate = Paths.get(trimmed);
        if (candidate.isAbsolute()) {
            return candidate.toAbsolutePath().normalize();
        }
        return absoluteExtractPath.resolve(trimmed).normalize();
    }

    /**
     * 综合多种策略解析真实存在的文件路径。
     * 如果 storedPath 对应的文件不存在，则尝试：
     * 1. 用当前解压根目录替换旧的绝对路径前缀
     * 2. 在解压目录下按项目ID查找同名文件
     */
    public Optional<Path> resolveExistingPath(String storedPath, String projectId, String fileName) {
        Path direct = resolveStoredPath(storedPath);
        if (direct != null && Files.exists(direct)) {
            return Optional.of(direct);
        }

        Optional<Path> suffixCandidate = tryResolveByExtractSuffix(storedPath);
        if (suffixCandidate.isPresent()) {
            Path candidate = suffixCandidate.get();
            if (Files.exists(candidate)) {
                return Optional.of(candidate);
            }
        }

        return searchInProject(projectId, fileName);
    }

    private Optional<Path> searchInProject(String projectId, String fileName) {
        if (projectId == null || projectId.isBlank() || fileName == null || fileName.isBlank()) {
            return Optional.empty();
        }
        try (DirectoryStream<Path> projectDirs = Files.newDirectoryStream(absoluteExtractPath, projectId + "*")) {
            for (Path projectDir : projectDirs) {
                if (!Files.isDirectory(projectDir)) {
                    continue;
                }
                Optional<Path> match = findFileRecursively(projectDir, fileName);
                if (match.isPresent()) {
                    return match;
                }
            }
        } catch (IOException e) {
            logger.warn("搜索项目目录失败: {}", e.getMessage());
        }
        return Optional.empty();
    }

    private Optional<Path> findFileRecursively(Path dir, String fileName) throws IOException {
        try (Stream<Path> stream = Files.walk(dir, 12)) {
            return stream.filter(Files::isRegularFile)
                    .filter(path -> path.getFileName().toString().equalsIgnoreCase(fileName))
                    .findFirst();
        }
    }

    private Optional<Path> tryResolveByExtractSuffix(String storedPath) {
        if (storedPath == null) {
            return Optional.empty();
        }
        String lower = storedPath.toLowerCase(Locale.ROOT);
        int idx = lower.indexOf("extracts");
        if (idx == -1) {
            return Optional.empty();
        }
        int start = idx + "extracts".length();
        while (start < storedPath.length() &&
                (storedPath.charAt(start) == '\\' || storedPath.charAt(start) == '/')) {
            start++;
        }
        if (start >= storedPath.length()) {
            return Optional.empty();
        }
        String relative = storedPath.substring(start);
        Path candidate = absoluteExtractPath.resolve(relative).normalize();
        return Optional.of(candidate);
    }

    private Path ensureAbsolutePath(String configPath) {
        Path path = Paths.get(configPath);
        if (!path.isAbsolute()) {
            String baseDir = System.getProperty("user.dir");
            if (baseDir == null || baseDir.isEmpty()) {
                baseDir = System.getProperty("user.home");
            }
            path = Paths.get(baseDir, configPath);
        }
        Path normalized = path.toAbsolutePath().normalize();
        try {
            Files.createDirectories(normalized);
        } catch (IOException e) {
            logger.warn("创建目录失败: {}", normalized, e);
        }
        return normalized;
    }

    private boolean isUnder(Path child, Path root) {
        try {
            return child.startsWith(root);
        } catch (Exception e) {
            return false;
        }
    }

    private String toForwardSlash(String input) {
        return input.replace("\\", "/");
    }
}

