package tech.easyflow.publicapi;

import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.expr.MemberValuePair;
import com.github.javaparser.ast.expr.NormalAnnotationExpr;
import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
import com.mybatisflex.core.MybatisFlexBootstrap;
import com.mybatisflex.core.query.QueryWrapper;
import com.zaxxer.hikari.HikariDataSource;
import tech.easyflow.system.entity.SysApiKeyResource;
import tech.easyflow.system.mapper.SysApiKeyResourceMapper;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 同步接口到数据库
 */
public class SyncApis {

    public static void main(String[] args) throws Exception {

        try (HikariDataSource dataSource = new HikariDataSource()) {
            dataSource.setJdbcUrl("jdbc:mysql://192.168.2.10:3306/easyflow-v2?useInformationSchema=true&characterEncoding=utf-8");
            dataSource.setUsername("root");
            dataSource.setPassword("123456");

            MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance();
            bootstrap.setDataSource(dataSource);
            bootstrap.addMapper(SysApiKeyResourceMapper.class);
            bootstrap.start();

            SysApiKeyResourceMapper mapper = bootstrap.getMapper(SysApiKeyResourceMapper.class);
            String dir = System.getProperty("user.dir") + "/easyflow-api/easyflow-api-public/src/main/java/tech/easyflow/publicapi/controller";
            List<String> filePath = getAllFilePaths(dir);
            for (String path : filePath) {
                extractCommentsFromFile(path, mapper);
            }
        }
    }

    public static List<String> getAllFilePaths(String directoryPath) throws IOException {
        Path startPath = Paths.get(directoryPath);

        try (Stream<Path> stream = Files.walk(startPath)) {
            return stream
                    .filter(Files::isRegularFile)      // 只获取文件，排除目录
                    .map(Path::toAbsolutePath)         // 转换为绝对路径
                    .map(Path::toString)               // 转换为字符串
                    .collect(Collectors.toList());
        }
    }

    public static void extractCommentsFromFile(String filePath, SysApiKeyResourceMapper mapper) throws Exception {
        System.out.println("正在解析文件: " + filePath);
        FileInputStream in = new FileInputStream(filePath);
        com.github.javaparser.JavaParser parser = new com.github.javaparser.JavaParser();
        parser.getParserConfiguration().setLanguageLevel(com.github.javaparser.ParserConfiguration.LanguageLevel.JAVA_17);
        CompilationUnit cu = parser.parse(in).getResult().orElseThrow();

        cu.findAll(ClassOrInterfaceDeclaration.class).forEach(c -> {
            // 1. 获取类级别的 RequestMapping 路径
            String classPath = "";
            Optional<AnnotationExpr> classMapping = c.getAnnotationByName("RequestMapping");
            if (classMapping.isPresent()) {
                classPath = getAnnotationValue(classMapping.get());
            }

            String finalClassPath = classPath; //用于lambda中使用
            String className = c.getNameAsString();
            String classComment = c.getJavadoc().map(d -> d.getDescription().toText()).orElse("");

            System.out.println("=========================================");
            System.out.println("类名: " + className);
            System.out.println("类注释: " + classComment);
            System.out.println("类路径: " + finalClassPath);

            // 2. 遍历方法
            c.getMethods().forEach(method -> {
                // 查找常见的 Mapping 注解
                String[] mappingTypes = {"GetMapping", "PostMapping", "PutMapping", "DeleteMapping", "PatchMapping", "RequestMapping"};

                for (String mappingType : mappingTypes) {
                    Optional<AnnotationExpr> methodMapping = method.getAnnotationByName(mappingType);
                    if (methodMapping.isPresent()) {
                        // 获取方法上的路径
                        String methodPath = getAnnotationValue(methodMapping.get());

                        // 拼接完整 URI
                        String fullUri = combinePaths(finalClassPath, methodPath);

                        // 获取请求方式 (如果是 RequestMapping，通常默认为 All 或者需要进一步解析 method 属性，这里简单处理)
                        String httpMethod = mappingType.replace("Mapping", "").toUpperCase();
                        if (httpMethod.equals("REQUEST")) httpMethod = "ALL";

                        // 获取方法注释
                        String methodComment = method.getJavadoc().map(doc -> doc.getDescription().toText()).orElse("");

                        System.out.println("--------------------------------");
                        System.out.println("  方法名: " + method.getNameAsString());
                        System.out.println("  类型: " + httpMethod);
                        System.out.println("  完整URI: " + fullUri);
                        System.out.println("  方法注释: " + methodComment);

                        // 可以在这里调用 mapper 存入数据库
                        QueryWrapper w = QueryWrapper.create();
                        w.eq(SysApiKeyResource::getRequestInterface, fullUri);
                        SysApiKeyResource record = mapper.selectOneByQuery(w);
                        if (record != null) {
                            record.setTitle(methodComment);
                            mapper.insertOrUpdate(record);
                        } else {
                            record = new SysApiKeyResource();
                            record.setRequestInterface(fullUri);
                            record.setTitle(methodComment);
                            mapper.insert(record);
                        }
                    }
                }
            });
        });
    }

    /**
     * 解析注解中的 value 或 path 值
     * 处理几种情况:
     * 1. @GetMapping("/api") -> SingleMemberAnnotationExpr
     * 2. @GetMapping(value = "/api") -> NormalAnnotationExpr
     * 3. @GetMapping(path = "/api") -> NormalAnnotationExpr
     * 4. @GetMapping -> 默认为空字符串
     */
    private static String getAnnotationValue(AnnotationExpr annotation) {
        // 情况 1: @GetMapping("/path")
        if (annotation instanceof SingleMemberAnnotationExpr) {
            String value = ((SingleMemberAnnotationExpr) annotation).getMemberValue().toString();
            return removeQuotes(value);
        }
        // 情况 2: @GetMapping(value="/path") 或 @GetMapping(path="/path")
        else if (annotation instanceof NormalAnnotationExpr) {
            NormalAnnotationExpr normal = (NormalAnnotationExpr) annotation;
            for (MemberValuePair pair : normal.getPairs()) {
                String key = pair.getNameAsString();
                if ("value".equals(key) || "path".equals(key)) {
                    return removeQuotes(pair.getValue().toString());
                }
            }
        }
        // 情况 3: @GetMapping (没有参数)
        return "";
    }

    /**
     * 去除 JavaParser 解析出的字符串中的双引号
     */
    private static String removeQuotes(String value) {
        if (value == null) return "";
        return value.replace("\"", "").trim();
    }

    /**
     * 拼接类路径和方法路径，处理斜杠
     */
    private static String combinePaths(String classPath, String methodPath) {
        if (classPath == null) classPath = "";
        if (methodPath == null) methodPath = "";

        // 确保以 / 开头
        if (!classPath.startsWith("/") && !classPath.isEmpty()) classPath = "/" + classPath;
        if (!methodPath.startsWith("/") && !methodPath.isEmpty()) methodPath = "/" + methodPath;

        // 如果 classPath 只有 /，去掉它，避免 //method
        if (classPath.equals("/")) classPath = "";

        String full = classPath + methodPath;
        // 处理重复斜杠 (例如 class=/api/ method=/list -> /api//list)
        return full.replace("//", "/");
    }
}
