name: Build Conda-Pack Environment

on:
  workflow_dispatch:
    inputs:
      branch:
        description: '选择要构建的分支'
        required: true
        default: 'dev'
        type: string
      platforms:
        description: '选择构建平台 (逗号分隔): linux-64, osx-64, osx-arm64, win-64'
        required: false
        default: 'win-64'
        type: string

jobs:
  build-conda-pack:
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            platform: linux-64
            env_file: unilabos-linux-64.yaml
            script_ext: sh
          - os: macos-13 # Intel
            platform: osx-64
            env_file: unilabos-osx-64.yaml
            script_ext: sh
          - os: macos-latest # ARM64
            platform: osx-arm64
            env_file: unilabos-osx-arm64.yaml
            script_ext: sh
          - os: windows-latest
            platform: win-64
            env_file: unilabos-win64.yaml
            script_ext: bat

    runs-on: ${{ matrix.os }}

    defaults:
      run:
        # Windows uses cmd for better conda/mamba compatibility, Unix uses bash
        shell: ${{ matrix.platform == 'win-64' && 'cmd' || 'bash' }}

    steps:
      - name: Check if platform should be built
        id: should_build
        shell: bash
        run: |
          if [[ -z "${{ github.event.inputs.platforms }}" ]]; then
            echo "should_build=true" >> $GITHUB_OUTPUT
          elif [[ "${{ github.event.inputs.platforms }}" == *"${{ matrix.platform }}"* ]]; then
            echo "should_build=true" >> $GITHUB_OUTPUT
          else
            echo "should_build=false" >> $GITHUB_OUTPUT
          fi

      - uses: actions/checkout@v4
        if: steps.should_build.outputs.should_build == 'true'
        with:
          ref: ${{ github.event.inputs.branch }}
          fetch-depth: 0

      - name: Setup Miniforge (with mamba)
        if: steps.should_build.outputs.should_build == 'true'
        uses: conda-incubator/setup-miniconda@v3
        with:
          miniforge-version: latest
          use-mamba: true
          python-version: '3.11.11'
          channels: conda-forge,robostack-staging,uni-lab,defaults
          channel-priority: flexible
          activate-environment: unilab
          auto-update-conda: false
          show-channel-urls: true

      - name: Install conda-pack, unilabos and dependencies (Windows)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
        run: |
          echo Installing unilabos and dependencies to unilab environment...
          echo Using mamba for faster and more reliable dependency resolution...
          mamba install -n unilab uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y

      - name: Install conda-pack, unilabos and dependencies (Unix)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
        shell: bash
        run: |
          echo "Installing unilabos and dependencies to unilab environment..."
          echo "Using mamba for faster and more reliable dependency resolution..."
          mamba install -n unilab uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y

      - name: Get latest ros-humble-unilabos-msgs version (Windows)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
        id: msgs_version_win
        run: |
          echo Checking installed ros-humble-unilabos-msgs version...
          conda list -n unilab ros-humble-unilabos-msgs
          for /f "tokens=2" %%i in ('conda list -n unilab ros-humble-unilabos-msgs --json ^| python -c "import sys, json; pkgs=json.load(sys.stdin); print(pkgs[0]['version'] if pkgs else 'not-found')"') do set VERSION=%%i
          echo installed_version=%VERSION% >> %GITHUB_OUTPUT%
          echo Installed ros-humble-unilabos-msgs version: %VERSION%

      - name: Get latest ros-humble-unilabos-msgs version (Unix)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
        id: msgs_version_unix
        shell: bash
        run: |
          echo "Checking installed ros-humble-unilabos-msgs version..."
          VERSION=$(conda list -n unilab ros-humble-unilabos-msgs --json | python -c "import sys, json; pkgs=json.load(sys.stdin); print(pkgs[0]['version'] if pkgs else 'not-found')")
          echo "installed_version=$VERSION" >> $GITHUB_OUTPUT
          echo "Installed ros-humble-unilabos-msgs version: $VERSION"

      - name: Check for newer ros-humble-unilabos-msgs (Windows)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
        run: |
          echo Checking for available ros-humble-unilabos-msgs versions...
          mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge || echo Search completed
          echo.
          echo Updating ros-humble-unilabos-msgs to latest version...
          mamba update -n unilab ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge -y || echo Already at latest version

      - name: Check for newer ros-humble-unilabos-msgs (Unix)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
        shell: bash
        run: |
          echo "Checking for available ros-humble-unilabos-msgs versions..."
          mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge || echo "Search completed"
          echo ""
          echo "Updating ros-humble-unilabos-msgs to latest version..."
          mamba update -n unilab ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge -y || echo "Already at latest version"

      - name: Install latest unilabos from source (Windows)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
        run: |
          echo Uninstalling existing unilabos...
          mamba run -n unilab pip uninstall unilabos -y || echo unilabos not installed via pip
          echo Installing unilabos from source (branch: ${{ github.event.inputs.branch }})...
          mamba run -n unilab pip install .
          echo Verifying installation...
          mamba run -n unilab pip show unilabos

      - name: Install latest unilabos from source (Unix)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
        shell: bash
        run: |
          echo "Uninstalling existing unilabos..."
          mamba run -n unilab pip uninstall unilabos -y || echo "unilabos not installed via pip"
          echo "Installing unilabos from source (branch: ${{ github.event.inputs.branch }})..."
          mamba run -n unilab pip install .
          echo "Verifying installation..."
          mamba run -n unilab pip show unilabos

      - name: Display environment info (Windows)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
        run: |
          echo === Environment Information ===
          mamba env list
          echo.
          echo === Installed Packages ===
          mamba list -n unilab | findstr /C:"unilabos" /C:"ros-humble-unilabos-msgs" || mamba list -n unilab
          echo.
          echo === Python Packages ===
          mamba run -n unilab pip list | findstr unilabos || mamba run -n unilab pip list

      - name: Display environment info (Unix)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
        shell: bash
        run: |
          echo "=== Environment Information ==="
          mamba env list
          echo ""
          echo "=== Installed Packages ==="
          mamba list -n unilab | grep -E "(unilabos|ros-humble-unilabos-msgs)" || mamba list -n unilab
          echo ""
          echo "=== Python Packages ==="
          mamba run -n unilab pip list | grep unilabos || mamba run -n unilab pip list

      - name: Verify environment integrity (Windows)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
        run: |
          echo Verifying Python version...
          mamba run -n unilab python -c "import sys; print(f'Python version: {sys.version}')"
          echo Verifying unilabos import...
          mamba run -n unilab python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo Warning: Could not import unilabos
          echo Checking critical packages...
          mamba run -n unilab python -c "import rclpy; print('ROS2 rclpy: OK')"
          echo Running comprehensive verification script...
          mamba run -n unilab python scripts\verify_installation.py --auto-install || echo Warning: Verification script reported issues
          echo Environment verification complete!

      - name: Verify environment integrity (Unix)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
        shell: bash
        run: |
          echo "Verifying Python version..."
          mamba run -n unilab python -c "import sys; print(f'Python version: {sys.version}')"
          echo "Verifying unilabos import..."
          mamba run -n unilab python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo "Warning: Could not import unilabos"
          echo "Checking critical packages..."
          mamba run -n unilab python -c "import rclpy; print('ROS2 rclpy: OK')"
          echo "Running comprehensive verification script..."
          mamba run -n unilab python scripts/verify_installation.py --auto-install || echo "Warning: Verification script reported issues"
          echo "Environment verification complete!"

      - name: Pack conda environment (Windows)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
        run: |
          echo Packing unilab environment with conda-pack...
          mamba activate unilab && conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files
          echo Pack file created:
          dir unilab-env-${{ matrix.platform }}.tar.gz

      - name: Pack conda environment (Unix)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
        shell: bash
        run: |
          echo "Packing unilab environment with conda-pack..."
          mamba install conda-pack -c conda-forge -y
          conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files
          echo "Pack file created:"
          ls -lh unilab-env-${{ matrix.platform }}.tar.gz

      - name: Prepare Windows distribution package
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
        run: |
          echo ==========================================
          echo Creating distribution package...
          echo Platform: ${{ matrix.platform }}
          echo ==========================================
          mkdir dist-package 2>nul || cd .

          rem Copy packed environment
          echo Adding: unilab-env-${{ matrix.platform }}.tar.gz
          copy unilab-env-${{ matrix.platform }}.tar.gz dist-package\

          rem Copy installation script
          echo Adding: install_unilab.bat
          copy scripts\install_unilab.bat dist-package\

          rem Copy verification script
          echo Adding: verify_installation.py
          copy scripts\verify_installation.py dist-package\

          rem Copy source code repository (including .git)
          echo Adding: Uni-Lab-OS source repository
          robocopy . dist-package\Uni-Lab-OS /E /XD dist-package /NFL /NDL /NJH /NJS /NC /NS || if %ERRORLEVEL% LSS 8 exit /b 0

          rem Create README using Python script
          echo Creating: README.txt
          python scripts\create_readme.py ${{ matrix.platform }} ${{ github.event.inputs.branch }} dist-package\README.txt

          echo.
          echo Distribution package contents:
          dir /b dist-package
          echo.

      - name: Prepare Unix/Linux distribution package
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
        shell: bash
        run: |
          echo "=========================================="
          echo "Creating distribution package..."
          echo "Platform: ${{ matrix.platform }}"
          echo "=========================================="
          mkdir -p dist-package

          # Copy packed environment
          echo "Adding: unilab-env-${{ matrix.platform }}.tar.gz"
          cp unilab-env-${{ matrix.platform }}.tar.gz dist-package/

          # Copy installation script
          echo "Adding: install_unilab.sh"
          cp scripts/install_unilab.sh dist-package/
          chmod +x dist-package/install_unilab.sh

          # Copy verification script
          echo "Adding: verify_installation.py"
          cp scripts/verify_installation.py dist-package/

          # Copy source code repository (including .git)
          echo "Adding: Uni-Lab-OS source repository"
          rsync -a --exclude='dist-package' . dist-package/Uni-Lab-OS

          # Create README using Python script
          echo "Creating: README.txt"
          python scripts/create_readme.py ${{ matrix.platform }} ${{ github.event.inputs.branch }} dist-package/README.txt

          echo ""
          echo "Distribution package contents:"
          ls -lh dist-package/
          echo ""

      - name: Upload distribution package
        if: steps.should_build.outputs.should_build == 'true'
        uses: actions/upload-artifact@v4
        with:
          name: unilab-pack-${{ matrix.platform }}-${{ github.event.inputs.branch }}
          path: dist-package/
          retention-days: 90
          if-no-files-found: error

      - name: Display package info (Windows)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
        run: |
          echo ==========================================
          echo Build Summary
          echo ==========================================
          echo Platform: ${{ matrix.platform }}
          echo Branch: ${{ github.event.inputs.branch }}
          echo Python version: 3.11.11
          echo.
          echo Distribution package contents:
          dir dist-package
          echo.
          echo Artifact name: unilab-pack-${{ matrix.platform }}-${{ github.event.inputs.branch }}
          echo.
          echo After download, extract the ZIP and run:
          echo   install_unilab.bat
          echo ==========================================

      - name: Display package info (Unix)
        if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
        shell: bash
        run: |
          echo "=========================================="
          echo "Build Summary"
          echo "=========================================="
          echo "Platform: ${{ matrix.platform }}"
          echo "Branch: ${{ github.event.inputs.branch }}"
          echo "Python version: 3.11.11"
          echo ""
          echo "Distribution package contents:"
          ls -lh dist-package/
          echo ""
          echo "Artifact name: unilab-pack-${{ matrix.platform }}-${{ github.event.inputs.branch }}"
          echo ""
          echo "After download:"
          echo "  install_unilab.sh"
          echo "=========================================="
