name: Build and Release

on:
  release:
    types: [published]
  workflow_dispatch:  # Allow manual trigger

permissions:
  contents: read

jobs:
  # Compile Stan models for Linux only
  compile-stan-models:
    name: Compile Stan models on Linux
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

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


      - name: Install uv
        uses: astral-sh/setup-uv@v4
        with:
          enable-cache: false

      - name: Install cmdstanpy
        run: |
          uv pip install --system cmdstanpy

      - name: Install and compile CmdStan
        run: |
          python -c "import cmdstanpy; cmdstanpy.install_cmdstan(compiler=True, verbose=True)"

      - name: Compile Prophet Stan model
        shell: bash
        run: |
          python << 'EOF'
          import cmdstanpy
          import shutil
          from pathlib import Path
          import platform

          # Compile the Stan model with threading support
          print("Compiling Prophet Stan model with threading support...")
          model = cmdstanpy.CmdStanModel(
              stan_file="stan/prophet.stan",
              cpp_options={"STAN_THREADS": True}
          )
          print(f"Compiled executable: {model.exe_file}")

          # Use stan/ root directory for Linux
          target_dir = Path("stan")
          target_dir.mkdir(parents=True, exist_ok=True)

          # Copy the compiled executable
          target_name = "prophet_model"
          shutil.copy2(model.exe_file, target_dir / target_name)
          (target_dir / target_name).chmod(0o755)

          print(f"✓ Binary installed at: {target_dir / target_name}")
          print(f"  Size: {(target_dir / target_name).stat().st_size} bytes")

          # Note: TBB libraries are not needed - they will be found from the system

          # Also copy cmdstan version for reference
          cmdstan_version_file = target_dir / "cmdstan_version.txt"
          with open(cmdstan_version_file, "w") as f:
              f.write(str(cmdstanpy.cmdstan_version()))
          print(f"✓ CmdStan version: {cmdstanpy.cmdstan_version()}")
          EOF

      - name: Upload compiled Stan models
        uses: actions/upload-artifact@v4
        with:
          name: stan-models-ubuntu-latest
          path: stan/
          retention-days: 1

  # Build wheels for Linux only
  build-wheels:
    name: Build wheels on Linux
    needs: compile-stan-models
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Download compiled Stan models
        uses: actions/download-artifact@v4
        with:
          pattern: stan-models-*
          path: stan-artifacts
          merge-multiple: false

      - name: Copy Stan models to workspace
        shell: bash
        run: |
          cp -r stan-artifacts/stan-models-ubuntu-latest/* stan/
          ls -la stan/

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

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Build wheels
        uses: PyO3/maturin-action@v1
        with:
          target: x86_64
          args: --release --out dist --find-interpreter
          sccache: 'true'
          manylinux: auto

      - name: Upload wheels
        uses: actions/upload-artifact@v4
        with:
          name: wheels-linux
          path: dist
          retention-days: 1

  # Build source distribution
  build-sdist:
    name: Build source distribution
    needs: compile-stan-models
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Download all compiled Stan models
        uses: actions/download-artifact@v4
        with:
          pattern: stan-models-*
          path: stan-artifacts
          merge-multiple: false

      - name: Merge Stan models into stan directory
        run: |
          cp -r stan-artifacts/stan-models-ubuntu-latest/* stan/
          ls -la stan/

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

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Build sdist
        uses: PyO3/maturin-action@v1
        with:
          command: sdist
          args: --out dist

      - name: Upload sdist
        uses: actions/upload-artifact@v4
        with:
          name: sdist
          path: dist
          retention-days: 1

  # Test PyPI upload (always runs on release)
  test-pypi-upload:
    name: Upload to Test PyPI
    needs: [build-wheels, build-sdist]
    runs-on: ubuntu-latest
    environment: testpypi
    permissions:
      id-token: write  # For trusted publishing

    steps:
      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          name: wheels-linux
          path: dist

      - name: Download sdist
        uses: actions/download-artifact@v4
        with:
          name: sdist
          path: dist

      - name: List artifacts
        run: ls -lR dist/

      - name: Publish to Test PyPI
        uses: PyO3/maturin-action@v1
        with:
          command: upload
          args: --skip-existing dist/*
        env:
          MATURIN_PYPI_TOKEN: ${{ secrets.TEST_PYPI_TOKEN }}
          MATURIN_REPOSITORY: testpypi

      - name: Wait for package to be available
        run: sleep 60

      - name: Install uv
        uses: astral-sh/setup-uv@v4
        with:
          enable-cache: false

      - name: Test installation from Test PyPI
        run: |
          uv venv
          source .venv/bin/activate
          uv pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ farseer
          python -c "import farseer; print('Successfully imported farseer version:', farseer.__version__)"

  # Production PyPI upload (only after successful Test PyPI)
  pypi-upload:
    name: Upload to PyPI
    needs: test-pypi-upload
    runs-on: ubuntu-latest
    environment: pypi
    permissions:
      id-token: write  # For trusted publishing

    steps:
      - name: Download all wheel artifacts
        uses: actions/download-artifact@v4
        with:
          name: wheels-linux
          path: dist

      - name: Download sdist
        uses: actions/download-artifact@v4
        with:
          name: sdist
          path: dist

      - name: List artifacts
        run: ls -lR dist/

      - name: Publish to PyPI
        uses: PyO3/maturin-action@v1
        with:
          command: upload
          args: --skip-existing dist/*
        env:
          MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
