#!/bin/bash
# AutoWorkflow Pre-Commit Gate Check
# Runs on: PreToolUse for Bash tool (only git commit commands)
# Purpose: BLOCK commits that violate workflow gates
#
# This hook implements the full pre_commit_gate from system/gates.md
# All 7 checks must pass or the commit is BLOCKED

set -e

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

# Project directory (use env var if set, otherwise current directory)
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"

# Source the logger
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/logger.sh" 2>/dev/null || true

# State directory
STATE_DIR="$PROJECT_DIR/.claude/.autoworkflow"
mkdir -p "$STATE_DIR"

# Track errors
ERRORS=0
WARNINGS=0

# Output formatting
print_header() {
    echo ""
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo -e "${BOLD}AUTOWORKFLOW: PRE-COMMIT GATE${NC}"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
}

print_check() {
    local num=$1
    local name=$2
    local status=$3
    local details=$4

    if [ "$status" = "pass" ]; then
        echo -e "[${num}/7] ${name}: ${GREEN}✅ PASS${NC} ${details}"
    elif [ "$status" = "fail" ]; then
        echo -e "[${num}/7] ${name}: ${RED}⛔ FAIL${NC}"
        echo -e "      └── ${details}"
    else
        echo -e "[${num}/7] ${name}: ${YELLOW}⚠ SKIP${NC} ${details}"
    fi
}

# Check 1: TypeScript errors
check_typescript() {
    if [ -f "package.json" ] && grep -q "typecheck\|tsc" package.json 2>/dev/null; then
        if npm run typecheck 2>&1 | grep -q "error"; then
            TS_ERRORS=$(npm run typecheck 2>&1 | grep -c "error" || echo "0")
            print_check "1" "TypeScript" "fail" "${TS_ERRORS} error(s) found"
            ERRORS=$((ERRORS + 1))
            return 1
        else
            print_check "1" "TypeScript" "pass" "No errors"
            return 0
        fi
    else
        print_check "1" "TypeScript" "skip" "(no typecheck script)"
        return 0
    fi
}

# Check 2: ESLint warnings
check_eslint() {
    if [ -f "package.json" ] && grep -q '"lint"' package.json 2>/dev/null; then
        LINT_OUTPUT=$(npm run lint 2>&1 || true)
        if echo "$LINT_OUTPUT" | grep -qE "error|warning"; then
            LINT_ERRORS=$(echo "$LINT_OUTPUT" | grep -c "error" || echo "0")
            LINT_WARNINGS=$(echo "$LINT_OUTPUT" | grep -c "warning" || echo "0")
            print_check "2" "ESLint" "fail" "${LINT_ERRORS} error(s), ${LINT_WARNINGS} warning(s)"
            ERRORS=$((ERRORS + 1))
            return 1
        else
            print_check "2" "ESLint" "pass" "No issues"
            return 0
        fi
    else
        print_check "2" "ESLint" "skip" "(no lint script)"
        return 0
    fi
}

# Check 3: TODO/FIXME in staged files
check_todos() {
    if git diff --cached --name-only 2>/dev/null | head -1 | grep -q .; then
        TODO_FILES=$(git diff --cached --name-only 2>/dev/null | xargs grep -l "TODO\|FIXME\|XXX\|HACK" 2>/dev/null || true)
        if [ -n "$TODO_FILES" ]; then
            TODO_COUNT=$(echo "$TODO_FILES" | wc -l | tr -d ' ')
            print_check "3" "TODO/FIXME" "fail" "Found in ${TODO_COUNT} file(s)"
            echo "$TODO_FILES" | while read -r file; do
                echo -e "      ${YELLOW}→${NC} $file"
            done
            ERRORS=$((ERRORS + 1))
            return 1
        fi
    fi
    print_check "3" "TODO/FIXME" "pass" "None in staged files"
    return 0
}

# Check 4: console.log in staged files
check_console_logs() {
    if git diff --cached --name-only 2>/dev/null | head -1 | grep -q .; then
        # Exclude test files
        LOG_FILES=$(git diff --cached --name-only 2>/dev/null | grep -v "\.test\.\|\.spec\.\|__tests__" | xargs grep -l "console\.log\|console\.debug\|console\.info" 2>/dev/null || true)
        if [ -n "$LOG_FILES" ]; then
            LOG_COUNT=$(echo "$LOG_FILES" | wc -l | tr -d ' ')
            print_check "4" "console.log" "fail" "Found in ${LOG_COUNT} file(s)"
            echo "$LOG_FILES" | while read -r file; do
                echo -e "      ${YELLOW}→${NC} $file"
            done
            ERRORS=$((ERRORS + 1))
            return 1
        fi
    fi
    print_check "4" "console.log" "pass" "None in staged files"
    return 0
}

