#!/bin/bash
# AIDA commit-msg hook - Validates commit message format
# Generated by AIDA scaffolding
# trace:TASK-0344 | ai:claude

COMMIT_MSG_FILE="$1"
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
FIRST_LINE=$(echo "$COMMIT_MSG" | head -n 1)

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

# Configuration - can be overridden in .aida/commit-config
STRICT_MODE="${AIDA_COMMIT_STRICT:-false}"
REQUIRE_REQ_FOR_FEAT="${AIDA_REQUIRE_REQ_FOR_FEAT:-true}"
REQUIRE_AI_TAG="${AIDA_REQUIRE_AI_TAG:-true}"

# Load project-specific config if exists
if [ -f ".aida/commit-config" ]; then
    source ".aida/commit-config"
fi

# Patterns
AI_TAG_PATTERN='^\[AI:[a-zA-Z]+(:(high|med|low))?\]'
CONVENTIONAL_PATTERN='^(\[AI:[a-zA-Z]+(:(high|med|low))?\] )?(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-zA-Z0-9_-]+\))?: .+'
REQ_ID_PATTERN='\([A-Z]+-[0-9]+\)$'
FEAT_FIX_PATTERN='^(\[AI:[a-zA-Z]+(:(high|med|low))?\] )?(feat|fix)'

ERRORS=()
WARNINGS=()

# Check for files with trace comments in this commit
STAGED_FILES=$(git diff --cached --name-only 2>/dev/null)
HAS_TRACE_FILES=false

# Files to exclude from trace detection (data files, not source code)
EXCLUDE_PATTERNS="requirements.yaml requirements.yaml.lock requirements.db .md"

for file in $STAGED_FILES; do
    # Skip excluded files
    skip=false
    for pattern in $EXCLUDE_PATTERNS; do
        case "$file" in
            *"$pattern"*)
                skip=true
                break
                ;;
        esac
    done
    [ "$skip" = true ] && continue

    if [ -f "$file" ]; then
        if grep -q "trace:[A-Z]*-[0-9]*" "$file" 2>/dev/null; then
            HAS_TRACE_FILES=true
            break
        fi
    fi
done

# Validation 1: Check conventional commit format
if ! echo "$FIRST_LINE" | grep -qE "$CONVENTIONAL_PATTERN"; then
    ERRORS+=("Commit message must follow conventional format: [AI:tool]? type(scope): description")
    ERRORS+=("  Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert")
    ERRORS+=("  Example: [AI:claude] feat(auth): add login validation (FR-0042)")
fi

# Validation 2: Check for requirement ID on feat/fix commits
if echo "$FIRST_LINE" | grep -qE "$FEAT_FIX_PATTERN"; then
    if ! echo "$FIRST_LINE" | grep -qE "$REQ_ID_PATTERN"; then
        if [ "$REQUIRE_REQ_FOR_FEAT" = "true" ]; then
            if [ "$STRICT_MODE" = "true" ]; then
                ERRORS+=("feat/fix commits must include requirement ID: (REQ-ID)")
                ERRORS+=("  Example: feat(auth): add login validation (FR-0042)")
            else
                WARNINGS+=("feat/fix commits should include requirement ID: (REQ-ID)")
                WARNINGS+=("  Example: feat(auth): add login validation (FR-0042)")
            fi
        fi
    fi
fi

# Validation 3: Check for AI attribution when trace comments exist
if [ "$HAS_TRACE_FILES" = true ] && [ "$REQUIRE_AI_TAG" = "true" ]; then
    if ! echo "$FIRST_LINE" | grep -qE "$AI_TAG_PATTERN"; then
        if [ "$STRICT_MODE" = "true" ]; then
            ERRORS+=("Commit includes AI-traced files but no [AI:tool] tag")
            ERRORS+=("  Format: [AI:claude] or [AI:claude:med] or [AI:claude:low]")
        else
            WARNINGS+=("Commit includes AI-traced files - consider adding [AI:tool] tag")
            WARNINGS+=("  Format: [AI:claude] or [AI:claude:med] or [AI:claude:low]")
        fi
    fi
fi

# Validation 4: Extract and suggest requirement references from staged files
if [ "$HAS_TRACE_FILES" = true ]; then
    SPEC_IDS=""
    for file in $STAGED_FILES; do
        skip=false
        for pattern in $EXCLUDE_PATTERNS; do
            case "$file" in
                *"$pattern"*)
                    skip=true
                    break
                    ;;
            esac
        done
        [ "$skip" = true ] && continue

        if [ -f "$file" ]; then
            FILE_SPECS=$(grep -oE "trace:[A-Z]+-[0-9]+" "$file" 2>/dev/null | sed 's/trace://' | sort -u)
            if [ -n "$FILE_SPECS" ]; then
                SPEC_IDS="$SPEC_IDS $FILE_SPECS"
            fi
        fi
    done
    SPEC_IDS=$(echo "$SPEC_IDS" | tr ' ' '\n' | sort -u | tr '\n' ' ' | xargs)

    if [ -n "$SPEC_IDS" ]; then
        # Check if commit message references at least one of these specs
        FOUND_REF=false
        for spec in $SPEC_IDS; do
            if echo "$COMMIT_MSG" | grep -q "$spec"; then
                FOUND_REF=true
                break
            fi
        done

        if [ "$FOUND_REF" = false ]; then
            WARNINGS+=("Staged files trace to: $SPEC_IDS")
            WARNINGS+=("  Consider including one in your commit message")
        fi
    fi
fi

# Output results
if [ ${#WARNINGS[@]} -gt 0 ]; then
    echo -e "${YELLOW}⚠ Warnings:${NC}"
    for warning in "${WARNINGS[@]}"; do
        echo -e "${YELLOW}  $warning${NC}"
    done
    echo ""
fi

if [ ${#ERRORS[@]} -gt 0 ]; then
    echo -e "${RED}✗ Commit message validation failed:${NC}"
    for error in "${ERRORS[@]}"; do
        echo -e "${RED}  $error${NC}"
    done
    echo ""
    echo -e "${YELLOW}Your message: ${NC}$FIRST_LINE"
    echo ""

    if [ "$STRICT_MODE" = "true" ]; then
        echo -e "${RED}Commit rejected (strict mode). Fix the message and try again.${NC}"
        echo -e "${YELLOW}To bypass: git commit --no-verify${NC}"
        exit 1
    else
        echo -e "${YELLOW}Commit allowed (permissive mode). Consider fixing for consistency.${NC}"
        echo -e "${YELLOW}Enable strict mode: export AIDA_COMMIT_STRICT=true${NC}"
    fi
fi

# Success
if [ ${#ERRORS[@]} -eq 0 ] && [ ${#WARNINGS[@]} -eq 0 ]; then
    echo -e "${GREEN}✓ Commit message format valid${NC}"
fi

exit 0
