package com.huangzj.protoplugin;

import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.PsiManager;
import com.intellij.openapi.ui.Messages;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;

public class ProtoCmdGeneratorAction extends AnAction {

    @Override
    public void update(@NotNull AnActionEvent e) {
        VirtualFile vf = e.getData(CommonDataKeys.VIRTUAL_FILE);
        if (vf == null) {
            PsiFile pf = e.getData(CommonDataKeys.PSI_FILE);
            if (pf != null) {
                vf = pf.getVirtualFile();
            }
        }
        boolean proto = vf != null && "proto".equalsIgnoreCase(vf.getExtension());
        // 主菜单（如 Tools）：始终显示条目，非 proto 时禁用，避免用户找不到入口。
        // 编辑器/项目树右键：仅在看 .proto 时显示，减少菜单噪音。
        String place = e.getPlace();
        if (ActionPlaces.isPopupPlace(place)) {
            e.getPresentation().setEnabledAndVisible(proto);
        } else {
            e.getPresentation().setVisible(true);
            e.getPresentation().setEnabled(proto);
        }
    }

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        Project project = e.getProject();
        VirtualFile protoFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
        if (protoFile == null) {
            PsiFile pf = e.getData(CommonDataKeys.PSI_FILE);
            if (pf != null) {
                protoFile = pf.getVirtualFile();
            }
        }
        if (project == null || protoFile == null) {
            return;
        }

        String text;
        try {
            text = new String(protoFile.contentsToByteArray(), StandardCharsets.UTF_8);
        } catch (Exception ex) {
            Messages.showErrorDialog(project, ex.getMessage(), "读取 proto 失败");
            return;
        }

        ProtoParseResult parsed = ProtoFileParser.parse(text);
        if (parsed.getRpcMethods().isEmpty()) {
            Messages.showWarningDialog(
                    project,
                    "当前文件未解析到 service/rpc。\n需 service 命名为 Service1Service、Service2Service…，且 rpc 为标准 proto3 语法。",
                    "未找到 RPC");
            return;
        }

        Map<Integer, String> pbMap = Map.of();
        VirtualFile parent = protoFile.getParent();
        if (parent != null) {
            VirtualFile pbSvc = parent.findChild("pb_service.proto");
            if (pbSvc != null) {
                try {
                    String pbText = new String(pbSvc.contentsToByteArray(), StandardCharsets.UTF_8);
                    pbMap = ProtoEnumResolver.parsePbServiceByNumber(pbText);
                } catch (Exception ignored) {
                }
            }
        }

        GenerateCmdDialog dialog = new GenerateCmdDialog(project, parsed, text, pbMap);
        if (!dialog.showAndGet()) {
            return;
        }

        List<RpcMethodInfo> selected = dialog.getSelectedRpcs();
        VirtualFile outDir = dialog.getOutputDirectory();
        String outPkg = dialog.getOutputPackage();
        String protoJavaPkg = dialog.getProtoJavaPackage();

        if (outDir == null) {
            return;
        }

        int[] created = {0};
        int[] skipped = {0};

        WriteCommandAction.runWriteCommandAction(project, () -> {
                    PsiDirectory psiDir = PsiManager.getInstance(project).findDirectory(outDir);
                    if (psiDir == null) {
                        return;
                    }
                    PsiFileFactory factory = PsiFileFactory.getInstance(project);
                    for (RpcMethodInfo rpc : selected) {
                        String className = rpc.getRpcName() + ".java";
                        if (psiDir.findFile(className) != null) {
                            skipped[0]++;
                            continue;
                        }
                        String pbConst = dialog.resolvePbServiceEnumName(rpc);
                        String methodConst = dialog.resolveMethodEnumConstant(rpc);
                        String src =
                                JavaCommandGenerator.generate(
                                        rpc, outPkg, protoJavaPkg, pbConst, methodConst);
                        PsiFile psiFile =
                                factory.createFileFromText(className, JavaLanguage.INSTANCE, src);
                        psiDir.add(psiFile);
                        created[0]++;
                    }
                });

        Messages.showInfoMessage(
                project,
                "新建 " + created[0] + " 个文件，跳过已存在 " + skipped[0] + " 个。",
                "Proto转Java 完成");
    }
}
