#!/bin/bash
# FastLED JavaScript/TypeScript Linting Script (Node.js + ESLint + TypeScript Type Checking - FAST!)

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Store project root directory for cache operations
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
COMPILER_DIR="$PROJECT_ROOT/src/platforms/wasm/compiler"

# Find a node_modules binary, preferring Unix name over .cmd (Windows)
# Usage: find_bin <dir> <name>  →  sets FOUND_BIN or returns 1
find_bin() {
    local dir="$1" name="$2"
    if [ -f "$dir/$name" ]; then
        FOUND_BIN="$dir/$name"
    elif [ -f "$dir/$name.cmd" ]; then
        FOUND_BIN="$dir/$name.cmd"
    else
        return 1
    fi
}

# Resolve eslint binary → sets ESLINT_BIN or returns 1
find_eslint() {
    find_bin "$PROJECT_ROOT/.cache/js-tools/node_modules/.bin" "eslint" && ESLINT_BIN="$FOUND_BIN"
}

# Resolve tsc binary → sets TSC_CMD or returns 1
find_tsc() {
    if find_bin "$COMPILER_DIR/node_modules/.bin" "tsc"; then
        TSC_CMD="$FOUND_BIN"
    elif find_bin "$PROJECT_ROOT/.cache/js-tools/node_modules/.bin" "tsc"; then
        TSC_CMD="$FOUND_BIN"
    elif command -v npx >/dev/null 2>&1; then
        TSC_CMD="npx tsc"
    else
        return 1
    fi
}

# Set up trap to invalidate cache on failure
trap 'if [ $? -ne 0 ]; then cd "$PROJECT_ROOT" && uv run python ci/js_lint_cache.py failure; fi' EXIT

echo -e "${BLUE}FAST FastLED TypeScript Linting (ESLint + TypeScript Type Checking - FAST!)${NC}"

# Check if ESLint is installed
if ! find_eslint; then
    echo -e "${RED}ERROR: ESLint not found. Run: uv run ci/setup-js-linting-fast.py${NC}"
    exit 1
fi

# Check if files need linting using fingerprint cache (from project root)
# Skip cache check if FASTLED_NO_FINGERPRINT is set
if [ "${FASTLED_NO_FINGERPRINT:-0}" = "1" ]; then
    echo -e "${BLUE}Skipping cache check (--no-fingerprint flag set)${NC}"
else
    echo -e "${BLUE}Checking if TypeScript files need linting...${NC}"
    cd "$PROJECT_ROOT"
    if uv run python ci/js_lint_cache.py check; then
        echo -e "${BLUE}TypeScript files changed - proceeding with linting${NC}"
    else
        echo -e "${GREEN}No changes detected - skipping TypeScript linting${NC}"
        exit 0
    fi
fi

