package org.jcnc.snow.compiler.ir.builder;

import org.jcnc.snow.compiler.ir.core.IROpCode;
import org.jcnc.snow.compiler.ir.core.IRValue;
import org.jcnc.snow.compiler.ir.instruction.BinaryOperationInstruction;
import org.jcnc.snow.compiler.ir.instruction.LoadConstInstruction;
import org.jcnc.snow.compiler.ir.instruction.CallInstruction;
import org.jcnc.snow.compiler.ir.value.IRConstant;
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode;
import org.jcnc.snow.compiler.parser.ast.CallExpressionNode;
import org.jcnc.snow.compiler.parser.ast.MemberExpressionNode;
import org.jcnc.snow.compiler.parser.ast.IdentifierNode;
import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode;
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * ExpressionBuilder 将 AST 中的 ExpressionNode 转换为 IR 指令，并返回结果的虚拟寄存器。
 * <p>
 * 支持以下表达式类型：
 * <ul>
 *   <li>NumberLiteralNode —— 常量字面量，生成 LoadConstInstruction；</li>
 *   <li>IdentifierNode —— 标识符，查找当前作用域寄存器；</li>
 *   <li>BinaryExpressionNode —— 二元运算，生成 BinaryOperationInstruction；</li>
 *   <li>CallExpressionNode —— 函数调用（同模块或模块静态），生成 CallInstruction。</li>
 * </ul>
 */
public class ExpressionBuilder {
    private static final Map<String, IROpCode> OP_I8 = Map.of(
            "+", IROpCode.ADD_B8, "-", IROpCode.SUB_B8,
            "*", IROpCode.MUL_B8, "/", IROpCode.DIV_B8
    );
    private static final Map<String, IROpCode> OP_I16 = Map.of(
            "+", IROpCode.ADD_S16, "-", IROpCode.SUB_S16,
            "*", IROpCode.MUL_S16, "/", IROpCode.DIV_S16
    );
    private static final Map<String, IROpCode> OP_I32 = Map.of(
            "+", IROpCode.ADD_I32, "-", IROpCode.SUB_I32,
            "*", IROpCode.MUL_I32, "/", IROpCode.DIV_I32
    );
    private static final Map<String, IROpCode> OP_L64 = Map.of(
            "+", IROpCode.ADD_L64, "-", IROpCode.SUB_L64,
            "*", IROpCode.MUL_L64, "/", IROpCode.DIV_L64
    );
    private static final Map<String, IROpCode> OP_F32 = Map.of(
            "+", IROpCode.ADD_F32, "-", IROpCode.SUB_F32,
            "*", IROpCode.MUL_F32, "/", IROpCode.DIV_F32
    );
    private static final Map<String, IROpCode> OP_D64 = Map.of(
            "+", IROpCode.ADD_D64, "-", IROpCode.SUB_D64,
            "*", IROpCode.MUL_D64, "/", IROpCode.DIV_D64
    );

    private final IRContext ctx;

    /**
     * 构造函数，传入 IRContext 用于生成寄存器和添加指令
     * @param ctx 构建上下文
     */
    public ExpressionBuilder(IRContext ctx) {
        this.ctx = ctx;
    }

