name: OpenWrt Package
on:
  push:
  workflow_dispatch:
    inputs:
      arch:
        description: "Target architecture (leave empty to build all)"
        required: false
        default: ""

env:
  CARGO_TERM_COLOR: always
  PACKAGE_NAME: "fips"

jobs:
  determine-versioning:
    runs-on: ubuntu-latest
    outputs:
      package_version: ${{ steps.version.outputs.package_version }}
      release_channel: ${{ steps.channel.outputs.release_channel }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Derive package version
        id: version
        shell: bash
        run: |
          : ${GITHUB_OUTPUT:=/tmp/github_output}
          if [[ "$GITHUB_REF" == refs/tags/* ]]; then
            echo "package_version=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
          else
            BRANCH=$(echo "$GITHUB_REF_NAME" | sed 's|/|-|g')
            HEIGHT=$(git rev-list --count HEAD)
            HASH=$(git rev-parse --short HEAD)
            echo "package_version=${BRANCH}.${HEIGHT}.${HASH}" >> "$GITHUB_OUTPUT"
          fi

      - name: Determine release channel
        id: channel
        shell: bash
        run: |
          : ${GITHUB_OUTPUT:=/tmp/github_output}
          if [[ "$GITHUB_REF" == refs/tags/* ]]; then
            TAG_NAME=${GITHUB_REF#refs/tags/}
            if [[ $TAG_NAME =~ ^v[0-9]+\.[0-9]+\.[0-9]+-alpha ]]; then
              echo "release_channel=alpha" >> "$GITHUB_OUTPUT"
            elif [[ $TAG_NAME =~ ^v[0-9]+\.[0-9]+\.[0-9]+-beta ]]; then
              echo "release_channel=beta" >> "$GITHUB_OUTPUT"
            elif [[ $TAG_NAME =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
              echo "release_channel=stable" >> "$GITHUB_OUTPUT"
            else
              echo "release_channel=dev" >> "$GITHUB_OUTPUT"
            fi
          else
            echo "release_channel=dev" >> "$GITHUB_OUTPUT"
          fi

  build:
    name: Build .ipk (${{ matrix.openwrt_arch }})
    runs-on: ubuntu-latest
    needs: determine-versioning

    strategy:
      fail-fast: false
      matrix:
        include:
          - build_arch: aarch64
            openwrt_arch: aarch64_cortex-a53
            rust_target: aarch64-unknown-linux-musl
            rust_channel: stable
            # MT3000, MT6000, Flint 2, RPi 3/4/5
          # MIPS disabled: 32-bit MIPS lacks AtomicU64; needs portable-atomic crate
          # - build_arch: mipsel
          #   openwrt_arch: mipsel_24kc
          #   rust_target: mipsel-unknown-linux-musl
          #   rust_channel: nightly
          # - build_arch: mips
          #   openwrt_arch: mips_24kc
          #   rust_target: mips-unknown-linux-musl
          #   rust_channel: nightly
          - build_arch: x86_64
            openwrt_arch: x86_64
            rust_target: x86_64-unknown-linux-musl
            rust_channel: stable
            # x86 routers / VMs

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Set SOURCE_DATE_EPOCH from git
        run: echo "SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)" >> "$GITHUB_ENV"

      - name: Initialize
        run: |
          PACKAGE_FILENAME=${{ env.PACKAGE_NAME }}_${{ needs.determine-versioning.outputs.package_version }}_${{ matrix.openwrt_arch }}.ipk
          echo "PACKAGE_FILENAME=$PACKAGE_FILENAME" >> $GITHUB_ENV

      - name: Install Rust toolchain (stable)
        if: matrix.rust_channel == 'stable'
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.rust_target }}

      - name: Install Rust toolchain (nightly, Tier 3)
        if: matrix.rust_channel == 'nightly'
        uses: dtolnay/rust-toolchain@nightly
        with:
          components: rust-src

      - name: Cache Cargo registry + build
        if: ${{ env.ACT != 'true' }}
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target/${{ matrix.rust_target }}
          key: openwrt-${{ matrix.rust_target }}-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            openwrt-${{ matrix.rust_target }}-

      - name: Install cargo-zigbuild
        run: cargo install cargo-zigbuild --version 0.19.8 --locked

      - name: Install zig (required by cargo-zigbuild)
        run: |
          ZIG_VERSION="0.13.0"
          ARCH=$(uname -m)
          case "$ARCH" in
            x86_64|amd64) ZIG_ARCH="x86_64" ;;
            aarch64|arm64) ZIG_ARCH="aarch64" ;;
            *) echo "Unsupported architecture: $ARCH"; exit 1 ;;
          esac
          curl -fsSL "https://ziglang.org/download/${ZIG_VERSION}/zig-linux-${ZIG_ARCH}-${ZIG_VERSION}.tar.xz" | sudo tar xJ -C /opt
          sudo ln -sf /opt/zig-linux-${ZIG_ARCH}-${ZIG_VERSION}/zig /usr/local/bin/zig
          zig version

      - name: Install llvm-strip
        run: sudo apt-get update && sudo apt-get install -y --no-install-recommends llvm

      - name: Install nak
        shell: bash
        run: |
          NAK_VERSION="0.16.2"
          ARCH=$(uname -m)
          case "$ARCH" in
            x86_64|amd64) NAK_ARCH="amd64" ;;
            aarch64|arm64) NAK_ARCH="arm64" ;;
            *) echo "Unsupported architecture: $ARCH"; exit 1 ;;
          esac
          curl -fsSL "https://github.com/fiatjaf/nak/releases/download/v${NAK_VERSION}/nak-v${NAK_VERSION}-linux-${NAK_ARCH}" \
            -o /usr/local/bin/nak
          chmod +x /usr/local/bin/nak
          nak --version

      - name: Install jq
        run: |
          if ! command -v jq &>/dev/null; then
            sudo apt-get update && sudo apt-get install -y jq
          fi

      # Priority: HIVE_CI_NSEC from env (loom job) > repo secret > generate ephemeral
      - name: Resolve signing key
        id: keys
        shell: bash
        env:
          SECRET_NSEC: ${{ secrets.HIVE_CI_NSEC }}
        run: |
          : ${GITHUB_OUTPUT:=/tmp/github_output}
          if [ -n "${HIVE_CI_NSEC:-}" ]; then
            echo "Using HIVE_CI_NSEC from loom job environment"
            NSEC="$HIVE_CI_NSEC"
          elif [ -n "$SECRET_NSEC" ]; then
            echo "Using HIVE_CI_NSEC from repository secrets"
            NSEC="$SECRET_NSEC"
          else
            echo "No nsec provided -- generating ephemeral keypair"
            NSEC=$(nak key generate)
          fi

          PUBKEY=$(echo "$NSEC" | nak key public)
          echo "::add-mask::$NSEC"
          echo "nsec=$NSEC" >> "$GITHUB_OUTPUT"
          echo "pubkey=$PUBKEY" >> "$GITHUB_OUTPUT"
          echo "Publisher pubkey (hex): $PUBKEY"
      - name: Build .ipk
        env:
          PKG_VERSION: ${{ needs.determine-versioning.outputs.package_version }}
          LLVM_STRIP: llvm-strip
        run: ./packaging/openwrt-ipk/build-ipk.sh --arch ${{ matrix.build_arch }}

      - name: SHA-256 hashes
        run: |
          echo "==> Binaries:"
          sha256sum target/${{ matrix.rust_target }}/release/fips target/${{ matrix.rust_target }}/release/fipsctl target/${{ matrix.rust_target }}/release/fipstop
          echo "==> Package:"
          sha256sum dist/${{ env.PACKAGE_FILENAME }}

      - name: Upload artifact (GitHub only)
        if: ${{ env.ACT != 'true' }}
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.PACKAGE_FILENAME }}
          path: dist/${{ env.PACKAGE_FILENAME }}
          retention-days: 30

      - name: Upload to Blossom
        id: blossom_upload
        shell: bash
        env:
          BLOSSOM_SERVER: "https://blossom.primal.net"
          NSEC: ${{ steps.keys.outputs.nsec }}
        run: |
          : ${GITHUB_OUTPUT:=/tmp/github_output}

          UPLOAD_RESPONSE=$(nak blossom upload \
            --server "$BLOSSOM_SERVER" \
            --sec "$NSEC" \
            "dist/${{ env.PACKAGE_FILENAME }}" < /dev/null)

          echo "Upload response:"
          echo "$UPLOAD_RESPONSE"

          FILE_HASH=$(echo "$UPLOAD_RESPONSE" | jq -r '.sha256')
          if [ -z "$FILE_HASH" ] || [ "$FILE_HASH" = "null" ]; then
            echo "Failed to extract hash from upload response"
            exit 1
          fi

          BLOSSOM_URL="${BLOSSOM_SERVER}/${FILE_HASH}"
          echo "url=$BLOSSOM_URL" >> "$GITHUB_OUTPUT"
          echo "hash=$FILE_HASH" >> "$GITHUB_OUTPUT"
          echo "Uploaded to Blossom: $BLOSSOM_URL"

      - name: Publish NIP-94 release event
        id: publish
        shell: bash
        env:
          RELAYS: "wss://relay.damus.io wss://nos.lol wss://nostr.mom wss://relay.primal.net"
          NSEC: ${{ steps.keys.outputs.nsec }}
        run: |
          : ${GITHUB_OUTPUT:=/tmp/github_output}
          set -e

          VERSION="${{ needs.determine-versioning.outputs.package_version }}"
          CHANNEL="${{ needs.determine-versioning.outputs.release_channel }}"

          nak event --sec "$NSEC" -k 1063 \
            -c "FIPS Package: ${{ env.PACKAGE_NAME }} for ${{ matrix.openwrt_arch }}" \
            --tag url="${{ steps.blossom_upload.outputs.url }}" \
            --tag m="application/octet-stream" \
            --tag x="${{ steps.blossom_upload.outputs.hash }}" \
            --tag ox="${{ steps.blossom_upload.outputs.hash }}" \
            --tag filename="${{ env.PACKAGE_FILENAME }}" \
            --tag A="${{ matrix.openwrt_arch }}" \
            --tag v="$VERSION" \
            --tag n="${{ env.PACKAGE_NAME }}" \
            --tag compression="none" \
            > event.json 2> event.err

          if [ ! -s event.json ]; then
            echo "Failed to create event"
            cat event.err 2>/dev/null || true
            exit 1
          fi

          echo "=== Event JSON ==="
          cat event.json
          echo "=================="

          EVENT_ID=$(jq -r '.id' event.json)
          if [ -z "$EVENT_ID" ] || [ "$EVENT_ID" = "null" ]; then
            echo "Failed to extract event ID"
            exit 1
          fi

          # Publish to relays
          cat event.json | nak event $RELAYS 2>&1

          echo "eventId=$EVENT_ID" >> "$GITHUB_OUTPUT"
          echo "Published NIP-94 event: $EVENT_ID"

      - name: Verify NIP-94 event on relays
        if: ${{ steps.publish.outputs.eventId != '' }}
        env:
          EVENT_ID: ${{ steps.publish.outputs.eventId }}
          RELAYS: "wss://relay.damus.io wss://nos.lol wss://nostr.mom wss://relay.primal.net"
        run: |
          echo "Verifying event $EVENT_ID on relays..."
          FOUND=0
          for relay in $RELAYS; do
            echo "Checking $relay..."
            RESULT=$(nak req -i "$EVENT_ID" "$relay" 2>/dev/null || echo "")
            if [ -n "$RESULT" ]; then
              echo "Found on $relay"
              FOUND=1
            else
              echo "Not found on $relay"
            fi
          done

          if [ $FOUND -eq 0 ]; then
            echo "Warning: Event not found on any relay yet (may still be propagating)"
          else
            echo "Event verified on at least one relay"
          fi

      - name: Build Summary
        run: |
          echo "Build Summary for ${{ matrix.openwrt_arch }}:"
          echo "  Package: ${{ env.PACKAGE_FILENAME }}"
          echo "  Release EventId: ${{ steps.publish.outputs.eventId }}"
          echo "  Blossom URL: ${{ steps.blossom_upload.outputs.url }}"

  release:
    name: Publish GitHub Release (github only)
    runs-on: ubuntu-latest
    needs: build
    if: startsWith(github.ref, 'refs/tags/')
    permissions:
      contents: write

    steps:
      - name: Download all .ipk artifacts
        uses: actions/download-artifact@v4
        with:
          path: dist
          merge-multiple: true

      - name: Create release
        uses: softprops/action-gh-release@v2
        with:
          files: dist/*.ipk
          generate_release_notes: true
