name: CI

on:
  push:
    branches:
      - main
      - Dev
      - 'feat/**'
  pull_request:
  workflow_dispatch:
    inputs:
      renderer_repo:
        description: 'Renderer repo (owner/name). Empty = vars.RENDERER_REPO or upstream default.'
        required: false
        default: ''
      renderer_ref:
        description: 'Renderer git ref. Empty = vars.RENDERER_REF or auto (main on client main, else Dev).'
        required: false
        default: ''

# Opt into the Node.js 24 runtime for the JavaScript actions
# (actions/checkout, actions/setup-node, …). Node 20 will be removed
# from GitHub-hosted runners in September 2026; this env var asks the
# runner to use Node 24 today so the workflow logs stop warning about
# it on every run.
env:
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
  # Upstream renderer used as the fallback when nothing else is
  # configured. Override per-fork via the RENDERER_REPO / RENDERER_REF
  # repository variables (Settings → Secrets and variables → Actions →
  # Variables) or, for one-off runs, via the workflow_dispatch inputs.
  UPSTREAM_RENDERER_REPO: 'duckietm/Nitro_Render_V3'

jobs:
  check:
    name: Type check + tests
    runs-on: ubuntu-latest
    steps:
      # The build/dev/typecheck setup expects the Nitro renderer SDK to
      # live as a sibling of this repo (see CLAUDE.md → Setup walkthrough).
      # Mirror that here by checking the client into <workspace>/Nitro-V3
      # and the renderer into <workspace>/Nitro_Render_V3.
      - name: Checkout Nitro-V3
        uses: actions/checkout@v4
        with:
          path: Nitro-V3

      # Resolve the renderer pairing with a clear precedence, from most
      # specific to most generic — no fork names or feature branches are
      # hardcoded in this workflow:
      #
      #   1. workflow_dispatch inputs (renderer_repo / renderer_ref)
      #        → explicit manual override, wins outright.
      #   2. repository variables (vars.RENDERER_REPO / vars.RENDERER_REF)
      #        → per-fork config set under Settings → Variables, applies
      #          to push and pull_request runs without editing this file.
      #   3. upstream default
      #        → UPSTREAM_RENDERER_REPO, ref `main` when the client build
      #          context is `main`, otherwise `Dev`.
      #
      # The two repos must stay wire-aligned (composer/parser
      # signatures); pairing the client with a stale renderer is what
      # produced the "Expected 14-15 arguments, but got 16" failure on
      # the catalog edit composer. When a feature touches both repos,
      # point RENDERER_REPO/RENDERER_REF (or the dispatch inputs) at the
      # companion renderer branch.
      - name: Resolve renderer ref
        id: renderer
        env:
          IN_REPO: ${{ github.event.inputs.renderer_repo }}
          IN_REF:  ${{ github.event.inputs.renderer_ref }}
          VAR_REPO: ${{ vars.RENDERER_REPO }}
          VAR_REF:  ${{ vars.RENDERER_REF }}
        run: |
          REPO="${{ github.event.inputs.renderer_repo }}"
          REF="${{ github.event.inputs.renderer_ref }}"

          if [ -z "$REPO" ] || [ -z "$REF" ]; then
            # For PRs we usually pair against the base ref, but the HK
            # PR specifically needs to pair against its OWN head ref —
            # the renderer companion PR is named identically
            # (`feat/housekeeping-packets`) and lives on the same fork.
            case "${GITHUB_EVENT_NAME}" in
              pull_request)
                if [ "${GITHUB_HEAD_REF}" = "feat/housekeeping-panel" ]; then
                  CTX="${GITHUB_HEAD_REF}"
                else
                  CTX="${GITHUB_BASE_REF}"
                fi
                ;;
              *)
                CTX="${GITHUB_REF_NAME}"
                ;;
            esac

            case "$CTX" in
              main)
                AUTO_REPO="duckietm/Nitro_Render_V3"
                AUTO_REF="main"
                ;;
              Dev)
                # The client `Dev` branch carries the custom features
                # (rare values, fortune wheel, soundboard); they live on
                # the matching renderer fork branch, not upstream.
                AUTO_REPO="medievalshell/Nitro_Render_V3"
                AUTO_REF="dev"
                ;;
              feat/housekeeping-panel)
                AUTO_REPO="simoleo89/Nitro_Render_V3"
                AUTO_REF="feat/housekeeping-packets"
                ;;
              *)
                AUTO_REPO="duckietm/Nitro_Render_V3"
                AUTO_REF="Dev"
                ;;
            esac

            [ -z "$REPO" ] && REPO="$AUTO_REPO"
            [ -z "$REF" ]  && REF="$AUTO_REF"
          fi

          # Precedence: dispatch input → repo variable → upstream default.
          REPO="$IN_REPO"
          [ -z "$REPO" ] && REPO="$VAR_REPO"
          [ -z "$REPO" ] && REPO="$UPSTREAM_RENDERER_REPO"

          REF="$IN_REF"
          [ -z "$REF" ] && REF="$VAR_REF"
          [ -z "$REF" ] && REF="$DEFAULT_REF"

          echo "repo=$REPO" >> "$GITHUB_OUTPUT"
          echo "ref=$REF"   >> "$GITHUB_OUTPUT"
          echo "Resolved renderer pairing: $REPO @ $REF (client ctx: $CTX, event: ${GITHUB_EVENT_NAME})"

      - name: Checkout Nitro_Render_V3 (sibling)
        uses: actions/checkout@v4
        with:
          repository: ${{ steps.renderer.outputs.repo }}
          ref: ${{ steps.renderer.outputs.ref }}
          path: Nitro_Render_V3

      - name: Setup Node 22
        uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: yarn
          cache-dependency-path: |
            Nitro-V3/yarn.lock
            Nitro_Render_V3/yarn.lock

      - name: Install renderer SDK deps
        working-directory: Nitro_Render_V3
        run: yarn install --frozen-lockfile

      - name: Install client deps
        working-directory: Nitro-V3
        run: yarn install --frozen-lockfile

      # The renderer SDK is consumed via a filesystem symlink in
      # node_modules/@nitrots/nitro-renderer; create it AFTER yarn
      # install (otherwise yarn would clean it up since the package
      # isn't declared in package.json). tsgo (TS 7 native preview)
      # then resolves the tsconfig `include` entry pointing at the
      # renderer's `src/**/*.ts`.
      #
      # Use an absolute path so the link target is unambiguous
      # regardless of the cwd that reads it. A relative target like
      # `../../../Nitro_Render_V3` resolves to
      # `Nitro-V3/Nitro_Render_V3` (one too few `..`), which doesn't
      # exist and makes tsgo report TS2307 across the entire src/.
      - name: Symlink renderer into client node_modules
        run: |
          mkdir -p Nitro-V3/node_modules/@nitrots
          ln -sfn "${{ github.workspace }}/Nitro_Render_V3" Nitro-V3/node_modules/@nitrots/nitro-renderer
          ls -la Nitro-V3/node_modules/@nitrots/
          ls Nitro-V3/node_modules/@nitrots/nitro-renderer/packages/api/src/ | head -5

      - name: Type check (tsgo)
        working-directory: Nitro-V3
        run: yarn typecheck

      # Hook-order lint gate — the full yarn eslint emits ~900 pre-existing
      # baseline errors (brace style, indentation), so we use a focused
      # config that asserts only react-hooks/rules-of-hooks. Catches the
      # "hook below early-return" pattern that produced two production
      # crashes this session (CatalogPurchaseWidgetView, CatalogItemGridWidgetView).
      - name: ESLint (hook-order gate)
        working-directory: Nitro-V3
        run: yarn lint:hooks

      - name: Vitest
        working-directory: Nitro-V3
        run: yarn test --run
