name: Continuous Integration

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Test on Python ${{ matrix.python-version }}
    runs-on: ubuntu-latest

    strategy:
      matrix:
        python-version: ["3.12", "3.13", "3.14"]
        experimental: [false]
        include:
          - python-version: "3.15-dev"
            experimental: true

    continue-on-error: ${{ matrix.experimental }}

    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 0  # Required for hatch-vcs version detection

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}

      - name: Cache tool directories
        uses: actions/cache@v5
        with:
          path: |
            .pytest_cache
            .mypy_cache
            .ruff_cache
          key: >-
            tools-${{ runner.os }}-py${{ matrix.python-version }}-
            ${{ hashFiles('src/**/*.py', 'tests/**/*.py') }}
          restore-keys: |
            tools-${{ runner.os }}-py${{ matrix.python-version }}-
            tools-${{ runner.os }}-

      - name: Install uv
        uses: astral-sh/setup-uv@v7
        with:
          enable-cache: true
          cache-dependency-glob: "pyproject.toml"

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

      # NOTE: Format checking is handled by pre-commit job (with black 24.10)
      # Removed redundant format check here to avoid version conflicts
      # between ruff-format and black

      - name: Run ruff lint
        run: ruff check .

      - name: Run mypy
        run: mypy src
        continue-on-error: ${{ matrix.python-version >= '3.12' }}

      - name: Run ty (Astral type checker - validation mode)
        run: ty check src
        continue-on-error: true
        # Non-blocking during validation period
        # Compare results with mypy before making blocking

      - name: Run tests with coverage
        run: |
          pytest -n 2 --cov --cov-report=xml --cov-report=term \
            --junitxml=junit-py${{ matrix.python-version }}.xml

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v6
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: ./coverage.xml
          flags: unittests
          name: codecov-${{ matrix.python-version }}
          fail_ci_if_error: false
          verbose: true

      - name: Upload test results to Codecov
        if: always()
        uses: codecov/codecov-action@v6
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: junit-py${{ matrix.python-version }}.xml
          report_type: test_results
          fail_ci_if_error: false
          verbose: true

  tox:
    name: Tox tests with UV (${{ matrix.tox-env }})
    runs-on: ubuntu-latest

    strategy:
      fail-fast: true  # Stop all jobs if one fails
      matrix:
        tox-env:
          # Critical checks first (Tier 1)
          - ruff-check
          - black
          - flake8
          # Type checking and linting (Tier 2)
          - mypy
          - isort
          - interrogate
          # Tests (Tier 3)
          - py312
          - py313
          - py314
          # Coverage (Tier 4)
          - coverage
          # Additional quality checks
          - licenses
          - codespell
          - pymarkdown
          - mdformat
          - pyroma
          - pyproject-fmt
          - validate-pyproject
          - validate-task-docs
          - tox-ini-fmt
          - yamllint
          - deptry
          - unimport
          - pydocstyle
          - vulture
          - blocklint
          - absolufy-imports
          - autoflake
          - pyupgrade
          - docformatter
          - autopep8
          - doc8
          - rstcheck
          - gitlint
        experimental: [false]
        include:
          - tox-env: py315
            experimental: true
          - tox-env: ty
            experimental: true
            # Non-blocking during validation period
          - tox-env: refurb
            experimental: true
            # Non-blocking during adoption phase - provides modernization suggestions
          - tox-env: doctest
            experimental: true
            # Non-blocking during initial rollout - existing doctest failures need fixing

    continue-on-error: ${{ matrix.experimental }}

    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 0  # Required for hatch-vcs version detection

      - name: Cache tox environments
        uses: actions/cache@v5
        with:
          path: .tox
          key: >-
            tox-${{ runner.os }}-${{ matrix.tox-env }}-
            ${{ hashFiles('pyproject.toml', 'tox.ini', 'uv.lock') }}
          restore-keys: |
            tox-${{ runner.os }}-${{ matrix.tox-env }}-
            tox-${{ runner.os }}-

      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          python-version: "3.12"

      - name: Install uv
        uses: astral-sh/setup-uv@v7
        with:
          enable-cache: true
          cache-dependency-glob: "pyproject.toml"

      - name: Install tox and tox-uv
        run: |
          uv pip install tox tox-uv --system

      - name: Run tox
        run: tox -e ${{ matrix.tox-env }}

      - name: Upload test results to Codecov
        if: always()
        uses: codecov/codecov-action@v6
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: junit*.xml
          report_type: test_results
          fail_ci_if_error: false
          verbose: true

  pre-commit:
    name: Pre-commit checks
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v6
        with:
          fetch-depth: 0  # Required for hatch-vcs version detection

      - name: Cache pre-commit hooks
        uses: actions/cache@v5
        with:
          path: ~/.cache/pre-commit
          key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}
          restore-keys: |
            pre-commit-${{ runner.os }}-

      - name: Cache Python dependencies
        uses: actions/cache@v5
        with:
          path: ~/.cache/pip
          key: pip-${{ runner.os }}-${{ hashFiles('pyproject.toml', 'uv.lock') }}
          restore-keys: |
            pip-${{ runner.os }}-

      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          python-version: "3.12"

      - name: Install uv
        uses: astral-sh/setup-uv@v7
        with:
          enable-cache: true
          cache-dependency-glob: "pyproject.toml"

      - name: Install pre-commit dependencies
        run: |
          uv pip install --system \
            docformatter==1.7.7 \
            pyroma \
            pyproject-fmt \
            deptry \
            pydocstyle \
            refurb \
            safety

      - name: Run pre-commit with UV
        uses: pre-commit/action@v3.0.1
        env:
          UV_SYSTEM_PYTHON: "1"
          # Skip check-jsonschema to run separately (non-blocking)
          SKIP: check-jsonschema

      - name: Run check-jsonschema (non-blocking)
        run: |
          uv pip install check-jsonschema --system
          pre-commit run check-jsonschema --all-files
        continue-on-error: true  # Don't block CI on network issues
        env:
          UV_SYSTEM_PYTHON: "1"
