#!/usr/bin/env bash
# lint-package-css.sh — Enforce extension CSS prefix convention
#
# Rule: The FIRST class selector in every rule must start with .ext-{slug}.
# Subsequent classes in compound/descendant selectors are allowed (they're
# scoped under the extension's namespace). Kernel .sw-* classes are always
# allowed. CodeMirror .cm-* classes are allowed as descendants.
#
# Exemptions: :root, @keyframes blocks, @font-face blocks, @media/@supports
# wrappers, CSS comments.
#
# Usage: bash scripts/lint-package-css.sh [packages-dir]
# Exit 0 = all clean, Exit 1 = violations found.

set -euo pipefail
PKG_DIR="${1:-packages}"
VIOLATIONS=0

for css in "$PKG_DIR"/*/css/main.css; do
  [ -f "$css" ] || continue

  # Derive slug from directory: {pkg_dir}/{slug}/css/main.css
  slug="$(basename "$(dirname "$(dirname "$css")")")"
  prefix="ext-${slug}"

  in_keyframes=0
  in_fontface=0
  in_comment=0
  brace_depth=0
  lineno=0

  while IFS= read -r line; do
    lineno=$((lineno + 1))

    # Track block comments
    if (( in_comment )); then
      [[ "$line" == *"*/"* ]] && in_comment=0
      continue
    fi
    if [[ "$line" == *"/*"* ]] && [[ "$line" != *"*/"* ]]; then
      in_comment=1
      continue
    fi

    # Skip single-line comments
    trimmed="${line#"${line%%[![:space:]]*}"}"
    [[ "$trimmed" == "" ]] && continue
    [[ "$trimmed" == /\** ]] && continue

    # Track @keyframes blocks
    if [[ "$trimmed" =~ ^@keyframes ]]; then
      in_keyframes=1
      continue
    fi
    if (( in_keyframes )); then
      [[ "$trimmed" == "}" ]] && in_keyframes=0
      continue
    fi

    # Skip @font-face
    if [[ "$trimmed" =~ ^@font-face ]]; then
      in_fontface=1
      continue
    fi
    if (( in_fontface )); then
      [[ "$trimmed" == *"}"* ]] && in_fontface=0
      continue
    fi

    # Skip @-rule wrappers
    [[ "$trimmed" =~ ^@ ]] && continue

    # Skip :root selectors
    [[ "$trimmed" =~ ^:root ]] && continue

    # Skip closing braces
    [[ "$trimmed" == "}" ]] && continue

    # Skip property declarations (contain : but not {)
    if [[ "$trimmed" == *":"* ]] && [[ "$trimmed" != *"{"* ]]; then
      continue
    fi

    # Selector line — check if it contains a class
    if [[ "$trimmed" == *"."* ]]; then
      # Split comma-separated selectors and check each one
      # We process the whole line as potentially multiple selectors
      IFS=',' read -ra selectors <<< "$trimmed"
      for sel in "${selectors[@]}"; do
        # Trim whitespace
        sel="${sel#"${sel%%[![:space:]]*}"}"
        sel="${sel%"${sel##*[![:space:]]}"}"

        # Remove trailing { if present
        sel="${sel%\{}"
        sel="${sel%"${sel##*[![:space:]]}"}"

        # Skip if empty
        [[ -z "$sel" ]] && continue

        # Find the FIRST class selector in this selector
        if [[ "$sel" =~ \.([a-zA-Z_][a-zA-Z0-9_-]*) ]]; then
          first_cls="${BASH_REMATCH[1]}"

          # Allow kernel .sw-* as first class
          [[ "$first_cls" == sw-* ]] && continue

          # Allow [data-ext=...] scoped selectors
          [[ "$sel" =~ ^\[data-ext ]] && continue

          # Must start with ext-{slug}
          if [[ "$first_cls" != ${prefix}* ]]; then
            echo "VIOLATION: $css:$lineno — .${first_cls} (expected .${prefix}-*)"
            VIOLATIONS=$((VIOLATIONS + 1))
          fi
        fi
      done
    fi
  done < "$css"
done

if (( VIOLATIONS > 0 )); then
  echo ""
  echo "Found $VIOLATIONS violation(s). First class selector in each rule must start with .ext-{slug}-"
  exit 1
else
  echo "All package CSS files pass prefix enforcement."
  exit 0
fi
