package click.kamil.springstatemachineexporter.analysis.resolver;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

class ConstraintClausesTest {

    @Test
    void splitAndClausesSplitsTopLevelAnd() {
        assertThat(ConstraintClauses.splitAndClauses(
                "\"PAY\".equalsIgnoreCase(message) && message == \"PAY\""))
                .containsExactly(
                        "\"PAY\".equalsIgnoreCase(message)",
                        "message == \"PAY\"");
    }

    @Test
    void splitAndClausesKeepsNestedAndInsideParens() {
        assertThat(ConstraintClauses.splitAndClauses(
                "(a == 1 && b == 2) && c == 3"))
                .containsExactly("(a == 1 && b == 2)", "c == 3");
    }

    @Test
    void primaryIdentExtractsEqualsIgnoreCaseArgument() {
        assertThat(ConstraintClauses.primaryIdent("\"PAY\".equalsIgnoreCase(message)"))
                .isEqualTo("message");
    }

    @Test
    void primaryIdentExtractsEqLeftOperand() {
        assertThat(ConstraintClauses.primaryIdent("message == \"PAY\""))
                .isEqualTo("message");
    }

    @Test
    void primaryIdentExtractsReceiverOfEqualsCall() {
        assertThat(ConstraintClauses.primaryIdent("machineType.equals(\"ORDER\")"))
                .isEqualTo("machineType");
    }

    @Test
    void equalityVariablesUnionsPrimaryIdentsAcrossClauses() {
        assertThat(ConstraintClauses.equalityVariables(
                "\"ORDER\".equalsIgnoreCase(machineType) && message == \"PAY\""))
                .containsExactly("machineType", "message");
    }

    @Test
    void primaryIdentExtractsObjectsEqualsIdent() {
        assertThat(ConstraintClauses.primaryIdent("Objects.equals(\"PAY\", message)"))
                .isEqualTo("message");
        assertThat(ConstraintClauses.primaryIdent("Objects.equals(machineType, \"ORDER\")"))
                .isEqualTo("machineType");
        assertThat(ConstraintClauses.primaryIdent("java.util.Objects.equalsIgnoreCase(\"ORDER\", type)"))
                .isEqualTo("type");
    }

    @Test
    void carrierLiteralsIncludeObjectsEqualsForms() {
        assertThat(ConstraintClauses.carrierLiterals(
                "Objects.equals(\"PAY\", message) && Objects.equals(machineType, \"ORDER\")"))
                .containsExactly("PAY");
        assertThat(ConstraintClauses.carrierLiterals("message == \"SHIP\""))
                .containsExactly("SHIP");
    }

    @Test
    void carrierLiteralsFromPathBindingsSkipsPlaceholders() {
        assertThat(ConstraintClauses.carrierLiteralsFromPathBindings(
                java.util.Map.of("message", "PAY", "id", "42")))
                .containsExactly("PAY");
        assertThat(ConstraintClauses.carrierLiteralsFromPathBindings(
                java.util.Map.of("message", "message", "event", "{event}")))
                .isEmpty();
    }

    @Test
    void boundCarrierLiteralsPrefersSingleConstraintLiteral() {
        assertThat(ConstraintClauses.boundCarrierLiterals(
                "message == \"PAY\"",
                java.util.Map.of("message", "SHIP")))
                .containsExactly("PAY");
        assertThat(ConstraintClauses.boundCarrierLiterals(
                null,
                java.util.Map.of("message", "SHIP")))
                .containsExactly("SHIP");
    }
}
