name: Build macOS Release

on:
  workflow_dispatch:
    inputs:
      version:
        description: 'Version name for the release (e.g., 1.0.0)'
        required: true
        type: string
  workflow_call:
    inputs:
      version:
        description: 'Version name for the release (e.g., 1.0.0)'
        required: true
        type: string

permissions:
  contents: write

env:
  PYTHON_VERSION: '3.13'

jobs:
  build-macos:
    runs-on: macos-latest

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

    - name: Get version
      id: get_version
      shell: bash
      run: |
        version="${{ inputs.version || github.event.inputs.version }}"
        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('pyproject.toml') }}
        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 .
        pip install --no-cache-dir cx_Freeze dmgbuild

    - 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: |
        # Create entry point script
        cat > ytsage_entry.py <<'ENTRY'
        from ytsage.main import main
        if __name__ == "__main__":
            main()
        ENTRY

        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,
            silent=True,
            packages=[
                "ytsage",
                "PySide6.QtCore",
                "PySide6.QtGui",
                "PySide6.QtWidgets",
                "PySide6.QtMultimedia",
                "PySide6.QtNetwork",
                "PySide6.QtDBus",
                "requests",
                "PIL",
                "packaging",
                "markdown",
                "loguru",
                "setuptools",
            ],
            zip_include_packages=[
                "PySide6",
                "shiboken6",
                "requests",
                "PIL",
                "packaging",
            ],
            excludes=[
                "PySide6.QtBluetooth",
                "PySide6.QtOpenGL",
                "PySide6.QtPrintSupport",
                "PySide6.QtSvg",
                "PySide6.QtTest",
                "PySide6.QtXml",
                "PySide6.QtSql",
                "PySide6.QtHelp",
                "PySide6.QtQml",
                "PySide6.QtQuick",
                "PySide6.QtWebEngineCore",
                "PIL.ImageDraw",
                "PIL.ImageFont",
                "numpy",
                "scipy",
                "wx",
                "pandas",
                "tkinter",
                "yt_dlp",
                "unittest",
                "test",
                "tests",
                "pydoc",
                "doctest",
                "email",
            ],
            include_files=[
                ("ytsage/assets/Icon", "lib/assets/Icon"),
                ("ytsage/assets/sound", "lib/assets/sound"),
                ("ytsage/languages", "lib/languages"),
                ("branding/icons", "lib/assets/branding/icons"),
            ],
        )

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

        setup(
            name="YTSage",
            version=version,
            description="YTSage",
            options={
                "build_exe": build_exe_options,
                "bdist_mac": {
                    "iconfile": "branding/icons/icon.icns",
                    "bundle_name": f"YTSage-v{version}",
                },
                "bdist_dmg": {
                    "volume_label": f"YTSage v{version}",
                    "applications_shortcut": True,
                    "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 -OO setup_cxfreeze.py bdist_mac
        
    - name: Trim unnecessary files from App bundle
      shell: bash
      run: |
        version="${{ steps.get_version.outputs.VERSION }}"
        
        # Locate the built .app
        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" ]; then
          echo "Processing App Bundle at: $app_path"
          
          # Simplified discovery of library directories
          # We search for 'lib' folders and then verify if they look like the python library folder
          find "$app_path/Contents" -type d -name "lib" | while read -r lib_dir; do
              # Check if this lib dir is a python library dir (contains asyncio or PySide6 or ytsage)
              if [ -d "$lib_dir/asyncio" ] || [ -d "$lib_dir/PySide6" ] || [ -d "$lib_dir/ytsage" ]; then
                  echo "Cleaning Library Directory: $lib_dir"
                  
                  # 1. Remove screenshots
                  rm -rf "$lib_dir/assets/branding/screenshots"
                  
                  # 2. Remove unused Qt translations (Recursively find 'translations' folder inside PySide6)
                  find "$lib_dir" -type d -path "*/PySide6/*/translations" -exec rm -rf {} + 2>/dev/null || true
                  find "$lib_dir" -type d -path "*/PySide6/translations" -exec rm -rf {} + 2>/dev/null || true
                  
                  # 3. Remove unused Qt plugins 
                  # Determine plugins path
                  plugins_path=""
                  if [ -d "$lib_dir/PySide6/plugins" ]; then plugins_path="$lib_dir/PySide6/plugins"; fi
                  if [ -d "$lib_dir/PySide6/Qt/plugins" ]; then plugins_path="$lib_dir/PySide6/Qt/plugins"; fi
                  
                  if [ -n "$plugins_path" ]; then
                      echo "Found plugins at: $plugins_path"
                      for plugin in designer pdf svg sql help qml quick webengine bluetooth opengl printsupport test xml; do
                         rm -rf "$plugins_path/$plugin"
                      done
                      
                      # Specific cleanups
                      find "$plugins_path" -name "libqpdf.*" -delete
                  fi
                  
                  # 4. Remove bloat Qt libraries / Frameworks
                  # Iterate specifically over unwanted Qt modules
                  # Matches both 'QtQml' (file) and 'QtQml.abi3.so' etc
                  for bloat in QtQml QtQmlMeta QtQmlModels QtQmlWorkerScript QtQuick QtQuickControls2 QtQuickTemplates2 QtWebEngine QtWebEngineCore QtVirtualKeyboard QtVirtualKeyboardQml QtOpenGL QtOpenGLWidgets QtPdf QtPdfWidgets; do
                      find "$lib_dir" -maxdepth 2 -name "$bloat" -delete
                      find "$lib_dir" -maxdepth 2 -name "${bloat}.*" -delete 
                      find "$lib_dir" -maxdepth 2 -name "*$bloat*" -delete 
                  done
                  
                  # 5. Remove build tools and unused python modules
                  for tool in setuptools wheel pkg_resources _distutils_hack curses _pyrepl; do
                     rm -rf "$lib_dir/$tool"
                  done
              fi
          done
          
          # Final sanity verification
          echo "Trim complete. Remaining contents of lib (first 2 levels):"
          find "$app_path/Contents" -type d -name "lib" -exec ls -R {} \; | head -n 50 || true
          
        else
           echo "Error: Could not find .app bundle to trim!"
           exit 1
        fi

    - 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
        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")"
          
          # Create ZIP
          (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"
          
          # Create DMG (Manual)
          echo "Creating DMG from $app_path..."
          mkdir -p dmg_stage
          cp -R "$app_path" "dmg_stage/"
          ln -s /Applications "dmg_stage/Applications"
          
          hdiutil create -volname "YTSage v${version}" -srcfolder "dmg_stage" -ov -format UDZO "artifacts/YTSage-v${version}-${ARCH_SUFFIX}.dmg"
          echo "Created: artifacts/YTSage-v${version}-${ARCH_SUFFIX}.dmg"
          
          rm -rf dmg_stage
        else
          echo "Error: .app bundle not found in dist/ or build/"
          exit 1
        fi

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

    - name: Create/Update draft release
      uses: softprops/action-gh-release@v2
      with:
        tag_name: v${{ steps.get_version.outputs.VERSION }}
        name: YTSage v${{ steps.get_version.outputs.VERSION }}
        draft: true
        prerelease: false
        append_body: true
        fail_on_unmatched_files: false
        body: |
          # YTSage v${{ steps.get_version.outputs.VERSION }}

          **Release Date**: ${{ github.event.head_commit.timestamp }}
        files: |
          artifacts/*
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
