name: Build macOS Release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write

env:
  PYTHON_VERSION: '3.13'

jobs:
  build-macos:
    strategy:
      matrix:
        os: [macos-14, macos-13]
    runs-on: ${{ matrix.os }}

    steps:
    - name: Checkout code
      uses: actions/checkout@v5
      with:
        fetch-depth: 0

    - name: Extract version from tag
      id: get_version
      shell: bash
      run: |
        tag="${GITHUB_REF_NAME}"
        version="${tag#v}"
        echo "Extracted version: $version"
        echo "VERSION=$version" >> "$GITHUB_OUTPUT"

    - name: Setup Python
      uses: actions/setup-python@v6
      with:
        python-version: ${{ env.PYTHON_VERSION }}

    - name: Cache Python dependencies
      uses: actions/cache@v4
      with:
        path: |
          venv
          ~/.cache/pip
          ~/Library/Caches/pip
        key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
        restore-keys: |
          ${{ runner.os }}-pip-

    - name: Create virtual environment and install dependencies
      shell: bash
      run: |
        python -m venv venv
        source venv/bin/activate
        python -m pip install --upgrade pip
        pip install --no-cache-dir -r requirements.txt
        pip install --no-cache-dir cx_Freeze dmgbuild yt-dlp

    - name: Prepare build variables
      shell: bash
      run: |
        version="${{ steps.get_version.outputs.VERSION }}"
        echo "VERSION=$version" >> "$GITHUB_ENV"
        arch="$(uname -m)" # arm64 or x86_64
        echo "ARCH=$arch" >> "$GITHUB_ENV"
        if [ "$arch" = "arm64" ]; then
          echo "ARCH_SUFFIX=arm64" >> "$GITHUB_ENV"
        else
          echo "ARCH_SUFFIX=x64" >> "$GITHUB_ENV"
        fi
        echo "Prepared build variables for version: $version on $(uname -a)"

    - name: Create cx_Freeze setup script
      shell: bash
      run: |
        cat > setup_cxfreeze.py <<'PY'
        import os
        from cx_Freeze import setup, Executable

        version = os.environ.get("VERSION", "0.0.0")

        build_exe_options = dict(
            optimize=2,
            packages=[
                "PySide6.QtCore",
                "PySide6.QtGui",
                "PySide6.QtWidgets",
                "requests",
                "PIL",
                "packaging",
                "markdown",
                "pyglet",
                "loguru",
                "setuptools",
            ],
            excludes=[
                "PySide6.QtBluetooth",
                "PySide6.QtNetwork",
                "PySide6.QtOpenGL",
                "PySide6.QtPrintSupport",
                "PySide6.QtSvg",
                "PySide6.QtTest",
                "PySide6.QtXml",
                "PySide6.QtSql",
                "PySide6.QtHelp",
                "PySide6.QtMultimedia",
                "PySide6.QtQml",
                "PySide6.QtQuick",
                "PySide6.QtWebEngineCore",
                "PIL.ImageDraw",
                "PIL.ImageFont",
                "numpy",
                "scipy",
                "wx",
                "pandas",
                "tkinter",
                "yt_dlp",
                "unittest",
                "test",
                "tests",
            ],
            include_files=[
                ("src", "src"),
                ("assets/branding/icons", "lib/assets/branding/icons"),
                ("assets/Icon", "lib/assets/Icon"),
                ("assets/sound", "lib/assets/sound"),
                ("languages", "lib/languages"),
            ],
        )

        executables = [
            Executable(
                script="main.py",
                target_name=f"YTSage-v{version}",
                icon="assets/branding/icons/icon.icns",
            )
        ]

        setup(
            name="YTSage",
            version=version,
            description="YTSage",
            options={
                "build_exe": build_exe_options,
                "bdist_mac": {
                    "iconfile": "assets/branding/icons/icon.icns",
                    "bundle_name": f"YTSage-v{version}",
                },
                "bdist_dmg": {
                    "volume_label": f"YTSage v{version}",
                    "applications_shortcut": True,
                    # Sensible defaults; can be customized later if desired
                    "format": "UDZO",
                    "filesystem": "HFS+",
                    "default_view": "icon-view",
                },
            },
            executables=executables,
        )
        PY

    - name: Build .app bundle (bdist_mac)
      shell: bash
      run: |
        source venv/bin/activate
        python setup_cxfreeze.py bdist_mac
        # Locate the built .app (cx_Freeze may place it under build/ or dist/)
        app_path=""
        for cand in "dist/YTSage-v${VERSION}.app" "build/dist/YTSage-v${VERSION}.app" "build/YTSage-v${VERSION}.app"; do
          if [ -d "$cand" ]; then app_path="$cand"; break; fi
        done
        if [ -z "$app_path" ]; then
          app_path=$(ls -d dist/*.app build/dist/*.app build/*.app 2>/dev/null | head -n1 || true)
        fi
        if [ -n "$app_path" ] && [ -d "$app_path/Contents/Resources/lib/assets/branding/screenshots" ]; then
          rm -rf "$app_path/Contents/Resources/lib/assets/branding/screenshots"
          echo "Removed screenshots folder from .app bundle at $app_path"
        fi
        echo "Post-bdist_mac directory listing:"
        echo "-- dist --"; ls -lah dist || true
        echo "-- build --"; ls -lah build || true

    - name: Build DMG (bdist_dmg)
      shell: bash
      run: |
        source venv/bin/activate
        python setup_cxfreeze.py bdist_dmg
        echo "Post-bdist_dmg directory listing:"
        echo "-- dist --"; ls -lah dist || true
        echo "-- build --"; ls -lah build || true

    - name: Package and prepare release artifacts (.app.zip and .dmg)
      shell: bash
      run: |
        version="${{ steps.get_version.outputs.VERSION }}"
        echo "Preparing artifacts for version: $version"
        mkdir -p artifacts

        # Find the .app bundle (preferring versioned name)
        app_path=""
        for cand in "dist/YTSage-v${version}.app" "build/dist/YTSage-v${version}.app" "build/YTSage-v${version}.app"; do
          if [ -d "$cand" ]; then app_path="$cand"; break; fi
        done
        if [ -z "$app_path" ]; then
          app_path=$(ls -d dist/*.app build/dist/*.app build/*.app 2>/dev/null | head -n1 || true)
        fi
        if [ -n "$app_path" ] && [ -d "$app_path" ]; then
          app_base="$(basename "$app_path")"
          app_parent="$(dirname "$app_path")"
          # Ensure screenshots folder is not shipped
          if [ -d "$app_path/Contents/Resources/lib/assets/branding/screenshots" ]; then
            rm -rf "$app_path/Contents/Resources/lib/assets/branding/screenshots"
            echo "Removed screenshots folder from .app bundle at $app_path"
          fi
          (cd "$app_parent" && zip -r "${GITHUB_WORKSPACE}/artifacts/YTSage-v${version}-${ARCH_SUFFIX}.app.zip" "$app_base")
          echo "Created: artifacts/YTSage-v${version}-${ARCH_SUFFIX}.app.zip"
        else
          echo "Warning: .app bundle not found in dist/ or build/"
        fi

        # Try to find the generated DMG in dist or build
        dmg_src=""
        for cand in "dist/YTSage-v${version}.dmg"; do
          if [ -f "$cand" ]; then dmg_src="$cand"; break; fi
        done
        if [ -z "$dmg_src" ]; then
          dmg_src=$(ls dist/*.dmg build/*.dmg build/dist/*.dmg 2>/dev/null | head -n1 || true)
        fi

        if [ -n "$dmg_src" ] && [ -f "$dmg_src" ]; then
          # Rename the DMG to a consistent name in artifacts
          cp "$dmg_src" "artifacts/YTSage-v${version}-${ARCH_SUFFIX}.dmg"
          echo "Copied DMG to artifacts from $dmg_src -> artifacts/YTSage-v${version}-${ARCH_SUFFIX}.dmg"
        else
          echo "Warning: No DMG found in dist/ or build/"
        fi

        echo "Final artifacts:"
        ls -lh artifacts || true

    - name: Create/Update draft release
      uses: softprops/action-gh-release@v1
      with:
        tag_name: ${{ github.ref_name }}
        name: YTSage ${{ github.ref_name }}
        draft: true
        prerelease: false
        append_body: true
        fail_on_unmatched_files: false
        body: |
          # YTSage ${{ github.ref_name }}

          **Release Date**: ${{ github.event.head_commit.timestamp }}

          **Full Changelog**: https://github.com/${{ github.repository }}/compare/${{ github.ref_name }}
        files: |
          artifacts/*
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
