name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Install V
        run: |
          git clone --depth 1 https://github.com/vlang/v /tmp/v
          cd /tmp/v && make
          sudo ln -sf /tmp/v/v /usr/local/bin/v
          v version

      - name: Build toolchain
        run: v -o bin/vr .

      - name: Smoke test — compile and run hello.vr
        run: ./bin/vr run examples/hello.vr

      - name: Smoke test — compile and run fib.vr
        run: ./bin/vr run examples/fib.vr

      - name: Smoke test — compile and run structs.vr
        run: ./bin/vr run examples/structs.vr

      - name: Smoke test — compile and run match.vr
        run: ./bin/vr run examples/match.vr

      - name: Smoke test — compile and run arrays.vr
        run: ./bin/vr run examples/arrays.vr

      - name: Smoke test — assemble, link, and run math.vasm
        run: |
          ./bin/vr assemble examples/math.vasm -o /tmp/math.vobj
          ./bin/vr link /tmp/math.vobj -o /tmp/math.vbin
          ./bin/vr run /tmp/math.vbin

      - name: Smoke test — multi-file compile + link
        run: |
          ./bin/vr compile examples/lib.vr -o /tmp/lib.vobj
          ./bin/vr compile examples/use_lib.vr -o /tmp/use_lib.vobj
          ./bin/vr link /tmp/lib.vobj /tmp/use_lib.vobj -o /tmp/use_lib.vbin
          ./bin/vr run /tmp/use_lib.vbin

      - name: Run test suite
        # test_failing is intentionally skipped — it asserts 1 == 2 on purpose.
        # The test runner exits 1 if any test_* fails, so we run every .vr file
        # that does NOT contain a test_failing function.  examples/tests.vr has
        # test_failing, so we compile a clean copy without it.
        run: |
          grep -n 'fn test_failing' examples/tests.vr || true
          sed '/fn test_failing/,/^}/d' examples/tests.vr > /tmp/ci_tests.vr
          ./bin/vr test /tmp/ci_tests.vr

      - name: Run stdlib test suite
        run: |
          ./bin/vr test examples/stdlib.vr

      - name: LSP smoke test
        run: |
          BODY='{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
          printf 'Content-Length: %d\r\n\r\n%s' "${#BODY}" "$BODY" | ./bin/vr lsp | grep -q '"id":1' && echo "LSP responded"

      - name: Watch-mode and directory-test smoke
        run: |
          ./bin/vr test examples | grep -q 'passed'

      - name: Debugger smoke — breakpoint, locals, backtrace, continue
        run: |
          printf 'fn main() {\n\tlet x = 10\n\tlet y = x + 5\n\tprintln(y)\n}\n' > /tmp/dbg_smoke.vr
          printf 'b 2\nc\nl\np x\nbt\nc\n' | ./bin/vr debug /tmp/dbg_smoke.vr | grep -q 'x = 0'

      - name: Profiler smoke — per-function instruction counts
        run: |
          printf 'fn fib(n) {\n\tif n < 2 {\n\t\treturn n\n\t}\n\treturn fib(n - 1) + fib(n - 2)\n}\nfn main() {\n\tprintln(fib(10))\n}\n' > /tmp/prof_smoke.vr
          ./bin/vr profile /tmp/prof_smoke.vr | grep -q 'fib'

      - name: Fuzzer smoke — short run must finish clean
        run: |
          ./bin/vr fuzz --seed 1 --iters 25 --max-ops 50000 --save-dir /tmp/fuzz_repros | grep -q 'no bugs found'
