package com.huangzj.protoplugin.json;

import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
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.huangzj.protoplugin.PackageInference;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.components.JBTextArea;
import com.intellij.util.ui.JBUI;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.jetbrains.annotations.Nullable;

/** 输入 JSON 与类名，在选中目录生成 Java 源文件。 */
public final class JsonToJavaDialog extends DialogWrapper {

    private final Project project;
    private final @Nullable VirtualFile folder;
    private final JBTextArea jsonArea;
    private final JTextField classNameField;
    private final JTextField packageField;

    public JsonToJavaDialog(Project project, @Nullable VirtualFile folder) {
        super(project);
        this.project = project;
        this.folder = folder;
        setTitle("Json 转 Java");
        jsonArea = new JBTextArea(12, 48);
        jsonArea.setLineWrap(true);
        jsonArea.setWrapStyleWord(true);
        classNameField = new JTextField(32);
        String pkg = PackageInference.inferPackage(folder);
        packageField = new JTextField(pkg, 32);
        init();
    }

    @Override
    protected @Nullable JComponent createCenterPanel() {
        JPanel root = new JPanel(new GridBagLayout());
        root.setBorder(JBUI.Borders.empty(8));
        GridBagConstraints gc = new GridBagConstraints();
        gc.insets = JBUI.insets(4);
        gc.anchor = GridBagConstraints.WEST;
        gc.fill = GridBagConstraints.HORIZONTAL;
        gc.gridx = 0;
        gc.gridy = 0;
        root.add(new JBLabel("Java 类名（不含 .java）:"), gc);
        gc.gridx = 1;
        gc.weightx = 1.0;
        root.add(classNameField, gc);
        gc.gridy++;
        gc.gridx = 0;
        gc.weightx = 0;
        root.add(new JBLabel("包名:"), gc);
        gc.gridx = 1;
        gc.weightx = 1.0;
        root.add(packageField, gc);
        gc.gridy++;
        gc.gridx = 0;
        gc.gridwidth = 2;
        gc.weightx = 1.0;
        gc.weighty = 0;
        root.add(new JBLabel("JSON（根须为对象 {}）:"), gc);
        gc.gridy++;
        gc.fill = GridBagConstraints.BOTH;
        gc.weighty = 1.0;
        JBScrollPane scroll = new JBScrollPane(jsonArea);
        scroll.setPreferredSize(new Dimension(480, 220));
        root.add(scroll, gc);
        return root;
    }

    @Override
    protected void doOKAction() {
        String rawName = classNameField.getText().trim();
        if (rawName.isEmpty()) {
            Messages.showWarningDialog(project, "请填写类名。", "Json 转 Java");
            return;
        }
        if (!isValidJavaIdentifier(rawName)) {
            Messages.showWarningDialog(project, "类名不是合法 Java 标识符。", "Json 转 Java");
            return;
        }
        String json = jsonArea.getText().trim();
        if (json.isEmpty()) {
            Messages.showWarningDialog(project, "请填写 JSON。", "Json 转 Java");
            return;
        }
        if (folder == null || !folder.isDirectory()) {
            Messages.showWarningDialog(project, "请在项目树中选择输出目录。", "Json 转 Java");
            return;
        }
        String pkg = packageField.getText().trim();
        String src;
        try {
            src = JsonToJavaGenerator.generate(json, rawName, pkg);
        } catch (Exception ex) {
            Messages.showErrorDialog(project, ex.getMessage(), "JSON 解析失败");
            return;
        }
        String fileName = rawName.endsWith(".java") ? rawName : rawName + ".java";
        int[] created = {0};
        int[] skipped = {0};
        WriteCommandAction.runWriteCommandAction(
                project,
                () -> {
                    PsiDirectory psiDir = PsiManager.getInstance(project).findDirectory(folder);
                    if (psiDir == null) {
                        return;
                    }
                    if (psiDir.findFile(fileName) != null) {
                        skipped[0]++;
                        return;
                    }
                    PsiFileFactory factory = PsiFileFactory.getInstance(project);
                    PsiFile psiFile =
                            factory.createFileFromText(fileName, JavaLanguage.INSTANCE, src);
                    psiDir.add(psiFile);
                    created[0]++;
                });
        if (skipped[0] > 0) {
            Messages.showWarningDialog(
                    project, "文件已存在，未覆盖: " + fileName, "Json 转 Java");
            return;
        }
        if (created[0] > 0) {
            Messages.showInfoMessage(project, "已生成: " + fileName, "Json 转 Java");
        }
        super.doOKAction();
    }

    private static boolean isValidJavaIdentifier(String name) {
        if (name.isEmpty()) {
            return false;
        }
        if (!Character.isJavaIdentifierStart(name.charAt(0))) {
            return false;
        }
        for (int i = 1; i < name.length(); i++) {
            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
                return false;
            }
        }
        return true;
    }
}
