name: Set state to is_deleted in pocketbase

on:
  push:
    branches:
      - main
    paths:
      - "json/**"
      - "vm/**"
      - "tools/**"
      - "turnkey/**"
      - "ct/**"
      - "install/**"

jobs:
  delete-pocketbase-entry:
    runs-on: self-hosted
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Get slugs from deleted JSON and script files
        id: slugs
        run: |
          BEFORE="${{ github.event.before }}"
          AFTER="${{ github.event.after }}"
          slugs=""

          # Deleted JSON files: get slug from previous commit
          deleted_json=$(git diff --name-only --diff-filter=D "$BEFORE" "$AFTER" -- json/ | grep '\.json$' || true)
          for f in $deleted_json; do
            [[ -z "$f" ]] && continue
            s=$(git show "$BEFORE:$f" 2>/dev/null | jq -r '.slug // empty' 2>/dev/null || true)
            [[ -n "$s" ]] && slugs="$slugs $s"
          done

          # Deleted script files: derive slug from path
          deleted_sh=$(git diff --name-only --diff-filter=D "$BEFORE" "$AFTER" -- ct/ install/ tools/ turnkey/ vm/ | grep '\.sh$' || true)
          for f in $deleted_sh; do
            [[ -z "$f" ]] && continue
            base="${f##*/}"
            base="${base%.sh}"
            if [[ "$f" == install/* && "$base" == *-install ]]; then
              s="${base%-install}"
            else
              s="$base"
            fi
            [[ -n "$s" ]] && slugs="$slugs $s"
          done

          slugs=$(echo $slugs | xargs -n1 | sort -u | tr '\n' ' ')
          if [[ -z "$slugs" ]]; then
            echo "No deleted JSON or script files to mark as deleted in PocketBase."
            echo "count=0" >> "$GITHUB_OUTPUT"
            exit 0
          fi
          echo "$slugs" > slugs_to_delete.txt
          echo "count=$(echo $slugs | wc -w)" >> "$GITHUB_OUTPUT"
          echo "Slugs to mark as deleted: $slugs"

      - name: Mark as deleted in PocketBase
        if: steps.slugs.outputs.count != '0'
        env:
          POCKETBASE_URL: ${{ secrets.POCKETBASE_URL }}
          POCKETBASE_COLLECTION: ${{ secrets.POCKETBASE_COLLECTION }}
          POCKETBASE_ADMIN_EMAIL: ${{ secrets.POCKETBASE_ADMIN_EMAIL }}
          POCKETBASE_ADMIN_PASSWORD: ${{ secrets.POCKETBASE_ADMIN_PASSWORD }}
        run: |
          node << 'ENDSCRIPT'
          (async function() {
            const fs = require('fs');
            const https = require('https');
            const http = require('http');
            const url = require('url');

            function request(fullUrl, opts, redirectCount) {
              redirectCount = redirectCount || 0;
              return new Promise(function(resolve, reject) {
                const u = url.parse(fullUrl);
                const isHttps = u.protocol === 'https:';
                const body = opts.body;
                const options = {
                  hostname: u.hostname,
                  port: u.port || (isHttps ? 443 : 80),
                  path: u.path,
                  method: opts.method || 'GET',
                  headers: opts.headers || {}
                };
                if (body) options.headers['Content-Length'] = Buffer.byteLength(body);
                const lib = isHttps ? https : http;
                const req = lib.request(options, function(res) {
                  if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
                    if (redirectCount >= 5) return reject(new Error('Too many redirects from ' + fullUrl));
                    const redirectUrl = url.resolve(fullUrl, res.headers.location);
                    res.resume();
                    resolve(request(redirectUrl, opts, redirectCount + 1));
                    return;
                  }
                  let data = '';
                  res.on('data', function(chunk) { data += chunk; });
                  res.on('end', function() {
                    resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, statusCode: res.statusCode, body: data });
                  });
                });
                req.on('error', reject);
                if (body) req.write(body);
                req.end();
              });
            }

            const raw = process.env.POCKETBASE_URL.replace(/\/$/, '');
            const apiBase = /\/api$/i.test(raw) ? raw : raw + '/api';
            const coll = process.env.POCKETBASE_COLLECTION;
            const slugs = fs.readFileSync('slugs_to_delete.txt', 'utf8').trim().split(/\s+/).filter(Boolean);

            const authUrl = apiBase + '/collections/users/auth-with-password';
            const authBody = JSON.stringify({
              identity: process.env.POCKETBASE_ADMIN_EMAIL,
              password: process.env.POCKETBASE_ADMIN_PASSWORD
            });
            const authRes = await request(authUrl, {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: authBody
            });
            if (!authRes.ok) {
              throw new Error('Auth failed. Response: ' + authRes.body);
            }
            const token = JSON.parse(authRes.body).token;
            const recordsUrl = apiBase + '/collections/' + encodeURIComponent(coll) + '/records';

            const patchBody = JSON.stringify({ is_deleted: true });

            for (const slug of slugs) {
              const filter = "(slug='" + slug + "')";
              const listRes = await request(recordsUrl + '?filter=' + encodeURIComponent(filter) + '&perPage=1', {
                headers: { 'Authorization': token }
              });
              const list = JSON.parse(listRes.body);
              const existingId = list.items && list.items[0] && list.items[0].id;
              if (!existingId) {
                console.log('No PocketBase record for slug "' + slug + '", skipping.');
                continue;
              }
              const patchRes = await request(recordsUrl + '/' + existingId, {
                method: 'PATCH',
                headers: { 'Authorization': token, 'Content-Type': 'application/json' },
                body: patchBody
              });
              if (patchRes.ok) {
                console.log('Set is_deleted=true for slug "' + slug + '" (id=' + existingId + ').');
              } else {
                console.warn('PATCH failed for slug "' + slug + '": ' + patchRes.statusCode + ' ' + patchRes.body);
              }
            }
            console.log('Done.');
          })().catch(e => { console.error(e); process.exit(1); });
          ENDSCRIPT
        shell: bash
