#!/bin/bash
# Check BUILD.bazel dependency constraints
# This script enforces architectural boundaries in the codebase.
#
# Usage:
#   ./scripts/check_build_deps.sh           # Check all rules
#   ./scripts/check_build_deps.sh --ci      # CI mode (fail on any violation)
#   ./scripts/check_build_deps.sh --count   # Just count current violations (for tracking progress)
#   ./scripts/check_build_deps.sh --strict  # Same as --ci (strict enforcement)

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
cd "$REPO_ROOT"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

MODE="${1:-check}"
EXIT_CODE=0

# Cache for expensive bazel query results
LIBRARY_DEPS_CACHE=""
MAIN_DEPS_CACHE=""

# Get deps of library/ (cached)
get_library_deps() {
    if [ -z "$LIBRARY_DEPS_CACHE" ]; then
        LIBRARY_DEPS_CACHE=$(bazel query 'deps(//src/main/scala/net/eagle0/eagle/library/...)' 2>/dev/null || true)
    fi
    echo "$LIBRARY_DEPS_CACHE"
}

# Get deps of src/main (cached)
get_main_deps() {
    if [ -z "$MAIN_DEPS_CACHE" ]; then
        MAIN_DEPS_CACHE=$(bazel query 'deps(//src/main/...)' 2>/dev/null || true)
    fi
    echo "$MAIN_DEPS_CACHE"
}

# Rule 1: src/main should not depend on src/test
check_main_depends_on_test() {
    echo -e "${YELLOW}Checking: src/main should not depend on src/test...${NC}"

    violations=$(get_main_deps | grep "^//src/test/" || true)

    if [ -n "$violations" ]; then
        echo -e "${RED}VIOLATION: src/main depends on src/test:${NC}"
        echo "$violations"
        return 1
    else
        echo -e "${GREEN}✓ No violations${NC}"
        return 0
    fi
}

# Rule 2: library/ should not depend on Scala proto types
# C++/Go proto deps are allowed (they're build-time deps for map generation tools)
check_library_depends_on_scala_proto() {
    echo -e "${YELLOW}Checking: library/ should not depend on Scala proto types...${NC}"

    violations=$(get_library_deps | grep "^//src/main/protobuf/.*_scala_proto$" || true)
    if [ -z "$violations" ]; then
        count=0
    else
        count=$(echo "$violations" | grep -c "^//" || true)
    fi

    if [ "$count" -gt 0 ]; then
        echo -e "${RED}VIOLATION: Found $count Scala proto dependencies in library/:${NC}"
        echo "$violations"
        return 1
    else
        echo -e "${GREEN}✓ No Scala proto dependencies in library/${NC}"
        return 0
    fi
}

# Rule 3: library/ should not depend on proto_converters
# Proto conversions should happen at service boundaries, not in library code
check_library_depends_on_proto_converters() {
    echo -e "${YELLOW}Checking: library/ should not depend on proto_converters...${NC}"

    violations=$(get_library_deps | grep "^//src/main/scala/net/eagle0/eagle/model/proto_converters/" || true)

    if [ -n "$violations" ]; then
        count=$(echo "$violations" | wc -l | tr -d ' ')
        echo -e "${RED}VIOLATION: library/ depends on $count proto_converters targets:${NC}"
        echo "$violations"
        echo ""
        echo "Proto conversions should happen at service boundaries (ShardokInterfaceGrpcClient,"
        echo "EagleServiceImpl, etc.), not in library code."
        return 1
    else
        echo -e "${GREEN}✓ No proto_converters dependencies in library/${NC}"
        return 0
    fi
}

# Count proto deps for informational purposes
count_proto_deps() {
    echo -e "${YELLOW}=== Proto dependency counts ===${NC}"

    library_deps=$(get_library_deps)
    scala_proto_results=$(echo "$library_deps" | grep "^//src/main/protobuf/.*_scala_proto$" || true)
    if [ -z "$scala_proto_results" ]; then
        scala_proto_count=0
    else
        scala_proto_count=$(echo "$scala_proto_results" | wc -l | tr -d ' ')
    fi
    echo "library/ Scala proto deps: $scala_proto_count"

    # C++/Go proto deps are expected (map generation tools)
    all_proto_count=$(echo "$library_deps" | grep -c "^//src/main/protobuf/" || echo "0")
    echo "library/ all proto deps (includes C++/Go build tools): $all_proto_count"
}

echo "=== BUILD.bazel Dependency Check ==="
echo ""

case "$MODE" in
    --count)
        count_proto_deps
        ;;
    --ci|--strict)
        check_main_depends_on_test || EXIT_CODE=1
        check_library_depends_on_scala_proto || EXIT_CODE=1
        check_library_depends_on_proto_converters || EXIT_CODE=1
        ;;
    *)
        check_main_depends_on_test || EXIT_CODE=1
        check_library_depends_on_scala_proto || EXIT_CODE=1
        check_library_depends_on_proto_converters || EXIT_CODE=1
        echo ""
        count_proto_deps
        ;;
esac

echo ""
if [ $EXIT_CODE -eq 0 ]; then
    echo -e "${GREEN}=== All checks passed ===${NC}"
else
    echo -e "${RED}=== Some checks failed ===${NC}"
fi

exit $EXIT_CODE
