# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Latest commit

env:
  CACHE_VERSION: 2
  DEFAULT_PYTHON: "3.14"
  PRE_COMMIT_HOME: ~/.cache/pre-commit
  VENV: venv

on:
  schedule:
    - cron: "2 4 * * 0" # weekly
  workflow_dispatch:
  push:
# pull_request:

jobs:
  # Determine cache key once
  cache:
    runs-on: ubuntu-latest
    name: Cache identify
    outputs:
      cache-key: ${{ steps.set-key.outputs.cache-key }}
      python-version: ${{ steps.python.outputs.python-version }}  # Ensure all runners use THIS minor version
    steps:
      - name: Check out committed code
        uses: actions/checkout@v6
      - name: Set up Python and determine minor version for ${{ env.DEFAULT_PYTHON }}
        id: python
        uses: actions/setup-python@v6
        with:
          python-version: ${{ env.DEFAULT_PYTHON }}
      - name: Fetch HA pyproject
        id: core-version
        run: wget -O ha_pyproject.toml "https://raw.githubusercontent.com/home-assistant/core/refs/heads/dev/pyproject.toml"
      - name: Compute cache key
        id: set-key
        run: echo "cache-key=${{ runner.os }}-${{ env.CACHE_VERSION }}-${{ hashFiles('pyproject.toml', 'requirements_test.txt', '.pre-commit-config.yaml') }}" >> "$GITHUB_OUTPUT"

  # Prepare default python version environment
  prepare:
    runs-on: ubuntu-latest
    needs: cache
    name: Prepare
    steps:
      - name: Prepare code checkout and python/pre-commit setup
        id: cache-reuse
        uses: plugwise/gh-actions/prepare-python-and-code@v1
        with:
          cache-key: ${{ needs.cache.outputs.cache-key }}
          fail-on-miss: false  # First time create cache (if not already exists)
          python-version: ${{ needs.cache.outputs.python-version }}
          venv-dir: ${{ env.VENV }}
          precommit-home: ${{ env.PRE_COMMIT_HOME }}

  ruff:
    runs-on: ubuntu-latest
    name: Ruff check and force
    needs:
      - cache
      - prepare
    steps:
      - name: Check out committed code
        uses: actions/checkout@v6
        with:
          persist-credentials: false
      - name: Restore cached environment
        id: cache-reuse
        uses: plugwise/gh-actions/restore-venv@v1
        with:
          cache-key: ${{ needs.cache.outputs.cache-key }}
          python-version: ${{ needs.cache.outputs.python-version }}
          venv-dir: ${{ env.VENV }}
          precommit-home: ${{ env.PRE_COMMIT_HOME }}
      - name: Ruff (with fix)
        run: |
          . venv-${{ needs.cache.outputs.python-version }}/bin/activate
          ruff check plugwise/ tests/
      - name: If needed, commit ruff changes to the pull request
        if: failure()
        run: |
          . venv-${{ needs.cache.outputs.python-version }}/bin/activate
          ruff format plugwise/ tests/
          git config --global user.name 'autoruff'
          git config --global user.email 'plugwise@users.noreply.github.com'
          git remote set-url origin https://x-access-token:${{ secrets.PAT_CT }}@github.com/$GITHUB_REPOSITORY
          git checkout $GITHUB_HEAD_REF
          git commit -am "fixup: ${GITHUB_REF##*/} Python code fixed using ruff"
          git push origin ${GITHUB_REF##*/}

  commitcheck:
    runs-on: ubuntu-latest
    name: Check commit
    needs:
      - cache
      - prepare
      - ruff
      - shellcheck
      - dependencies_check
    steps:
      - name: Check out committed code
        uses: actions/checkout@v6
      - name: Restore cached environment
        id: cache-reuse
        uses: plugwise/gh-actions/restore-venv@v1
        with:
          cache-key: ${{ needs.cache.outputs.cache-key }}
          python-version: ${{ needs.cache.outputs.python-version }}
          venv-dir: ${{ env.VENV }}
          precommit-home: ${{ env.PRE_COMMIT_HOME }}
      - name: Verify commit
        run: |
          . venv-${{ needs.cache.outputs.python-version }}/bin/activate
          pre-commit run --show-diff-on-failure --color=always --all-files --hook-stage manual pylint
      - name: Biome lint
        run: |
          . venv-${{ needs.cache.outputs.python-version }}/bin/activate
          mkdir -p ./tmp && curl -sL "https://github.com/biomejs/biome/releases/latest/download/biome-linux-x64" -o ./tmp/biome && chmod +x ./tmp/biome
          pre-commit run --show-diff-on-failure --color=always --all-files --hook-stage manual biome
      - name: Lint markdown files
        run: |
          . venv-${{ needs.cache.outputs.python-version }}/bin/activate
          pre-commit run --show-diff-on-failure --color=always --all-files --hook-stage manual markdownlint

  pytest:
    runs-on: ubuntu-latest
    name: Run pytest using Python ${{ matrix.python-version }}
    needs:
      - cache
      - prepare
      - commitcheck
    strategy:
      matrix:
        python-version: ["3.14", "3.13"]
    steps:
      - name: Check out committed code
        uses: actions/checkout@v6
      - name: Set up Python ${{ matrix.python-version }}
        id: python
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Restore cached environment
        id: cache-reuse
        uses: plugwise/gh-actions/restore-venv@v1
        with:
          fail-on-miss: false  # First time create cache (if not already exists)
          cache-key: ${{ needs.cache.outputs.cache-key }}
          python-version: ${{ steps.python.outputs.python-version }}  # Force to installed python minor
          venv-dir: ${{ env.VENV }}
          precommit-home: ${{ env.PRE_COMMIT_HOME }}
      - name: Run all tests
        run: |
          . venv-${{ steps.python.outputs.python-version }}/bin/activate
          pytest --log-level info tests/*.py --cov='.'
      - name: Upload coverage artifact
        uses: actions/upload-artifact@v5
        with:
          name: coverage-${{ steps.python.outputs.python-version }}
          path: .coverage
          if-no-files-found: error
          include-hidden-files: true

  mypy:
    runs-on: ubuntu-latest
    name: Run mypy
    needs:
      - cache
      - prepare
      - pytest
    steps:
      - name: Check out committed code
        uses: actions/checkout@v6
        with:
          persist-credentials: false
      - name: Restore cached environment
        id: cache-reuse
        uses: plugwise/gh-actions/restore-venv@v1
        with:
          cache-key: ${{ needs.cache.outputs.cache-key }}
          python-version: ${{ needs.cache.outputs.python-version }}
          venv-dir: ${{ env.VENV }}
          precommit-home: ${{ env.PRE_COMMIT_HOME }}
      - name: Run mypy
        run: |
          . venv-${{ needs.cache.outputs.python-version }}/bin/activate
          pip list | grep -i mypy
          mypy plugwise/

  # Check shellscripts
  shellcheck:
    name: Shellcheck
    runs-on: ubuntu-latest
    steps:
      - name: Check out committed code
        uses: actions/checkout@v6
      - name: Run ShellCheck
        uses: ludeeus/action-shellcheck@master

  # Check for missing python dependencies
  dependencies_check:
    runs-on: ubuntu-latest
    name: Dependency
    steps:
      - name: Check out committed code
        uses: actions/checkout@v6
      - name: Run dependency checker
        run: scripts/dependencies_check.sh debug

  coverage:
    name: Process test coverage
    runs-on: ubuntu-latest
    needs:
      - cache
      - prepare
      - pytest
      - mypy
    steps:
      - name: Check out committed code
        uses: actions/checkout@v6
      - name: Restore cached environment
        id: cache-reuse
        uses: plugwise/gh-actions/restore-venv@v1
        with:
          cache-key: ${{ needs.cache.outputs.cache-key }}
          python-version: ${{ needs.cache.outputs.python-version }}
          venv-dir: ${{ env.VENV }}
          precommit-home: ${{ env.PRE_COMMIT_HOME }}
      - name: Download all coverage artifacts
        uses: actions/download-artifact@v6
        with:
          pattern: coverage-*
          merge-multiple: true
          path: ${{ github.workspace }}/artifacts
      - name: Combine coverage results
        run: |
          . venv-${{ needs.cache.outputs.python-version }}/bin/activate
          coverage combine artifacts/.coverage*
          coverage report --fail-under=94
          coverage xml
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v5
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

  test-publishing:
    name: Build and publish Python 🐍 distributions 📦 to TestPyPI
    runs-on: ubuntu-latest
    environment: testpypi
    permissions:
      contents: read     # Required by actions/checkout
      id-token: write    # Needed for OIDC-based Trusted Publishing
    needs:
      - cache
      - prepare
      - coverage
      - mypy
    steps:
      - name: Check out committed code
        uses: actions/checkout@v6
      - name: Prepare uv
        run: |
          pip install uv
          uv venv --seed venv
          . venv/bin/activate
          uv pip install toml
      - name: Check for existing package on TestPyPI
        id: check_package
        run: |
          . venv/bin/activate
          PACKAGE_VERSION=$(python -c "import toml; print(toml.load('pyproject.toml')['project']['version'])")
          PACKAGE_NAME=$(python -c "import toml; print(toml.load('pyproject.toml')['project']['name'])")
          echo "Checking for package: $PACKAGE_NAME==$PACKAGE_VERSION"

          if curl -s "https://test.pypi.org/pypi/$PACKAGE_NAME/json" | jq -r '.releases | keys[]' | grep -q "^$PACKAGE_VERSION$"; then
            echo "Package version already exists. Skipping upload."
            echo "should_publish=false" >> $GITHUB_OUTPUT
          else
            echo "Package version does not exist. Proceeding with upload."
            echo "should_publish=true" >> $GITHUB_OUTPUT
          fi
      - name: Build
        if: steps.check_package.outputs.should_publish == 'true'
        run: |
          . venv/bin/activate
          uv build
      - name: Publish distribution 📦 to TestPyPI
        if: steps.check_package.outputs.should_publish == 'true'
        run: |
          . venv/bin/activate
          uv publish --publish-url https://test.pypi.org/legacy/

  complexity:
    name: Process test complexity
    runs-on: ubuntu-latest
    needs:
      - cache
      - prepare
      - coverage
    steps:
      - name: Check out committed code
        uses: actions/checkout@v6
      - name: Restore cached environment
        id: cache-reuse
        uses: plugwise/gh-actions/restore-venv@v1
        with:
          cache-key: ${{ needs.cache.outputs.cache-key }}
          python-version: ${{ needs.cache.outputs.python-version }}
          venv-dir: ${{ env.VENV }}
          precommit-home: ${{ env.PRE_COMMIT_HOME }}
      - name: Run complexity report (click to view details)
        run: |
          . venv-${{ needs.cache.outputs.python-version }}/bin/activate
          echo "Showing complexity higher or equal to 'C'"
          radon cc plugwise/ tests/ -s -nc --no-assert
