name: 📦🚀 Build Installer - Windows 10

on:
  workflow_dispatch:
    inputs:
      release_type:
        description: "Tagged release testing scenario"
        required: false
        type: choice
        default: ""
        options:
          - ""
          - 9.9.9-b1
          - 9.9.9-rc1
          - 9.9.9
  push:
    paths-ignore:
      - "**.md"
    branches:
      - "long_lived/**"
      - main
      - "release/**"
  release:
    types: [published]
  pull_request:
    paths-ignore:
      - "**.md"
    branches:
      - "**"

concurrency:
  # SHA is added to the end if on `main` to let all main workflows run
  group: ${{ github.ref }}-${{ github.workflow }}-${{ github.event_name }}-${{ (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.ref, 'refs/heads/long_lived/')) && github.sha || '' }}
  cancel-in-progress: true

permissions:
  id-token: write
  contents: write

jobs:
  version:
    uses: ./.github/workflows/reflow-version.yml

  build:
    name: Build EXE
    runs-on: [windows-2019]
    needs:
      - version
    timeout-minutes: 65
    outputs:
      chia-installer-version: ${{ steps.version_number.outputs.CHIA_INSTALLER_VERSION }}
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.10"]

    env:
      CHIA_INSTALLER_VERSION: ${{ needs.version.outputs.chia-installer-version }}
      SETUPTOOLS_SCM_PRETEND_VERSION_FOR_CHIA_BLOCKCHAIN: ${{ needs.version.outputs.chia-installer-version }}
      TAG_TYPE: ${{ needs.version.outputs.tag-type }}

    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
          submodules: recursive

      - name: Set Env
        uses: Chia-Network/actions/setjobenv@main
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - uses: Chia-Network/actions/git-ssh-to-https@main

      - name: Get npm cache directory
        id: npm-cache
        shell: bash
        run: |
          echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT"

      - name: Cache npm
        uses: actions/cache@v4
        with:
          path: ${{ steps.npm-cache.outputs.dir }}
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      - uses: chia-network/actions/cache-pip@main

      - uses: Chia-Network/actions/setup-python@main
        name: Install Python ${{ matrix.python-version }}
        with:
          python-version: ${{ matrix.python-version }}

      - name: Setup Node 18.x
        uses: actions/setup-node@v4
        with:
          node-version: "18.x"

      - name: Test for secrets access
        id: check_secrets
        shell: bash
        run: |
          unset HAS_SIGNING_SECRET

          if [ -n "$SIGNING_SECRET" ]; then HAS_SIGNING_SECRET='true' ; fi
          echo "HAS_SIGNING_SECRET=${HAS_SIGNING_SECRET}" >> "$GITHUB_OUTPUT"
        env:
          SIGNING_SECRET: "${{ secrets.SM_CLIENT_CERT_FILE_B64 }}"

      - name: Setup Certificate
        if: steps.check_secrets.outputs.HAS_SIGNING_SECRET
        shell: bash
        run: |
          echo "${{ secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12

      - name: Set signing variables
        if: steps.check_secrets.outputs.HAS_SIGNING_SECRET
        shell: bash
        run: |
          echo "SM_HOST=${{ secrets.SM_HOST }}" >> "$GITHUB_ENV"
          echo "SM_API_KEY=${{ secrets.SM_API_KEY }}" >> "$GITHUB_ENV"
          echo "SM_CLIENT_CERT_FILE=D:\\Certificate_pkcs12.p12" >> "$GITHUB_ENV"
          echo "SM_CLIENT_CERT_PASSWORD=${{ secrets.SM_CLIENT_CERT_PASSWORD }}" >> "$GITHUB_ENV"
          echo "SM_CODE_SIGNING_CERT_SHA1_HASH=${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }}" >> "$GITHUB_ENV"
          echo "C:\Program Files (x86)\Windows Kits\10\App Certification Kit" >> $GITHUB_PATH
          echo "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools" >> $GITHUB_PATH
          echo "C:\Program Files\DigiCert\DigiCert One Signing Manager Tools" >> $GITHUB_PATH

      - name: Setup SSM KSP on windows latest
        if: steps.check_secrets.outputs.HAS_SIGNING_SECRET
        shell: cmd
        run: |
          curl -X GET https://download.chia.net/dc/smtools-windows-x64.msi -o smtools-windows-x64.msi
          msiexec /i smtools-windows-x64.msi /quiet /qn
          smksp_registrar.exe list
          smctl.exe keypair ls
          C:\Windows\System32\certutil.exe -csp "DigiCert Signing Manager KSP" -key -user
          smksp_cert_sync.exe

      - name: Get latest madmax plotter
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        shell: bash
        run: |
          LATEST_MADMAX=$(gh api repos/Chia-Network/chia-plotter-madmax/releases/latest --jq 'select(.prerelease == false) | .tag_name')
          mkdir "$GITHUB_WORKSPACE"\\madmax
          gh release download -R Chia-Network/chia-plotter-madmax "$LATEST_MADMAX" -p 'chia_plot-*.exe' -O "$GITHUB_WORKSPACE"\\madmax\\chia_plot.exe
          gh release download -R Chia-Network/chia-plotter-madmax "$LATEST_MADMAX" -p 'chia_plot_k34-*.exe' -O "$GITHUB_WORKSPACE"\\madmax\\chia_plot_k34.exe

      - name: Fetch bladebit versions
        shell: bash
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Fetch the latest version of each type
          LATEST_RELEASE=$(gh api repos/Chia-Network/bladebit/releases/latest --jq 'select(.prerelease == false) | .tag_name')
          LATEST_BETA=$(gh api repos/Chia-Network/bladebit/releases --jq 'map(select(.prerelease) | select(.tag_name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+-beta[0-9]+$"))) | first | .tag_name')
          LATEST_RC=$(gh api repos/Chia-Network/bladebit/releases --jq 'map(select(.prerelease) | select(.tag_name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+-rc[0-9]+$"))) | first | .tag_name')

          # Compare the versions and choose the newest that matches the requirements
          if [[ "$TAG_TYPE" == "beta" || -z "$TAG_TYPE" ]]; then
            # For beta or dev builds (indicated by the absence of a tag), use the latest version available
            LATEST_VERSION=$(printf "%s\n%s\n%s\n" "$LATEST_RELEASE" "$LATEST_BETA" "$LATEST_RC" | sed '/-/!s/$/_/' | sort -V | sed 's/_$//' | tail -n 1)
          elif [[ "$TAG_TYPE" == "rc" ]]; then
            # For RC builds, use the latest RC or full release if it's newer
            LATEST_VERSION=$(printf "%s\n%s\n" "$LATEST_RELEASE" "$LATEST_RC" | sed '/-/!s/$/_/' | sort -V | sed 's/_$//' | tail -n 1)
          else
            # For full releases, use the latest full release
            LATEST_VERSION="$LATEST_RELEASE"
          fi
          echo "LATEST_VERSION=$LATEST_VERSION" >> "$GITHUB_ENV"

      - name: Get latest bladebit plotter
        shell: bash
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          # Download and extract the chosen version
          mkdir "$GITHUB_WORKSPACE\\bladebit"
          cd "$GITHUB_WORKSPACE\\bladebit"
          gh release download -R Chia-Network/bladebit "$LATEST_VERSION" -p 'bladebit*windows-x86-64.zip'
          ls *.zip | xargs -I{} bash -c 'unzip {} && rm {}'
          cd "$OLDPWD"

      - uses: ./.github/actions/install
        with:
          python-version: ${{ matrix.python-version }}
          development: true
          constraints-file-artifact-name: constraints-file-intel

      - uses: chia-network/actions/activate-venv@main

      - name: Prepare GUI cache
        id: gui-ref
        shell: bash
        run: |
          gui_ref=$(git submodule status chia-blockchain-gui | sed -e 's/^ //g' -e 's/ chia-blockchain-gui.*$//g')
          echo "${gui_ref}"
          echo "GUI_REF=${gui_ref}" >> "$GITHUB_OUTPUT"
          echo "rm -rf ./chia-blockchain-gui"
          rm -rf ./chia-blockchain-gui

      - name: Cache GUI
        uses: actions/cache@v4
        id: cache-gui
        with:
          path: .\chia-blockchain-gui
          key: ${{ runner.os }}-chia-blockchain-gui-${{ steps.gui-ref.outputs.GUI_REF }}

      - if: steps.cache-gui.outputs.cache-hit != 'true'
        name: Build GUI
        continue-on-error: false
        run: |
          cd .\build_scripts
          .\build_windows-1-gui.ps1

      - name: Build Windows installer
        env:
          HAS_SIGNING_SECRET: ${{ steps.check_secrets.outputs.HAS_SIGNING_SECRET }}
        run: |
          $env:path="C:\Program` Files` (x86)\Microsoft` Visual` Studio\2019\Enterprise\SDK\ScopeCppSDK\vc15\VC\bin\;$env:path"
          $env:path="C:\Program` Files` (x86)\Windows` Kits\10\App` Certification` Kit;$env:path"
          cd .\build_scripts
          .\build_windows-2-installer.ps1

      - name: Upload Installer to artifacts
        uses: actions/upload-artifact@v4
        with:
          name: chia-installers-windows-exe-intel
          path: chia-blockchain-gui\release-builds\windows-installer\

      - name: Remove Windows exe and installer to exclude from cache
        run: |
          Remove-Item .\chia-blockchain-gui\packages\gui\dist -Recurse -Force
          Remove-Item .\chia-blockchain-gui\packages\gui\daemon -Recurse -Force
          Remove-Item .\chia-blockchain-gui\Chia-win32-x64 -Recurse -Force
          Remove-Item .\chia-blockchain-gui\release-builds -Recurse -Force

  publish:
    name: 📦 Publish Installers
    uses: ./.github/workflows/reflow-publish-installer.yml
    with:
      concurrency-name: windows
      chia-installer-version: ${{ needs.version.outputs.chia-installer-version }}
      chia-dev-version: ${{ needs.version.outputs.chia-dev-version }}
      configuration: ${{ toJSON( matrix.configuration ) }}
    secrets: inherit
    needs:
      - version
      - build
    strategy:
      fail-fast: false
      matrix:
        configuration:
          - python-version: ["3.10"]
            os:
              - matrix: windows
                file-type:
                  name: EXE
                  extension: exe
                glue-name: windows
                artifact-platform-name: windows
                file-arch-name:
                  intel: intel
                file-suffix:
                  arm: ""
                  intel: ""
                names:
                  gui:
                    file: ChiaSetup-{0}.exe
                    dev-file: ChiaSetup-{1}.exe
                    latest-dev-file: ChiaSetup-latest-dev.exe
            mode:
              - name: GUI
                matrix: gui
                glue-name: gui
              - name: CLI
                matrix: cli
                glue-name: cli
            arch:
              - name: ARM64
                matrix: arm
                artifact-name: arm
                glue-name: arm
              - name: Intel
                matrix: intel
                artifact-name: intel
                glue-name: intel
            exclude:
              - os:
                  matrix: windows
                arch:
                  matrix: arm
              - os:
                  matrix: windows
                mode:
                  matrix: cli

  test:
    name: Test ${{ matrix.os.name }}
    runs-on: ${{ matrix.os.runs-on[matrix.arch.matrix] }}
    needs:
      - version
      - build
    strategy:
      fail-fast: false
      matrix:
        os:
          - name: 2019
            matrix: 2019
            runs-on:
              intel: windows-2019
          - name: 2022
            matrix: 2022
            runs-on:
              intel: windows-2022
        arch:
          - name: Intel
            matrix: intel

    env:
      INSTALL_PATH: installed/

    steps:
      - uses: Chia-Network/actions/clean-workspace@main

      - name: Download packages
        uses: actions/download-artifact@v4
        with:
          name: chia-installers-windows-exe-intel
          path: packages

      - name: Install package
        run: |
          dir ./packages/
          $env:INSTALLER_PATH = (Get-ChildItem packages/ChiaSetup-*.exe)
          # note that the installer requires the target path use backslashes
          $env:RESOLVED_INSTALL_PATH = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($env:INSTALL_PATH)
          Start-Process -Wait -FilePath $env:INSTALLER_PATH -ArgumentList "/S", ("/D=" + $env:RESOLVED_INSTALL_PATH)
          echo ======================================
          dir ./
          echo ======================================
          dir ./installed/

      - name: List installed files
        run: |
          Get-ChildItem -Recurse $env:INSTALL_PATH | Select FullName

      - name: List all files
        if:
        run: |
          Get-ChildItem -Recurse $env:INSTALL_PATH | Select FullName

      - name: Run chia dev installers test
        run: |
          & ($env:INSTALL_PATH + "/resources/app.asar.unpacked/daemon/chia.exe") dev installers test --expected-chia-version "${{ needs.version.outputs.chia-installer-version }}"