# Find TypeScript files in WASM compiler (exclude node_modules, dist, vendor)
WASM_TS_FILES=$(find src/platforms/wasm/compiler -name "*.ts" -type f -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/vendor/*" -not -name "*.d.ts" 2>/dev/null)
# Find remaining JS files (audio worklet, etc.)
WASM_JS_FILES=$(find src/platforms/wasm/compiler -name "*.js" -type f -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/vendor/*" 2>/dev/null)
# Find TypeScript files in avr8js
AVR_TS_FILES=$(find ci/docker_utils/avr8js -name "*.ts" -type f -not -path "*/node_modules/*" 2>/dev/null)

if [ -z "$WASM_TS_FILES" ] && [ -z "$WASM_JS_FILES" ] && [ -z "$AVR_TS_FILES" ]; then
    echo -e "${YELLOW}WARNING: No TypeScript or JavaScript files found${NC}"
    exit 0
fi

if [ -n "$WASM_TS_FILES" ]; then
    echo -e "${BLUE}Found WASM TypeScript files:${NC}"
    echo "$WASM_TS_FILES" | sed 's/^/  /'
fi

if [ -n "$WASM_JS_FILES" ]; then
    echo -e "${BLUE}Found WASM JavaScript files:${NC}"
    echo "$WASM_JS_FILES" | sed 's/^/  /'
fi

if [ -n "$AVR_TS_FILES" ]; then
    echo -e "${BLUE}Found avr8js TypeScript files:${NC}"
    echo "$AVR_TS_FILES" | sed 's/^/  /'
fi

# Run ESLint using config from the compiler directory
echo -e "${BLUE}Running ESLint...${NC}"
cd .cache/js-tools

# Build the list of files/patterns to lint
LINT_TARGETS=()

# Add WASM TypeScript files
if [ -n "$WASM_TS_FILES" ]; then
    LINT_TARGETS+=("../../src/platforms/wasm/compiler/*.ts")
    LINT_TARGETS+=("../../src/platforms/wasm/compiler/modules/**/*.ts")
fi

# Add WASM JavaScript files (audio worklet, etc.)
if [ -n "$WASM_JS_FILES" ]; then
    LINT_TARGETS+=("../../src/platforms/wasm/compiler/modules/**/*.js")
fi

# Add avr8js TypeScript files
if [ -n "$AVR_TS_FILES" ]; then
    LINT_TARGETS+=("../../ci/docker_utils/avr8js/*.ts")
fi

# Copy eslintrc from compiler directory so ESLint can resolve the TS parser
# (ESLint resolves parser modules relative to the config file location)
cp "../../src/platforms/wasm/compiler/.eslintrc.cjs" ".eslintrc.cjs" 2>/dev/null || true

if "$ESLINT_BIN" --no-eslintrc --no-inline-config -c .eslintrc.cjs "${LINT_TARGETS[@]}"; then
    echo -e "${GREEN}ESLint completed successfully${NC}"
else
    echo -e "${RED}ERROR: ESLint failed${NC}"
    cd "$PROJECT_ROOT" && uv run python ci/js_lint_cache.py failure
    exit 1
fi

# Run TypeScript Type Checking
echo -e "${BLUE}Running TypeScript Type Checking...${NC}"
cd "$COMPILER_DIR"

if ! find_tsc; then
    echo -e "${YELLOW}TypeScript not found, skipping type checking${NC}"
    echo -e "${BLUE}To enable: cd src/platforms/wasm/compiler && npm install${NC}"
    echo -e "${GREEN}SUCCESS: Linting completed (type checking skipped)${NC}"
    cd "$PROJECT_ROOT"
    if [ "${FASTLED_NO_FINGERPRINT:-0}" != "1" ]; then
        uv run python ci/js_lint_cache.py success
    fi
    exit 0
fi

echo -e "${BLUE}Using TypeScript for type checking: $TSC_CMD${NC}"
TSC_OUTPUT=$($TSC_CMD --noEmit --project tsconfig.json 2>&1)
TSC_EXIT_CODE=$?

# Filter out known benign errors
FILTERED_OUTPUT=$(echo "$TSC_OUTPUT" | grep -v "node_modules/events/events.js" || true)

if [ -n "$FILTERED_OUTPUT" ]; then
    echo "$FILTERED_OUTPUT"
    if [ $TSC_EXIT_CODE -ne 0 ]; then
        echo -e "${RED}TypeScript type checking failed with errors${NC}"
        cd "$PROJECT_ROOT" && uv run python ci/js_lint_cache.py failure
        exit 1
    fi
fi
echo -e "${GREEN}TypeScript type checking completed successfully${NC}"

echo -e "${GREEN}SUCCESS: TypeScript linting and type checking completed successfully${NC}"

# Mark linting as successful in cache (from project root)
# Skip if FASTLED_NO_FINGERPRINT is set (no cache check was performed)
if [ "${FASTLED_NO_FINGERPRINT:-0}" != "1" ]; then
    cd "$PROJECT_ROOT"
    uv run python ci/js_lint_cache.py success
fi
