#!/usr/bin/env bash
# Conventional Commits linter for git commit-msg hook
# https://www.conventionalcommits.org/

set -e

COMMIT_MSG_FILE="$1"
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")

# Skip merge commits
if echo "$COMMIT_MSG" | grep -qE "^Merge "; then
    exit 0
fi

# Skip revert commits
if echo "$COMMIT_MSG" | grep -qE "^Revert "; then
    exit 0
fi

# Conventional Commits pattern
# type(scope)?: subject
# NOTE: Breaking changes (!) are NOT allowed - major releases are done manually
PATTERN="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .+"

FIRST_LINE=$(echo "$COMMIT_MSG" | head -n1)

if ! echo "$FIRST_LINE" | grep -qE "$PATTERN"; then
    echo ""
    echo "ERROR: Commit message does not follow Conventional Commits format."
    echo ""
    echo "Expected format: <type>[optional scope]: <description>"
    echo ""
    echo "Allowed types:"
    echo "  feat:     A new feature"
    echo "  fix:      A bug fix"
    echo "  docs:     Documentation only changes"
    echo "  style:    Changes that do not affect code meaning (formatting)"
    echo "  refactor: Code change that neither fixes a bug nor adds a feature"
    echo "  perf:     A code change that improves performance"
    echo "  test:     Adding missing tests or correcting existing tests"
    echo "  build:    Changes that affect the build system or dependencies"
    echo "  ci:       Changes to CI configuration files and scripts"
    echo "  chore:    Other changes that don't modify src or test files"
    echo "  revert:   Reverts a previous commit"
    echo ""
    echo "Examples:"
    echo "  feat: add user authentication"
    echo "  fix(parser): handle empty input"
    echo "  docs: update README with examples"
    echo ""
    echo "NOTE: Breaking changes (feat!, fix!, etc.) are NOT allowed."
    echo "      Major version releases are done manually."
    echo ""
    echo "Your commit message:"
    echo "  $FIRST_LINE"
    echo ""
    exit 1
fi

# Check for breaking change indicator (!) in header
if echo "$FIRST_LINE" | grep -qE "^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?\!:"; then
    echo ""
    echo "ERROR: Breaking changes (!) are not allowed in commit messages."
    echo ""
    echo "Major version releases must be done manually."
    echo "Use 'feat:' instead of 'feat!:' for new features."
    echo ""
    echo "Your commit message:"
    echo "  $FIRST_LINE"
    echo ""
    exit 1
fi

# Check for BREAKING CHANGE footer
if echo "$COMMIT_MSG" | grep -qiE "^BREAKING[ -]CHANGE:"; then
    echo ""
    echo "ERROR: BREAKING CHANGE footer is not allowed."
    echo ""
    echo "Major version releases must be done manually."
    echo ""
    exit 1
fi

# Check header length
HEADER_LENGTH=${#FIRST_LINE}
if [ "$HEADER_LENGTH" -gt 100 ]; then
    echo ""
    echo "ERROR: Commit header exceeds 100 characters ($HEADER_LENGTH chars)."
    echo ""
    echo "Your header: $FIRST_LINE"
    echo ""
    exit 1
fi

exit 0
