name: Performance and size

on:
  push:
    branches: [main]
  workflow_dispatch:

env:
  CARGO_TERM_COLOR: always

jobs:
  run-benchmarks:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/
            ~/.cargo/registry/index/
            ~/.cargo/registry/cache/
            ~/.cargo/git/db/
            target/
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

      - uses: brndnmtthws/rust-action-cargo-binstall@v1
        with:
          packages: hyperfine

      - name: Build Ezno
        run: cargo build --release
        env:
          CARGO_PROFILE_RELEASE_DEBUG: true

      - name: Run checker performance
        shell: bash
        run: |
          # Generate a file which contains everything that Ezno currently implements  
          cargo run -p ezno-parser --example code_blocks_to_script ./checker/specification/specification.md --comment-headers --out ./demo.tsx

          echo "### Checking
          \`\`\`shell
          $(hyperfine -i './target/release/ezno check demo.tsx')
          \`\`\`" >> $GITHUB_STEP_SUMMARY

          echo "<details>
          <summary>Input</summary>

          > Code generated from specification.md. this is not meant to accurately represent a program but instead give an idea for how it scales across all the type checking features
          \`\`\`tsx
          $(cat ./demo.tsx)
          \`\`\`
          </details>
          " >> $GITHUB_STEP_SUMMARY

          echo "::info::Wrote code to summary"
          
          command_output=$(./target/release/ezno check demo.tsx --timings --max-diagnostics all 2>&1 || true)
          diagnostics=""; statistics=""; found_splitter=false;

          while IFS= read -r line; do
              if [[ "$line" == "---"* ]]; then found_splitter=true;
              elif [[ "$found_splitter"  == false ]]; then diagnostics+="$line"$'\n';
              else statistics+="$line"$'\n'; fi
          done <<< "$command_output"

          echo "<details>
          <summary>Diagnostics</summary>

          \`\`\`
          $diagnostics
          \`\`\`
          </details>

          <details>
          <summary>Statistics</summary>

          \`\`\`
          $statistics
          \`\`\`
          </details>
          " >> $GITHUB_STEP_SUMMARY

      - name: Run checker performance w/staging
        shell: bash
        if: github.ref_name != 'main'
        run: |
          echo "::group::Running all"
          
          cat ./checker/specification/specification.md ./checker/specification/staging.md > all.md
          cargo run -p ezno-parser --example code_blocks_to_script all.md --comment-headers --out ./all.tsx

          ./target/release/ezno check all.tsx --timings || true
          hyperfine -i './target/release/ezno check all.tsx'
          echo "::endgroup::"
            
      - name: Run checker performance on large file
        shell: bash
        run: |
          echo "::group::Running large"

          cat ./checker/specification/specification.md > main.md
          cargo run -p ezno-parser --example code_blocks_to_script main.md --comment-headers --out ./code.tsx

          for i in {1..10}; do
            cat ./code.tsx >> large.tsx
          done

          ./target/release/ezno check large.tsx --timings --max-diagnostics 0 || true
           hyperfine -i './target/release/ezno check large.tsx'
          echo "::endgroup::"

      - name: Run parsing & stringing (minfied) benchmarks
        shell: bash
        run: |
          strings=(
            "https://esm.sh/v128/react-dom@18.2.0/es2022/react-dom.mjs"
          )
          # Currently broken "https://esm.sh/v135/typescript@5.3.3/es2022/typescript.mjs"

          for url in "${strings[@]}"; do
              curl -sS $url > input.js
              echo "--- debug: $url ---"
              cargo run -p ezno-parser --example parse input.js --timings --render-timings
              echo "--- release: $url ---"
              cargo run -p ezno-parser --release --example parse input.js --timings --render-timings

              hyperfine "./target/debug/examples/parse input.js" "./target/release/examples/parse input.js"
          done
