name: Manual Publish to PyPI (Tagged Release Only)

on:
  workflow_dispatch:
    inputs:
      tag:
        description: "Existing git tag to publish (e.g. v0.2.1)"
        required: true
      versioning_method:
        description: "Version strategy: setuptools_scm (tag-based) or inject_static (write into pyproject.toml)"
        required: true
        type: choice
        options:
          - setuptools_scm
          - inject_static
      dry_run:
        description: "Set true to build & validate without uploading"
        required: false
        default: "false"

concurrency:
  group: pypi-publish-${{ github.workflow }}-${{ inputs.tag }}
  cancel-in-progress: false

permissions:
  contents: read
  id-token: write   # Needed for PyPI Trusted Publishing (OIDC)

jobs:
  publish:
    runs-on: ubuntu-latest
    # Optional: uncomment if you want an environment gate
    # environment: pypi
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Validate tag
        id: validate_tag
        run: |
          TAG="${{ inputs.tag }}"
          git fetch --tags --force
          if ! git rev-parse "$TAG" >/dev/null 2>&1; then
            echo "Tag '$TAG' not found." >&2
            exit 1
          fi
          if [[ ! "$TAG" =~ ^v[0-9]+(\.[0-9]+){1,2}([a-zA-Z0-9._-]+)?$ ]]; then
            echo "Tag format invalid: $TAG" >&2
            exit 1
          fi
            TAG_COMMIT="$(git rev-list -n 1 "$TAG")"
          HEAD_COMMIT="$(git rev-parse HEAD)"
          if [ "$TAG_COMMIT" != "$HEAD_COMMIT" ]; then
            git checkout "$TAG"
          fi
          VERSION="${TAG#v}"
          echo "version=$VERSION" >> "$GITHUB_OUTPUT"

      - name: Show derived version
        run: |
          echo "Version: ${{ steps.validate_tag.outputs.version }}"

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

      - name: Cache pip
        uses: actions/cache@v4
        with:
          path: ~/.cache/pip
          key: pip-${{ runner.os }}-${{ hashFiles('pyproject.toml', 'setup.cfg', 'requirements*.txt') }}
          restore-keys: |
            pip-${{ runner.os }}-

      - name: Install build tooling
        run: |
          python -m pip install --upgrade pip
          pip install --upgrade build twine

      - name: Inject static version (if selected)
        if: inputs.versioning_method == 'inject_static'
        run: |
          VERSION="${{ steps.validate_tag.outputs.version }}"
          if [ -f pyproject.toml ]; then
            if grep -q "^version *= *" pyproject.toml; then
              sed -i "s/^version *= *.*/version = \"${VERSION}\"/" pyproject.toml
            else
              echo "version = \"${VERSION}\"" >> pyproject.toml
            fi
          elif [ -f setup.cfg ]; then
            if grep -q "^version =" setup.cfg; then
              sed -i "s/^version = .*/version = ${VERSION}/" setup.cfg
            else
              echo "version = ${VERSION}" >> setup.cfg
            fi
          else
            echo "No metadata file found for static injection." >&2
            exit 1
          fi

      - name: Check setuptools_scm presence (info)
        if: inputs.versioning_method == 'setuptools_scm'
        run: |
          if grep -qi "setuptools_scm" pyproject.toml 2>/dev/null; then
            echo "setuptools_scm detected."
          else
            echo "Warning: setuptools_scm strategy chosen but not listed in pyproject.toml."
          fi

      - name: Build distributions
        run: |
          rm -rf dist
          python -m build

      - name: Validate distributions
        run: twine check dist/*

      - name: Pre-upload smoke test (install from local wheel)
        if: inputs.dry_run != 'true'
        run: |
          WHEEL_FILE=$(ls dist/*.whl | head -n 1)
          pip install "$WHEEL_FILE"
          python -c "from importlib.metadata import version; print('Smoke test passed. Version:', version('aimodelshare'))"

      - name: Dry run (skip upload)
        if: inputs.dry_run == 'true'
        run: |
          echo "Dry run enabled; skipping upload."
          ls -l dist

      - name: Publish to PyPI (Trusted Publisher)
        if: inputs.dry_run != 'true'
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          skip-existing: false
          # No password: uses OIDC trusted publishing

      - name: Post-publish check
        if: inputs.dry_run != 'true'
        run: |
          pip install --upgrade aimodelshare
          python -c "from importlib.metadata import version; print('Installed version:', version('aimodelshare'))"

      - name: Summary
        run: |
          echo "Tag: ${{ inputs.tag }}"
          echo "Version: ${{ steps.validate_tag.outputs.version }}"
          echo "Dry run: ${{ inputs.dry_run }}"
