name: Python CI

on:
  push:
    branches: [ "*" ]
  pull_request:
    branches: [ main ]
  workflow_dispatch:

permissions:
  contents: read

jobs:
  check-forbidden-folders:
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
    - uses: actions/checkout@v6

    - name: Check for forbidden folders in PR
      run: |
        echo "Checking for forbidden folders in pull request..."

        # Function to check for folder existence case-insensitively
        check_forbidden_folder() {
          local pattern="$1"
          local description="$2"

          # Use find with case-insensitive matching
          if find . -type d -ipath "*${pattern}*" -print -quit | grep -q .; then
            echo "❌ ERROR: Found forbidden folder matching '${pattern}'"
            echo "Description: ${description}"
            find . -type d -ipath "*${pattern}*" | sed 's/^/ Found: /'
            return 1
          else
            echo "✅ No forbidden folder found for pattern: ${pattern}"
            return 0
          fi
        }

        # Function to check if folder is empty (or doesn't exist)
        check_empty_folder() {
          local pattern="$1"
          local description="$2"

          # Find matching folders
          local folders=$(find . -type d -path "*${pattern}*" 2>/dev/null)

          if [ -z "$folders" ]; then
            echo "✅ Folder not found (acceptable): ${pattern}"
            return 0
          fi

          # Check if any found folder is not empty
          local has_content=0
          while IFS= read -r folder; do
            if [ -n "$(find "$folder" -mindepth 1 -print -quit)" ]; then
              echo "❌ ERROR: Folder should be empty: ${folder}"
              echo "Description: ${description}"
              find "$folder" -mindepth 1 -maxdepth 1 | sed 's/^/ Contains: /'
              has_content=1
            fi
          done <<< "$folders"

          if [ $has_content -eq 1 ]; then
            return 1
          else
            echo "✅ Folder exists and is empty: ${pattern}"
            return 0
          fi
        }

        # Check for forbidden folders
        ERROR=0

        check_forbidden_folder "pr_info" "Temporary PR working folder - should not be in PRs" || ERROR=1
        check_forbidden_folder "tests/mcp_tools_py_manual/sample_project" "Generated sample project for manual testing" || ERROR=1

        # Check for forbidden files
        if [ -f "tests/mcp_tools_py_manual/__init__.py" ]; then
            echo "❌ ERROR: Found forbidden file tests/mcp_tools_py_manual/__init__.py"
            echo "Description: Generated init file for manual testing - should not be committed"
            ERROR=1
        else
            echo "✅ No forbidden manual test init file found"
        fi

        if [ $ERROR -eq 1 ]; then
          echo ""
          echo "❌ PULL REQUEST BLOCKED: Forbidden folders/files detected!"
          echo "These should not be included in pull requests."
          echo "Please remove them and update your .gitignore if necessary."
          echo "Note: These are allowed in regular commits, just not in PRs."
          exit 1
        else
          echo ""
          echo "✅ All checks passed! No forbidden folders/files found."
        fi

  # Matrix approach: Each check runs as independent job with individual pass/fail status
  # fail-fast: false ensures all checks complete even if one fails
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        check:
          - {name: "black", cmd: "black --version && black --check src tests"}
          - {name: "isort", cmd: "isort --version && isort --check --profile=black --float-to-top src tests"}
          - {name: "pylint", cmd: "pylint --version && pylint -E ./src ./tests"}
          - {name: "pytest", cmd: "pytest --version && pytest tests"}
          - {name: "mypy", cmd: "mypy --version && mypy --strict src tests"}
    name: ${{ matrix.check.name }}
    steps:
      - uses: actions/checkout@v6

      - name: Install uv
        uses: astral-sh/setup-uv@v5

      - name: Set up Python 3.11
        uses: actions/setup-python@v5
        with:
          python-version: 3.11

      - name: Install dependencies
        run: uv pip install --system ".[dev]"

      - name: Environment info
        run: |
          uname -a
          python --version
          uv --version
          git --version

      - name: Run ${{ matrix.check.name }}
        run: ${{ matrix.check.cmd }}

  # Architecture and code quality checks (PR only)
  architecture:
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    strategy:
      fail-fast: false
      matrix:
        check:
          - {name: "import-linter", cmd: "lint-imports --help > /dev/null && lint-imports"}
          - {name: "tach", cmd: "tach --version && tach check"}
          - {name: "pycycle", cmd: "pycycle --version && pycycle --here"}
          - {name: "vulture", cmd: "vulture --version && vulture src tests vulture_whitelist.py --min-confidence 60"}
          - {name: "file-sizes", cmd: "echo 'File size check disabled - mcp-coder not available in CI' && exit 0"}
    name: ${{ matrix.check.name }}
    steps:
      - uses: actions/checkout@v6

      - name: Install uv
        uses: astral-sh/setup-uv@v5

      - name: Set up Python 3.11
        uses: actions/setup-python@v5
        with:
          python-version: 3.11

      - name: Install dependencies
        run: uv pip install --system ".[dev]"

      - name: Environment info
        run: |
          uname -a
          python --version
          uv --version
          git --version

      - name: Run ${{ matrix.check.name }}
        run: ${{ matrix.check.cmd }}