    /**
     * 将 AST 表达式节点转换为 IR 指令，并返回结果寄存器
     * @param expr 表达式节点
     * @return 存放计算结果的虚拟寄存器
     */
    public IRVirtualRegister build(ExpressionNode expr) {
        // 1. 常量字面量处理
        if (expr instanceof NumberLiteralNode(String value)) {
            char suffix = value.isEmpty() ? '\0' : Character.toLowerCase(value.charAt(value.length() - 1));
            String digits = (suffix == 'b' || suffix == 's' || suffix == 'l' || suffix == 'f' || suffix == 'd')
                    ? value.substring(0, value.length() - 1)
                    : value;

            IRVirtualRegister reg = ctx.newRegister();
            switch (suffix) {
                case 'b' -> ctx.addInstruction(
                        new LoadConstInstruction(reg, new IRConstant(Byte.parseByte(digits)))
                );
                case 's' -> ctx.addInstruction(
                        new LoadConstInstruction(reg, new IRConstant(Short.parseShort(digits)))
                );
                case 'l' -> ctx.addInstruction(
                        new LoadConstInstruction(reg, new IRConstant(Long.parseLong(digits)))
                );
                case 'f' -> ctx.addInstruction(
                        new LoadConstInstruction(reg, new IRConstant(Float.parseFloat(digits)))
                );
                case 'd' -> ctx.addInstruction(
                        new LoadConstInstruction(reg, new IRConstant(Double.parseDouble(digits)))
                );
                default -> {
                    if (digits.contains(".") || digits.matches(".*[eE].*")) {
                        ctx.addInstruction(
                                new LoadConstInstruction(reg, new IRConstant(Double.parseDouble(digits)))
                        );
                    } else {
                        ctx.addInstruction(
                                new LoadConstInstruction(reg, new IRConstant(Integer.parseInt(digits)))
                        );
                    }
                }
            }
            return reg;
        }

        // 2. 变量标识符处理
        if (expr instanceof IdentifierNode(String name)) {
            IRVirtualRegister reg = ctx.getScope().lookup(name);
            if (reg == null) {
                throw new IllegalStateException("未定义标识符: " + name);
            }
            return reg;
        }

        // 3. 二元表达式处理
        if (expr instanceof BinaryExpressionNode(ExpressionNode left, String operator, ExpressionNode right)) {
            IRVirtualRegister lreg = build(left);
            IRVirtualRegister rreg = build(right);

            char suf = resolveSuffix(left, right);
            IROpCode code = switch (suf) {
                case 'b' -> OP_I8.get(operator);
                case 's' -> OP_I16.get(operator);
                case 'l' -> OP_L64.get(operator);
                case 'f' -> OP_F32.get(operator);
                case 'd' -> OP_D64.get(operator);
                default  -> OP_I32.get(operator);
            };
            if (code == null) {
                throw new IllegalStateException("不支持的运算符: " + operator);
            }
            IRVirtualRegister dest = ctx.newRegister();
            ctx.addInstruction(new BinaryOperationInstruction(code, dest, lreg, rreg));
            return dest;
        }

        // 4. 函数调用表达式处理
        if (expr instanceof CallExpressionNode(ExpressionNode callee, List<ExpressionNode> arguments)) {
            // 构造实参寄存器列表，使用 IRValue 类型
            List<IRValue> args = new ArrayList<>();
            for (ExpressionNode argNode : arguments) {
                args.add(build(argNode));
            }
            // 解析 callee
            String fullName;
            if (callee instanceof MemberExpressionNode(ExpressionNode object, String member)
                    && object instanceof IdentifierNode(String name)) {
                // 模块静态调用
                fullName = name + "." + member;
            } else if (callee instanceof IdentifierNode(String name)) {
                // 同模块调用
                fullName = name;
            } else {
                throw new IllegalStateException(
                        "不支持的调用目标: " + callee.getClass().getSimpleName()
                );
            }
            IRVirtualRegister dest = ctx.newRegister();
            ctx.addInstruction(new CallInstruction(dest, fullName, args));
            return dest;
        }

        throw new IllegalStateException(
                "不支持的表达式类型: " + expr.getClass().getSimpleName()
        );
    }

    /**
     * 决定二元运算类型后缀，基于两侧 NumberLiteralNode 的后缀。
     */
    private char resolveSuffix(ExpressionNode left, ExpressionNode right) {
        char l = (left instanceof NumberLiteralNode(String value))
                ? Character.toLowerCase(value.charAt(value.length() - 1))
                : '\0';
        char r = (right instanceof NumberLiteralNode(String value))
                ? Character.toLowerCase(value.charAt(value.length() - 1))
                : '\0';
        if (l == 'd' || r == 'd') return 'd';
        if (l == 'f' || r == 'f') return 'f';
        if (l == 'l' || r == 'l') return 'l';
        if (l == 's' || r == 's') return 's';
        if (l == 'b' || r == 'b') return 'b';
        return '\0';
    }
}
