package click.kamil.springstatemachineexporter.ast.common;

import click.kamil.springstatemachineexporter.model.State;
import org.eclipse.jdt.core.dom.*;

public class StateResolver {
    private final CodebaseContext context;

    public StateResolver(CodebaseContext context) {
        this.context = context;
    }

    public State resolveState(Expression expr, CompilationUnit cu) {
        if (expr == null)
            return null;

        // 1. Check for constants
        String resolvedValue = context.getConstantResolver().resolve(expr, context);
        if (resolvedValue != null) {
            return State.of(expr.toString(), resolvedValue);
        }

        // 2. Check for @Value fields (SimpleName)
        if (expr instanceof SimpleName sn) {
            String fieldName = sn.getIdentifier();
            TypeDeclaration td = click.kamil.springstatemachineexporter.ast.common.AstUtils.findEnclosingType(sn);
            if (td != null) {
                String value = findValueFromField(td, fieldName);
                if (value != null) {
                    return State.of(fieldName, value);
                }
            }
        }

        if (expr instanceof StringLiteral sl)
            return State.of(sl.getLiteralValue());

        String raw = expr.toString();
        if (expr instanceof QualifiedName qn) {
            String full = resolveQualifiedName(qn, cu);
            return State.of(raw, full);
        }
        if (expr instanceof SimpleName sn) {
            String full = resolveSimpleName(sn, cu);
            return State.of(raw, full);
        }
        return State.of(raw);
    }

    private String findValueFromField(TypeDeclaration td, String fieldName) {
        for (FieldDeclaration fd : td.getFields()) {
            for (Object fragObj : fd.fragments()) {
                if (fragObj instanceof VariableDeclarationFragment fragment) {
                    if (fragment.getName().getIdentifier().equals(fieldName)) {
                        // Check for @Value annotation
                        for (Object mod : fd.modifiers()) {
                            if (mod instanceof Annotation ann) {
                                String name = ann.getTypeName().getFullyQualifiedName();
                                if (name.endsWith("Value")) {
                                    return extractAnnotationValue(ann);
                                }
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    private String extractAnnotationValue(Annotation ann) {
        String raw = click.kamil.springstatemachineexporter.ast.common.AstUtils.extractAnnotationMember(ann, "value");
        if (raw.isEmpty()) {
            return null;
        }
        raw = stripQuotes(raw);
        if (raw != null && raw.contains("${")) {
            return click.kamil.springstatemachineexporter.analysis.util.PlaceholderResolver.resolve(
                    raw, java.util.Collections.emptyMap());
        }
        return raw;
    }

    private String stripQuotes(String s) {
        if (s == null) return null;
        return s.replaceAll("^\"|\"$", "");
    }

    private String resolveQualifiedName(QualifiedName qn, CompilationUnit cu) {
        String qualifier = qn.getQualifier().toString();
        String name = qn.getName().getIdentifier();
        TypeDeclaration td = context.getTypeDeclaration(qualifier, cu);
        if (td != null)
            return context.getFqn(td) + "." + name;
        return qn.getFullyQualifiedName();
    }

    private String resolveSimpleName(SimpleName sn, CompilationUnit cu) {
        String name = sn.getIdentifier();
        if (cu == null)
            return name;
        for (Object impObj : cu.imports()) {
            ImportDeclaration imp = (ImportDeclaration) impObj;
            String impName = imp.getName().getFullyQualifiedName();
            if (impName.endsWith("." + name))
                return impName;
        }
        return name;
    }
}
