name: Build and Release

on:
  # 手动触发
  workflow_dispatch:
    inputs:
      version:
        description: '版本号 (如 0.1.0)'
        required: true
        type: string
  # 推送 tag 时自动触发
  push:
    tags:
      - 'v*'

jobs:
  # macOS 构建需要分架构
  # better-sqlite3 等原生模块会通过 prebuild 下载对应架构的预编译二进制
  build-mac:
    strategy:
      matrix:
        include:
          - os: macos-14 # 使用 ARM runner 交叉编译 x64
            arch: x64
          - os: macos-14 # Apple Silicon (arm64) 原生构建
            arch: arm64
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 9

      - name: Get pnpm store directory
        shell: bash
        run: |
          echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

      - name: Setup pnpm cache
        uses: actions/cache@v4
        with:
          path: ${{ env.STORE_PATH }}
          key: ${{ runner.os }}-${{ matrix.arch }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-${{ matrix.arch }}-pnpm-store-

      - name: Install dependencies
        run: pnpm install

      # macOS 签名和公证需要的 API Key 文件
      - name: Create Apple API Key File
        run: |
          mkdir -p ~/private_keys
          echo "${{ secrets.APPLE_API_KEY }}" > ~/private_keys/AuthKey_${{ secrets.APPLE_API_KEY_ID }}.p8

      - name: Build Electron app for macOS (${{ matrix.arch }})
        env:
          GH_TOKEN: ${{ secrets.GH_TOKEN }}
          # 代码签名
          CSC_LINK: ${{ secrets.CSC_LINK }}
          CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
          # 公证
          APPLE_API_KEY: ~/private_keys/AuthKey_${{ secrets.APPLE_API_KEY_ID }}.p8
          APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
          APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
          # 分析服务
          APTABASE_APP_KEY: ${{ secrets.APTABASE_APP_KEY }}
        run: pnpm build && pnpm exec electron-builder --mac --${{ matrix.arch }} --config electron-builder.yml -p never

      - name: Upload macOS artifacts (${{ matrix.arch }})
        uses: actions/upload-artifact@v4
        with:
          name: ChatLab-mac-${{ matrix.arch }}
          path: |
            dist/*.dmg
            dist/*.zip
            dist/*.yml
            dist/*.json
            dist/*.blockmap
          if-no-files-found: warn
          retention-days: 1 # 只保留1天，Release后会上传到GitHub Releases

  build-win:
    runs-on: windows-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Setup pnpm
        uses: pnpm/action-setup@v4
        with:
          version: 9

      - name: Get pnpm store directory
        shell: bash
        run: |
          echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

      - name: Setup pnpm cache
        uses: actions/cache@v4
        with:
          path: ${{ env.STORE_PATH }}
          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pnpm-store-

      - name: Install dependencies
        run: pnpm install

      - name: Build Electron app for Windows
        env:
          GH_TOKEN: ${{ secrets.GH_TOKEN }}
          # 分析服务
          APTABASE_APP_KEY: ${{ secrets.APTABASE_APP_KEY }}
        run: pnpm build:win

      - name: Upload Windows artifacts
        uses: actions/upload-artifact@v4
        with:
          name: ChatLab-win
          path: |
            dist/*.exe
            dist/*.yml
            dist/*.json
            dist/*.blockmap
          if-no-files-found: warn
          retention-days: 1 # 只保留1天，Release后会上传到GitHub Releases

  release:
    needs: [build-mac, build-win]
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch'

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # 获取完整历史用于生成 changelog

      - name: Download macOS artifacts (x64)
        uses: actions/download-artifact@v4
        with:
          name: ChatLab-mac-x64
          path: dist

      - name: Download macOS artifacts (arm64)
        uses: actions/download-artifact@v4
        with:
          name: ChatLab-mac-arm64
          path: dist

      - name: Download Windows artifacts
        uses: actions/download-artifact@v4
        with:
          name: ChatLab-win
          path: dist

      - name: List files
        run: ls -la dist/

      - name: Generate Release Notes
        id: release_notes
        run: |
          # 获取当前版本号
          if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
            CURRENT_VERSION="v${{ inputs.version }}"
          else
            CURRENT_VERSION="${{ github.ref_name }}"
          fi
          VERSION_NUMBER="${CURRENT_VERSION#v}"

          echo "Current version: $CURRENT_VERSION"

          # 获取上一个 tag
          PREVIOUS_TAG=$(git tag --sort=-creatordate | grep -v "^${CURRENT_VERSION}$" | head -n 1)

          if [ -z "$PREVIOUS_TAG" ]; then
            echo "No previous tag found, using first commit"
            COMMIT_RANGE="HEAD"
          else
            echo "Previous tag: $PREVIOUS_TAG"
            COMMIT_RANGE="${PREVIOUS_TAG}..HEAD"
          fi

          # 生成 release notes
          {
            echo ""

            # 提取 feat commits
            FEATS=$(git log $COMMIT_RANGE --pretty=format:"%s" --grep="^feat" 2>/dev/null | sed 's/^feat[:(]//' | sed 's/^[^)]*): //' | sed 's/^/- /')
            if [ -n "$FEATS" ]; then
              echo "### 新功能"
              echo "$FEATS"
              echo ""
            fi

            # 提取 fix commits
            FIXES=$(git log $COMMIT_RANGE --pretty=format:"%s" --grep="^fix" 2>/dev/null | sed 's/^fix[:(]//' | sed 's/^[^)]*): //' | sed 's/^/- 🐛 /')
            if [ -n "$FIXES" ]; then
              echo "### 修复"
              echo "$FIXES"
              echo ""
            fi

            # 如果没有 feat 和 fix，显示提示
            if [ -z "$FEATS" ] && [ -z "$FIXES" ]; then
              echo "- 常规更新和优化"
              echo ""
            fi

            echo "---"
            echo ""
            echo "## Download"
            echo ""
            echo "| Platform | File |"
            echo "|-----------------|-------------|"
            echo "| Mac (Apple Silicon) | [ChatLab-${VERSION_NUMBER}-arm64.dmg](https://github.com/hellodigua/ChatLab/releases/download/v${VERSION_NUMBER}/ChatLab-${VERSION_NUMBER}-arm64.dmg) |"
            echo "| Mac (Intel) | [ChatLab-${VERSION_NUMBER}-x64.dmg](https://github.com/hellodigua/ChatLab/releases/download/v${VERSION_NUMBER}/ChatLab-${VERSION_NUMBER}-x64.dmg) |"
            echo "| Windows | [ChatLab-${VERSION_NUMBER}-setup.exe](https://github.com/hellodigua/ChatLab/releases/download/v${VERSION_NUMBER}/ChatLab-${VERSION_NUMBER}-setup.exe) |"
          } > release_notes.md

          echo "Generated release notes:"
          cat release_notes.md

      - name: Create Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ github.event_name == 'workflow_dispatch' && format('v{0}', inputs.version) || github.ref_name }}
          name: ChatLab ${{ github.event_name == 'workflow_dispatch' && inputs.version || github.ref_name }}
          body_path: release_notes.md
          files: |
            dist/*.exe
            dist/*.dmg
            dist/*.zip
            dist/*.yml
            dist/*.blockmap
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      # 同步到 Cloudflare R2（国内镜像）
      # 注意：beta/alpha/rc 等预发布版本不上传到 R2
      - name: Get version for R2 upload
        id: version
        run: |
          if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
            VERSION_TAG="v${{ inputs.version }}"
          else
            VERSION_TAG="${{ github.ref_name }}"
          fi
          echo "tag=$VERSION_TAG" >> $GITHUB_OUTPUT

          # 检查是否为预发布版本（包含 -beta、-alpha、-rc 等）
          if [[ "$VERSION_TAG" =~ -(beta|alpha|rc)\. ]]; then
            echo "is_prerelease=true" >> $GITHUB_OUTPUT
            echo "Detected prerelease version: $VERSION_TAG, will skip R2 upload"
          else
            echo "is_prerelease=false" >> $GITHUB_OUTPUT
            echo "Detected stable version: $VERSION_TAG, will upload to R2"
          fi

      # 上传所有文件到版本目录
      - name: Upload to Cloudflare R2 (version directory)
        if: steps.version.outputs.is_prerelease == 'false'
        uses: ryand56/r2-upload-action@latest
        with:
          r2-account-id: ${{ secrets.R2_ACCOUNT_ID }}
          r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
          r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
          r2-bucket: ${{ secrets.R2_BUCKET_NAME }}
          source-dir: dist
          destination-dir: releases/download/${{ steps.version.outputs.tag }}

      # 准备 yml 文件用于根目录上传
      # 需要修改 yml 中的 path/url 为包含版本号的完整路径
      - name: Prepare yml files for root upload
        if: steps.version.outputs.is_prerelease == 'false'
        run: |
          mkdir -p dist-yml
          VERSION_TAG="${{ steps.version.outputs.tag }}"

          # 处理所有 yml 文件
          for yml_file in dist/*.yml; do
            filename=$(basename "$yml_file")
            echo "Processing $filename..."

            # 使用 sed 修改 path 和 url 字段，添加版本目录前缀
            # path: ChatLab-x.x.x-arm64.dmg → path: vx.x.x/ChatLab-x.x.x-arm64.dmg
            # url: ChatLab-x.x.x-arm64.dmg → url: vx.x.x/ChatLab-x.x.x-arm64.dmg
            sed -E "s|^(path: )(.+)|\1${VERSION_TAG}/\2|g; s|^(  - url: )(.+)|\1${VERSION_TAG}/\2|g" "$yml_file" > "dist-yml/$filename"

            echo "Original:"
            cat "$yml_file"
            echo ""
            echo "Modified:"
            cat "dist-yml/$filename"
            echo "---"
          done

      # 上传 yml 文件到根目录（覆盖旧版本，electron-updater 从这里检测更新）
      - name: Upload yml files to Cloudflare R2 (root directory)
        if: steps.version.outputs.is_prerelease == 'false'
        uses: ryand56/r2-upload-action@latest
        with:
          r2-account-id: ${{ secrets.R2_ACCOUNT_ID }}
          r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
          r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
          r2-bucket: ${{ secrets.R2_BUCKET_NAME }}
          source-dir: dist-yml
          destination-dir: releases/download
