#!/usr/bin/env bash
#
# Pre-commit naming + style check for shopdb-flask.
# Enforces CONTRIBUTING.md rules:
#   1. No non-ASCII chars in source (em-dashes, smart quotes, arrows, emojis)
#   2. No banned shorthand identifiers (cfg, ctx, mgr, req, res, env, util, helper)
#      as standalone names (suffix usage like printers_bp, request_obj is allowed)
#   3. No snake_case DB column names in __tablename__ or db.Column attrs
#   4. No snake_case API params in frontend that should match DB column names
#
# Exits non-zero if any violation found.
# Skips: venv/, node_modules/, __pycache__/, frontend/dist/, migrations/versions/

set -e

REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo .)"
cd "$REPO_ROOT"

VIOLATIONS=0

EXCLUDES=(
    --exclude-dir=venv
    --exclude-dir=node_modules
    --exclude-dir=__pycache__
    --exclude-dir=dist
    --exclude-dir=.git
    --exclude-dir=versions
)

INCLUDES_CODE=(
    --include='*.py'
    --include='*.vue'
    --include='*.js'
    --include='*.ts'
)

INCLUDES_ALL=(
    --include='*.py'
    --include='*.vue'
    --include='*.js'
    --include='*.ts'
    --include='*.json'
    --include='*.md'
    --include='*.yaml'
    --include='*.yml'
)

echo "==> Checking for non-ASCII characters..."
NON_ASCII=$(grep -rPn '[^\x00-\x7F]' "${EXCLUDES[@]}" "${INCLUDES_CODE[@]}" . 2>/dev/null || true)
if [ -n "$NON_ASCII" ]; then
    echo "FAIL: non-ASCII characters found (em-dashes, smart quotes, arrows, emojis):"
    echo "$NON_ASCII"
    echo
    VIOLATIONS=$((VIOLATIONS + 1))
fi

echo "==> Checking for banned shorthand (standalone)..."
# Match the word as a standalone identifier: not preceded or followed by underscore/word char
# Word boundary in grep is \b but we want to exclude suffix usage like printers_bp
# So: match (^|[^a-zA-Z0-9_])(banned)([^a-zA-Z0-9_]|$)
for word in cfg ctx mgr req res; do
    HITS=$(grep -rPn "(^|[^a-zA-Z0-9_])${word}([^a-zA-Z0-9_]|\$)" "${EXCLUDES[@]}" --include='*.py' --include='*.vue' --include='*.js' --include='*.ts' . 2>/dev/null \
        | grep -vP "(^|[^a-zA-Z0-9_])(request_obj|response_obj)" \
        || true)
    if [ -n "$HITS" ]; then
        echo "FAIL: banned shorthand '$word' (standalone) found:"
        echo "$HITS"
        echo
        VIOLATIONS=$((VIOLATIONS + 1))
    fi
done

echo "==> Checking for snake_case DB tablenames..."
SNAKE_TABLES=$(grep -rPn "__tablename__\s*=\s*['\"][^'\"]*_" "${EXCLUDES[@]}" --include='*.py' . 2>/dev/null || true)
if [ -n "$SNAKE_TABLES" ]; then
    echo "FAIL: snake_case __tablename__ found (must be lowercase concatenated):"
    echo "$SNAKE_TABLES"
    echo
    VIOLATIONS=$((VIOLATIONS + 1))
fi

echo "==> Checking for snake_case DB column attrs..."
SNAKE_COLS=$(grep -rPn "^\s+[a-z]+_[a-z_]+\s*=\s*db\.Column" "${EXCLUDES[@]}" --include='*.py' . 2>/dev/null || true)
if [ -n "$SNAKE_COLS" ]; then
    echo "FAIL: snake_case db.Column attribute found (must match column name, no underscores):"
    echo "$SNAKE_COLS"
    echo
    VIOLATIONS=$((VIOLATIONS + 1))
fi

echo "==> Checking for snake_case ForeignKey targets..."
SNAKE_FK=$(grep -rPn "ForeignKey\(['\"][^'\"]*_[^'\"]*['\"]" "${EXCLUDES[@]}" --include='*.py' . 2>/dev/null || true)
if [ -n "$SNAKE_FK" ]; then
    echo "FAIL: snake_case ForeignKey target found:"
    echo "$SNAKE_FK"
    echo
    VIOLATIONS=$((VIOLATIONS + 1))
fi

echo "==> Checking for snake_case API params in frontend (DB-mirrored fields)..."
SNAKE_FE=$(grep -rPn "params\.(machine_id|location_id|vendor_id|type_id|business_unit_id|model_id|status_id|operating_system_id|asset_id|user_id|is_active|is_shopfloor)" "${EXCLUDES[@]}" --include='*.vue' --include='*.js' --include='*.ts' . 2>/dev/null || true)
if [ -n "$SNAKE_FE" ]; then
    echo "FAIL: snake_case API params in frontend (must match DB column names without underscores):"
    echo "$SNAKE_FE"
    echo
    VIOLATIONS=$((VIOLATIONS + 1))
fi

# ADR-013 Phase 4: a plugin frontend (plugins/<name>/frontend/) may import core
# via the @/ alias or its own tree (./, ../ within the plugin), never another
# plugin's tree and never an escaping ../../ into src. Keeps plugin frontends
# self-contained so a per-site build can drop one cleanly.
echo "==> Checking for cross-plugin / escaping imports in plugin frontends..."
if [ -d plugins ]; then
    PLUGIN_FE_IMPORTS=$(grep -rPn "(import|from)\s+['\"]([^'\"]*\.\./\.\./|[^'\"]*/plugins/)" \
        --include='*.vue' --include='*.js' plugins/*/frontend/ 2>/dev/null || true)
    if [ -n "$PLUGIN_FE_IMPORTS" ]; then
        echo "FAIL: plugin frontend imports must use the @/ alias for core, not"
        echo "      an escaping ../../ or another plugin's path:"
        echo "$PLUGIN_FE_IMPORTS"
        echo
        VIOLATIONS=$((VIOLATIONS + 1))
    fi
fi

if [ "$VIOLATIONS" -gt 0 ]; then
    echo "=================================================="
    echo "$VIOLATIONS naming/style violation(s) found."
    echo "See CONTRIBUTING.md for the full convention."
    echo "=================================================="
    exit 1
fi

echo "==> All naming/style checks passed."
exit 0
