# =============================================================================
# CI Workflow — Continuous Integration
# =============================================================================
# Triggers on push and pull_request.
#
# Detection logic:
#   1. Python: if requirements.txt exists → install deps, lint, test.
#   2. Node/JS: if package.json exists → npm ci, lint, test, build.
#   3. Neither detected → print a message and exit 0 (never fail).
#
# Controlled by .ci/config.env:
#   ENABLE_CI   — master switch (default: true)
#   CI_STRICT   — if true, lint/test failures fail the workflow
#                  if false, failures are warnings only
#
# See docs/CI.md for full details.
# =============================================================================

name: CI

on:
  push:
  pull_request:

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      # -----------------------------------------------------------------------
      # Step 1: Checkout the code
      # -----------------------------------------------------------------------
      - name: Checkout
        uses: actions/checkout@v4

      # -----------------------------------------------------------------------
      # Step 2: Load configuration from .ci/config.env
      # -----------------------------------------------------------------------
      - name: Load config
        id: config
        run: |
          # Source config.env to get ENABLE_CI, CI_STRICT, etc.
          if [ -f .ci/config.env ]; then
            # Export all non-comment, non-empty lines
            set -a
            source .ci/config.env
            set +a
            echo "Config loaded from .ci/config.env"
          else
            echo "WARNING: .ci/config.env not found, using defaults"
            ENABLE_CI=true
            CI_STRICT=true
          fi

          # Pass values to subsequent steps via environment file
          echo "ENABLE_CI=${ENABLE_CI:-true}" >> "$GITHUB_ENV"
          echo "CI_STRICT=${CI_STRICT:-true}" >> "$GITHUB_ENV"

      # -----------------------------------------------------------------------
      # Step 3: Check master switch
      # -----------------------------------------------------------------------
      - name: Check if CI is enabled
        run: |
          if [ "$ENABLE_CI" != "true" ]; then
            echo "CI is disabled (ENABLE_CI=$ENABLE_CI). Exiting."
            exit 0
          fi

      # -----------------------------------------------------------------------
      # Step 4: Detect project type
      # -----------------------------------------------------------------------
      - name: Detect project type
        id: detect
        run: |
          HAS_PYTHON=false
          HAS_NODE=false

          if [ -f requirements.txt ] || [ -f setup.py ] || [ -f pyproject.toml ]; then
            HAS_PYTHON=true
            echo "Detected: Python project"
          fi

          if [ -f package.json ]; then
            HAS_NODE=true
            echo "Detected: Node.js project"
          fi

          if [ "$HAS_PYTHON" = "false" ] && [ "$HAS_NODE" = "false" ]; then
            echo "No Python or Node.js project detected. CI will skip gracefully."
          fi

          echo "HAS_PYTHON=${HAS_PYTHON}" >> "$GITHUB_ENV"
          echo "HAS_NODE=${HAS_NODE}" >> "$GITHUB_ENV"

      # -----------------------------------------------------------------------
      # Step 5: Python — Setup & Install
      # -----------------------------------------------------------------------
      - name: Set up Python
        if: env.HAS_PYTHON == 'true'
        uses: actions/setup-python@v5
        with:
          python-version: "3.x"

      - name: Install Python dependencies
        if: env.HAS_PYTHON == 'true'
        run: |
          python -m pip install --upgrade pip
          if [ -f requirements.txt ]; then
            pip install -r requirements.txt
          fi
          # Install optional dev tools (won't fail if not needed)
          pip install ruff black flake8 pytest 2>/dev/null || true

      # -----------------------------------------------------------------------
      # Step 6: Python — Lint
      # Runs ruff, then black --check, then flake8. Each is optional:
      # only runs if the tool is installed AND relevant config exists.
      # -----------------------------------------------------------------------
      - name: Python lint
        if: env.HAS_PYTHON == 'true'
        run: |
          EXIT_CODE=0

          # --- ruff ---
          if command -v ruff >/dev/null 2>&1; then
            echo ">>> ruff check ."
            ruff check . || EXIT_CODE=$?
          else
            echo "SKIP: ruff not installed"
          fi

          # --- black ---
          if command -v black >/dev/null 2>&1; then
            echo ">>> black --check ."
            black --check . || EXIT_CODE=$?
          else
            echo "SKIP: black not installed"
          fi

          # --- flake8 ---
          if command -v flake8 >/dev/null 2>&1; then
            echo ">>> flake8 ."
            flake8 . || EXIT_CODE=$?
          else
            echo "SKIP: flake8 not installed"
          fi

          if [ "$EXIT_CODE" -ne 0 ]; then
            if [ "$CI_STRICT" = "true" ]; then
              echo "ERROR: Lint failed (CI_STRICT=true)"
              exit 1
            else
              echo "WARNING: Lint issues found (CI_STRICT=false, continuing)"
            fi
          fi

      # -----------------------------------------------------------------------
      # Step 7: Python — Test
      # Runs pytest if a tests/ directory or pytest config is detected.
      # -----------------------------------------------------------------------
      - name: Python test
        if: env.HAS_PYTHON == 'true'
        run: |
          # Check if tests exist
          HAS_TESTS=false
          if [ -d tests ] || [ -d test ]; then
            HAS_TESTS=true
          fi
          # Check for pytest config in pyproject.toml or pytest.ini
          if [ -f pytest.ini ] || [ -f setup.cfg ]; then
            HAS_TESTS=true
          fi
          if [ -f pyproject.toml ] && grep -q '\[tool\.pytest' pyproject.toml 2>/dev/null; then
            HAS_TESTS=true
          fi

          if [ "$HAS_TESTS" = "true" ]; then
            echo ">>> pytest"
            if ! pytest; then
              if [ "$CI_STRICT" = "true" ]; then
                echo "ERROR: Tests failed (CI_STRICT=true)"
                exit 1
              else
                echo "WARNING: Tests failed (CI_STRICT=false, continuing)"
              fi
            fi
          else
            echo "SKIP: No tests detected (no tests/ dir or pytest config)"
          fi

      # -----------------------------------------------------------------------
      # Step 8: Node.js — Setup & Install
      # -----------------------------------------------------------------------
      - name: Set up Node.js
        if: env.HAS_NODE == 'true'
        uses: actions/setup-node@v4
        with:
          node-version: "lts/*"

      - name: Install Node dependencies
        if: env.HAS_NODE == 'true'
        run: npm ci

      # -----------------------------------------------------------------------
      # Step 9: Node.js — Lint (only if "lint" script exists in package.json)
      # -----------------------------------------------------------------------
      - name: Node lint
        if: env.HAS_NODE == 'true'
        run: |
          if grep -q '"lint"' package.json 2>/dev/null; then
            echo ">>> npm run lint"
            if ! npm run lint; then
              if [ "$CI_STRICT" = "true" ]; then
                echo "ERROR: Lint failed (CI_STRICT=true)"
                exit 1
              else
                echo "WARNING: Lint issues found (CI_STRICT=false, continuing)"
              fi
            fi
          else
            echo "SKIP: no 'lint' script in package.json"
          fi

      # -----------------------------------------------------------------------
      # Step 10: Node.js — Test (only if "test" script exists)
      # -----------------------------------------------------------------------
      - name: Node test
        if: env.HAS_NODE == 'true'
        run: |
          if grep -q '"test"' package.json 2>/dev/null; then
            echo ">>> npm test"
            if ! npm test; then
              if [ "$CI_STRICT" = "true" ]; then
                echo "ERROR: Tests failed (CI_STRICT=true)"
                exit 1
              else
                echo "WARNING: Tests failed (CI_STRICT=false, continuing)"
              fi
            fi
          else
            echo "SKIP: no 'test' script in package.json"
          fi

      # -----------------------------------------------------------------------
      # Step 11: Node.js — Build (only if "build" script exists)
      # -----------------------------------------------------------------------
      - name: Node build
        if: env.HAS_NODE == 'true'
        run: |
          if grep -q '"build"' package.json 2>/dev/null; then
            echo ">>> npm run build"
            npm run build
          else
            echo "SKIP: no 'build' script in package.json"
          fi

      # -----------------------------------------------------------------------
      # Step 12: Summary
      # -----------------------------------------------------------------------
      - name: CI Summary
        if: always()
        run: |
          echo "=============================="
          echo " CI Complete"
          echo " Python detected: $HAS_PYTHON"
          echo " Node detected:   $HAS_NODE"
          echo " Strict mode:     $CI_STRICT"
          echo "=============================="