# Check 5: UI Enforcement (orphan features)
check_ui_enforcement() {
    if [ -f "package.json" ] && grep -q '"audit:ui"' package.json 2>/dev/null; then
        AUDIT_OUTPUT=$(npm run audit:ui 2>&1 || true)
        if echo "$AUDIT_OUTPUT" | grep -qi "orphan\|missing ui\|no component"; then
            print_check "5" "UI Enforcement" "fail" "Orphan features detected"
            ERRORS=$((ERRORS + 1))
            return 1
        else
            print_check "5" "UI Enforcement" "pass" "No orphan features"
            return 0
        fi
    else
        print_check "5" "UI Enforcement" "skip" "(no audit:ui script)"
        return 0
    fi
}

# Check 6: Circular Dependencies
check_circular_deps() {
    if [ -f "package.json" ] && grep -q '"audit:cycles"' package.json 2>/dev/null; then
        CYCLE_OUTPUT=$(npm run audit:cycles 2>&1 || true)
        if echo "$CYCLE_OUTPUT" | grep -qi "circular\|cycle"; then
            print_check "6" "Circular Deps" "fail" "Cycles detected"
            ERRORS=$((ERRORS + 1))
            return 1
        else
            print_check "6" "Circular Deps" "pass" "No cycles"
            return 0
        fi
    else
        print_check "6" "Circular Deps" "skip" "(no audit:cycles script)"
        return 0
    fi
}

# Check 7: Commit message format (conventional commits)
check_commit_message() {
    # Get the commit message from the staged commit or COMMIT_EDITMSG
    local commit_msg=""

    if [ -f ".git/COMMIT_EDITMSG" ]; then
        commit_msg=$(head -1 .git/COMMIT_EDITMSG)
    fi

    if [ -n "$commit_msg" ]; then
        # Check conventional commit format: type(scope): description
        if echo "$commit_msg" | grep -qE "^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .+"; then
            print_check "7" "Commit Format" "pass" "Valid conventional commit"
            return 0
        else
            print_check "7" "Commit Format" "fail" "Must be: type(scope): description"
            echo -e "      ${YELLOW}→${NC} Got: $commit_msg"
            ERRORS=$((ERRORS + 1))
            return 1
        fi
    else
        print_check "7" "Commit Format" "skip" "(no message yet)"
        return 0
    fi
}

# Main execution
main() {
    aw_log_gate "pre_commit" "CHECKING" "7 checks"

    print_header

    echo "Checking requirements..."
    echo ""

    # Run all checks
    check_typescript || true
    check_eslint || true
    check_todos || true
    check_console_logs || true
    check_ui_enforcement || true
    check_circular_deps || true
    check_commit_message || true

    echo ""
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

    if [ $ERRORS -gt 0 ]; then
        echo -e "${RED}${BOLD}⛔ GATE BLOCKED${NC} - ${ERRORS} issue(s) must be fixed"
        echo ""
        echo "Fix the issues above before committing."
        echo "The commit has been BLOCKED."
        echo ""

        # Write block status to state file
        echo "BLOCKED" > "$STATE_DIR/gate-status"
        echo "$ERRORS" > "$STATE_DIR/gate-errors"

        aw_log_gate "pre_commit" "BLOCKED" "$ERRORS errors"

        # EXIT WITH ERROR TO BLOCK THE COMMIT
        exit 1
    else
        echo -e "${GREEN}${BOLD}✅ ALL GATES PASSED${NC}"
        echo ""
        echo "Ready to commit."
        echo ""

        # Write pass status to state file
        echo "PASSED" > "$STATE_DIR/gate-status"
        echo "0" > "$STATE_DIR/gate-errors"

        aw_log_gate "pre_commit" "PASSED" "7/7 checks"

        exit 0
    fi
}

# Only run if there are staged changes
if git diff --cached --quiet 2>/dev/null; then
    # No staged changes, skip all checks
    exit 0
fi

main
