name: Build & Release

on:
  push:
    tags:
      - 'v*'           # Full release (npm + Electron)
      - 'npm-v*'       # npm only
      - 'electron-v*'  # Electron only
  workflow_dispatch:
    inputs:
      publish_npm:
        description: 'Publish to npm'
        required: true
        type: boolean
        default: false
      npm_version:
        description: 'npm version override (leave empty to use server/package.json)'
        required: false
        type: string
      build_electron:
        description: 'Build Electron installer & GitHub Release'
        required: true
        type: boolean
        default: false
      electron_version:
        description: 'Electron version override (leave empty to use package.json)'
        required: false
        type: string

jobs:
  # ── Determine what to build ────────────────────────────────
  prepare:
    runs-on: ubuntu-latest
    outputs:
      do_npm: ${{ steps.resolve.outputs.do_npm }}
      do_electron: ${{ steps.resolve.outputs.do_electron }}
      npm_version: ${{ steps.resolve.outputs.npm_version }}
      electron_version: ${{ steps.resolve.outputs.electron_version }}
    steps:
      - uses: actions/checkout@v5

      - id: resolve
        shell: bash
        run: |
          if [[ "${{ github.event_name }}" == "push" ]]; then
            TAG="${GITHUB_REF_NAME}"
            if [[ "$TAG" == npm-v* ]]; then
              echo "do_npm=true" >> $GITHUB_OUTPUT
              echo "do_electron=false" >> $GITHUB_OUTPUT
              echo "npm_version=${TAG#npm-v}" >> $GITHUB_OUTPUT
            elif [[ "$TAG" == electron-v* ]]; then
              echo "do_npm=false" >> $GITHUB_OUTPUT
              echo "do_electron=true" >> $GITHUB_OUTPUT
              echo "electron_version=${TAG#electron-v}" >> $GITHUB_OUTPUT
            else
              echo "do_npm=true" >> $GITHUB_OUTPUT
              echo "do_electron=true" >> $GITHUB_OUTPUT
              echo "npm_version=$(node -p "require('./server/package.json').version")" >> $GITHUB_OUTPUT
              echo "electron_version=${TAG#v}" >> $GITHUB_OUTPUT
            fi
          else
            echo "do_npm=${{ inputs.publish_npm }}" >> $GITHUB_OUTPUT
            echo "do_electron=${{ inputs.build_electron }}" >> $GITHUB_OUTPUT

            if [[ -n "${{ inputs.npm_version }}" ]]; then
              echo "npm_version=${{ inputs.npm_version }}" >> $GITHUB_OUTPUT
            else
              echo "npm_version=$(node -p "require('./server/package.json').version")" >> $GITHUB_OUTPUT
            fi

            if [[ -n "${{ inputs.electron_version }}" ]]; then
              echo "electron_version=${{ inputs.electron_version }}" >> $GITHUB_OUTPUT
            else
              echo "electron_version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
            fi
          fi

  # ── Publish to npm (Trusted Publisher via OIDC) ────────────
  publish-npm:
    needs: prepare
    if: needs.prepare.outputs.do_npm == 'true'
    runs-on: ubuntu-latest
    environment: npm-publish
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v5

      - uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: npm
          registry-url: https://registry.npmjs.org

      - run: npm ci

      - name: Lint
        run: npm run lint

      - name: Test
        run: npm test

      - name: Build server
        run: npm run build -w server

      - name: Publish to npm
        working-directory: server
        run: |
          npm version "${{ needs.prepare.outputs.npm_version }}" --no-git-tag-version --allow-same-version
          npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

  # ── Build Electron + GitHub Release ────────────────────────
  publish-electron:
    needs: prepare
    if: needs.prepare.outputs.do_electron == 'true'
    runs-on: windows-latest
    permissions:
      contents: write
    env:
      ELECTRON_CACHE: ${{ github.workspace }}/.cache/electron
      ELECTRON_BUILDER_CACHE: ${{ github.workspace }}/.cache/electron-builder
    steps:
      - uses: actions/checkout@v5

      - uses: actions/setup-node@v6
        with:
          node-version: 22
          cache: npm

      # Cache Electron binary (~90MB, avoids re-download each build)
      - name: Cache Electron binary
        uses: actions/cache@v5
        with:
          path: ${{ github.workspace }}/.cache/electron
          key: electron-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
          restore-keys: |
            electron-${{ runner.os }}-

      # Cache electron-builder tools (NSIS, nsis-resources, etc.)
      - name: Cache electron-builder tools
        uses: actions/cache@v5
        with:
          path: ${{ github.workspace }}/.cache/electron-builder
          key: electron-builder-${{ runner.os }}-${{ hashFiles('electron-builder.yml') }}
          restore-keys: |
            electron-builder-${{ runner.os }}-

      - run: npm ci

      - name: Lint
        run: npm run lint

      - name: Test
        run: npm test

      - name: Build application
        run: |
          npm run build
          npx tsc -p electron/tsconfig.json

      - name: Sync Electron version
        shell: bash
        run: npm version "${{ needs.prepare.outputs.electron_version }}" --no-git-tag-version --allow-same-version

      - name: Package Electron app
        run: npx electron-builder --win --publish never
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract changelog
        id: changelog
        shell: bash
        run: |
          VERSION="${{ needs.prepare.outputs.electron_version }}"
          # Extract the section for this version from CHANGELOG.md
          BODY=$(awk "/^## \\[${VERSION}\\]/{found=1; next} /^## \\[/{if(found) exit} found{print}" CHANGELOG.md)
          if [ -z "$BODY" ]; then
            BODY="Release v${VERSION}"
          fi
          # Write to file to avoid escaping issues
          echo "$BODY" > release_body.md

      - name: Determine release tag
        id: release_tag
        shell: bash
        run: |
          # Use the original push tag if available (v* for full release),
          # otherwise fall back to electron-v* prefix
          if [[ "${{ github.ref_name }}" == v* ]]; then
            echo "tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT
          else
            echo "tag=electron-v${{ needs.prepare.outputs.electron_version }}" >> $GITHUB_OUTPUT
          fi

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ steps.release_tag.outputs.tag }}
          name: ChatCrystal v${{ needs.prepare.outputs.electron_version }}
          body_path: release_body.md
          draft: false
          prerelease: ${{ contains(needs.prepare.outputs.electron_version, '-') }}
          files: |
            release/*.exe
            release/*.yml
            release/*.yaml
