/**
 * 04 – Force-push simulation and backup verification.
 *
 * This is the critical test that proves data loss can happen from a
 * force-push on the source repo, and verifies that the backup system
 * (when enabled) preserves the old state.
 *
 * Scenario:
 *   1. Confirm my-project is already mirrored with known commits / content
 *   2. Record the pre-force-push state (branch SHAs, commit messages, file content)
 *   3. Rewrite history in the source bare repo (simulate a force-push)
 *   4. Trigger Gitea mirror-sync WITHOUT backup
 *   5. Verify Gitea now reflects the rewritten history — old commits are GONE
 *   6. Restore the source repo, re-mirror, then enable backup
 *   7. Force-push again and sync WITH backup enabled
 *   8. Verify backup activity was recorded (snapshot attempted before sync)
 *
 * The source bare repos live on the host filesystem at
 * tests/e2e/git-repos/<owner>/<name>.git and are served read-only into the
 * git-server container. Because the bind-mount is :ro in docker-compose,
 * we modify the repos on the host and Gitea's dumb-HTTP clone picks up
 * the changes on the next fetch.
 *
 * Prerequisites: 02-mirror-workflow.spec.ts must have run first so that
 * my-project is already mirrored into Gitea.
 */

import { execSync } from "node:child_process";
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import { join, resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { test, expect } from "@playwright/test";
import {
  APP_URL,
  GITEA_URL,
  GITEA_MIRROR_ORG,
  GiteaAPI,
  getAppSessionCookies,
  saveConfig,
  waitFor,
  getRepositoryIds,
  triggerSyncRepo,
} from "./helpers";

// ─── Paths ───────────────────────────────────────────────────────────────────

const E2E_DIR = resolve(dirname(fileURLToPath(import.meta.url)));
const GIT_REPOS_DIR = join(E2E_DIR, "git-repos");
const MY_PROJECT_BARE = join(GIT_REPOS_DIR, "e2e-test-user", "my-project.git");

// ─── Git helpers ─────────────────────────────────────────────────────────────

/** Run a git command in a given directory. */
function git(args: string, cwd: string): string {
  try {
    return execSync(`git ${args}`, {
      cwd,
      encoding: "utf-8",
      stdio: ["pipe", "pipe", "pipe"],
      env: {
        ...process.env,
        GIT_AUTHOR_NAME: "Force Push Bot",
        GIT_AUTHOR_EMAIL: "force-push@test.local",
        GIT_COMMITTER_NAME: "Force Push Bot",
        GIT_COMMITTER_EMAIL: "force-push@test.local",
      },
    }).trim();
  } catch (err: any) {
    const stderr = err.stderr?.toString() ?? "";
    const stdout = err.stdout?.toString() ?? "";
    throw new Error(
      `git ${args} failed in ${cwd}:\n${stderr || stdout || err.message}`,
    );
  }
}

/**
 * Get the SHA of a ref in a bare repository.
 * Uses `git rev-parse` so it works for branches and tags.
 */
function getRefSha(bareRepo: string, ref: string): string {
  return git(`rev-parse ${ref}`, bareRepo);
}

/**
 * Clone the bare repo to a temporary working copy, execute a callback that
 * mutates the working copy, then force-push back to the bare repo and
 * update server-info for dumb-HTTP serving.
 */
function mutateSourceRepo(
  bareRepo: string,
  tmpName: string,
  mutate: (workDir: string) => void,
): void {
  const tmpDir = join(GIT_REPOS_DIR, ".work-force-push", tmpName);
  rmSync(tmpDir, { recursive: true, force: true });
  mkdirSync(join(GIT_REPOS_DIR, ".work-force-push"), { recursive: true });

  try {
    // Clone from the bare repo
    git(`clone "${bareRepo}" "${tmpDir}"`, GIT_REPOS_DIR);
    git("config user.name 'Force Push Bot'", tmpDir);
    git("config user.email 'force-push@test.local'", tmpDir);

    // Let the caller rewrite history
    mutate(tmpDir);

    // Force-push all refs back to the bare repo
    git(`push --force --all "${bareRepo}"`, tmpDir);
    git(`push --force --tags "${bareRepo}"`, tmpDir);

    // Update server-info so the dumb-HTTP server picks up the new refs
    git("update-server-info", bareRepo);
  } finally {
    rmSync(tmpDir, { recursive: true, force: true });
  }
}

/** Helper to clean up the temporary working directory. */
function cleanupWorkDir(): void {
  const workDir = join(GIT_REPOS_DIR, ".work-force-push");
  rmSync(workDir, { recursive: true, force: true });
}

// ─── Tests ───────────────────────────────────────────────────────────────────

test.describe("E2E: Force-push simulation", () => {
  let giteaApi: GiteaAPI;
  let appCookies = "";

  /** SHA of the main branch BEFORE we force-push. */
  let originalMainSha = "";
  /** The commit message of the HEAD commit before force-push. */
  let originalHeadMessage = "";
  /** Content of README.md before force-push. */
  let originalReadmeContent = "";
  /** Number of commits on main before force-push. */
  let originalCommitCount = 0;

  test.beforeAll(async () => {
    giteaApi = new GiteaAPI(GITEA_URL);
    try {
      await giteaApi.createToken();
    } catch {
      console.log("[ForcePush] Could not create Gitea token");
    }
  });

  test.afterAll(async () => {
    cleanupWorkDir();
    await giteaApi.dispose();
  });

  // ── F0: Preconditions ────────────────────────────────────────────────────

  test("F0: Confirm my-project is mirrored and record its state", async ({
    request,
  }) => {
    // Verify the source bare repo exists on the host
    expect(
      existsSync(MY_PROJECT_BARE),
      `Bare repo should exist at ${MY_PROJECT_BARE}`,
    ).toBeTruthy();

    // Verify it is mirrored in Gitea
    const repo = await giteaApi.getRepo(GITEA_MIRROR_ORG, "my-project");
    expect(repo, "my-project should exist in Gitea").toBeTruthy();
    console.log(
      `[ForcePush] my-project in Gitea: mirror=${repo.mirror}, ` +
        `default_branch=${repo.default_branch}`,
    );

    // Record the current state of main in Gitea
    const mainBranch = await giteaApi.getBranch(
      GITEA_MIRROR_ORG,
      "my-project",
      "main",
    );
    expect(mainBranch, "main branch should exist").toBeTruthy();
    originalMainSha = mainBranch.commit.id;
    originalHeadMessage =
      mainBranch.commit.message?.trim() ?? "(unknown message)";
    console.log(
      `[ForcePush] Original main HEAD: ${originalMainSha.substring(0, 12)} ` +
        `"${originalHeadMessage}"`,
    );

    // Record commit count
    const commits = await giteaApi.listCommits(GITEA_MIRROR_ORG, "my-project", {
      limit: 50,
    });
    originalCommitCount = commits.length;
    console.log(
      `[ForcePush] Original commit count on main: ${originalCommitCount}`,
    );

    // Record README content
    const readme = await giteaApi.getFileContent(
      GITEA_MIRROR_ORG,
      "my-project",
      "README.md",
    );
    originalReadmeContent = readme ?? "";
    expect(originalReadmeContent).toContain("My Project");
    console.log(
      `[ForcePush] Original README length: ${originalReadmeContent.length} chars`,
    );

    // Also verify the source bare repo matches
    const sourceSha = getRefSha(MY_PROJECT_BARE, "refs/heads/main");
    console.log(
      `[ForcePush] Source bare main SHA: ${sourceSha.substring(0, 12)}`,
    );
    // They may differ slightly if Gitea hasn't synced the very latest, but
    // the important thing is that both exist.
  });

  // ── F1: Rewrite history on the source repo ───────────────────────────────

  test("F1: Force-push rewritten history to source repo", async () => {
    const shaBeforeRewrite = getRefSha(MY_PROJECT_BARE, "refs/heads/main");
    console.log(
      `[ForcePush] Source main before rewrite: ${shaBeforeRewrite.substring(0, 12)}`,
    );

    mutateSourceRepo(MY_PROJECT_BARE, "my-project-rewrite", (workDir) => {
      // We're on the main branch.
      // Rewrite history: remove the last commit (the LICENSE commit) via
      // reset --hard HEAD~1, then add a completely different commit.
      git("checkout main", workDir);

      // Record what HEAD is for logging
      const headBefore = git("log --oneline -1", workDir);
      console.log(`[ForcePush] Working copy HEAD before reset: ${headBefore}`);

      // Hard reset to remove the last commit (this drops "Add MIT license")
      git("reset --hard HEAD~1", workDir);

      const headAfterReset = git("log --oneline -1", workDir);
      console.log(`[ForcePush] After reset HEAD~1: ${headAfterReset}`);

      // Write a replacement commit with different content (simulates someone
      // rewriting history with different changes)
      writeFileSync(
        join(workDir, "README.md"),
        "# My Project\n\nThis README was FORCE-PUSHED.\n\nOriginal history has been rewritten.\n",
      );
      writeFileSync(
        join(workDir, "FORCE_PUSH_MARKER.txt"),
        `Force-pushed at ${new Date().toISOString()}\n`,
      );
      git("add -A", workDir);

      execSync('git commit -m "FORCE PUSH: Rewritten history"', {
        cwd: workDir,
        encoding: "utf-8",
        stdio: ["pipe", "pipe", "pipe"],
        env: {
          ...process.env,
          GIT_AUTHOR_NAME: "Force Push Bot",
          GIT_AUTHOR_EMAIL: "force-push@test.local",
          GIT_AUTHOR_DATE: "2024-06-15T12:00:00+00:00",
          GIT_COMMITTER_NAME: "Force Push Bot",
          GIT_COMMITTER_EMAIL: "force-push@test.local",
          GIT_COMMITTER_DATE: "2024-06-15T12:00:00+00:00",
        },
      });

      const headAfterRewrite = git("log --oneline -3", workDir);
      console.log(`[ForcePush] After rewrite (last 3):\n${headAfterRewrite}`);
    });

    const shaAfterRewrite = getRefSha(MY_PROJECT_BARE, "refs/heads/main");
    console.log(
      `[ForcePush] Source main after rewrite: ${shaAfterRewrite.substring(0, 12)}`,
    );

    // The SHA must have changed — this proves the force-push happened
    expect(
      shaAfterRewrite,
      "Source repo main SHA should change after force-push",
    ).not.toBe(originalMainSha);

    // Verify the old SHA is no longer reachable on main
    const logOutput = git("log --oneline main", MY_PROJECT_BARE);
    expect(
      logOutput,
      "Rewritten history should NOT contain the old head commit",
    ).toContain("FORCE PUSH");
  });

  // ── F2: Sync to Gitea WITHOUT backup ─────────────────────────────────────

  test("F2: Disable backup and sync force-pushed repo to Gitea", async ({
    request,
  }) => {
    appCookies = await getAppSessionCookies(request);

    const giteaToken = giteaApi.getTokenValue();
    expect(giteaToken).toBeTruthy();

    // Ensure backup is disabled for this test
    await saveConfig(request, giteaToken, appCookies, {
      giteaConfig: {
        backupStrategy: "disabled",
        blockSyncOnBackupFailure: false,
      },
    });
    console.log("[ForcePush] Backup disabled for unprotected sync test");

    // Trigger Gitea's mirror-sync directly via the Gitea API.
    // This is more reliable than going through the app for this test because
    // the app's sync-repo endpoint involves extra processing. We want to test
    // the raw effect of Gitea pulling the rewritten refs.
    const synced = await giteaApi.triggerMirrorSync(
      GITEA_MIRROR_ORG,
      "my-project",
    );
    console.log(`[ForcePush] Gitea mirror-sync triggered: ${synced}`);

    // Wait for Gitea to pull the new refs from the git-server
    console.log("[ForcePush] Waiting for Gitea to pull rewritten refs...");
    await new Promise((r) => setTimeout(r, 15_000));
  });

  // ── F3: Verify Gitea reflects the rewritten history ──────────────────────

  test("F3: Verify Gitea has the force-pushed content (old history GONE)", async () => {
    // Poll until Gitea picks up the new HEAD
    await waitFor(
      async () => {
        const branch = await giteaApi.getBranch(
          GITEA_MIRROR_ORG,
          "my-project",
          "main",
        );
        if (!branch) return false;
        return branch.commit.id !== originalMainSha;
      },
      {
        timeout: 60_000,
        interval: 5_000,
        label: "Gitea main branch updates to new SHA",
      },
    );

    // Read the new state
    const newMainBranch = await giteaApi.getBranch(
      GITEA_MIRROR_ORG,
      "my-project",
      "main",
    );
    expect(newMainBranch).toBeTruthy();
    const newSha = newMainBranch.commit.id;
    const newMsg = newMainBranch.commit.message?.trim() ?? "";
    console.log(
      `[ForcePush] New main HEAD: ${newSha.substring(0, 12)} "${newMsg}"`,
    );

    // The SHA MUST be different from the original
    expect(
      newSha,
      "Gitea main SHA should have changed after force-push sync",
    ).not.toBe(originalMainSha);

    // The new commit message should be the force-pushed one
    expect(newMsg).toContain("FORCE PUSH");

    // Verify the force-push marker file now exists in Gitea
    const markerContent = await giteaApi.getFileContent(
      GITEA_MIRROR_ORG,
      "my-project",
      "FORCE_PUSH_MARKER.txt",
    );
    expect(
      markerContent,
      "FORCE_PUSH_MARKER.txt should appear after sync",
    ).toBeTruthy();
    console.log(
      `[ForcePush] Marker file present: ${markerContent?.substring(0, 40)}...`,
    );

    // Verify the README was overwritten
    const newReadme = await giteaApi.getFileContent(
      GITEA_MIRROR_ORG,
      "my-project",
      "README.md",
    );
    expect(newReadme).toContain("FORCE-PUSHED");
    expect(newReadme).not.toBe(originalReadmeContent);
    console.log("[ForcePush] README.md confirms overwritten content");

    // Verify the LICENSE file is GONE (it was in the dropped commit)
    const licenseContent = await giteaApi.getFileContent(
      GITEA_MIRROR_ORG,
      "my-project",
      "LICENSE",
    );
    expect(
      licenseContent,
      "LICENSE should be GONE after force-push removed that commit",
    ).toBeNull();
    console.log("[ForcePush] ✗ LICENSE file is GONE — data loss confirmed");

    // Verify the old commit SHA is no longer accessible
    const oldCommit = await giteaApi.getCommit(
      GITEA_MIRROR_ORG,
      "my-project",
      originalMainSha,
    );
    // Gitea may or may not GC the unreachable commit immediately, so this
    // is informational rather than a hard assertion.
    if (oldCommit) {
      console.log(
        `[ForcePush] Old commit ${originalMainSha.substring(0, 12)} is ` +
          `still in Gitea's object store (not yet GC'd)`,
      );
    } else {
      console.log(
        `[ForcePush] Old commit ${originalMainSha.substring(0, 12)} is ` +
          `no longer accessible — data loss complete`,
      );
    }

    // Check commit count changed
    const newCommits = await giteaApi.listCommits(
      GITEA_MIRROR_ORG,
      "my-project",
      { limit: 50 },
    );
    console.log(
      `[ForcePush] Commit count: was ${originalCommitCount}, now ${newCommits.length}`,
    );
    // The rewrite dropped one commit and added one, so the count should differ
    // or at minimum the commit list should not contain the old head message.
    const commitMessages = newCommits.map(
      (c: any) => c.commit?.message?.trim() ?? "",
    );
    expect(
      commitMessages.some((m: string) => m.includes("FORCE PUSH")),
      "New commit list should contain the force-pushed commit",
    ).toBeTruthy();

    console.log(
      "\n[ForcePush] ════════════════════════════════════════════════════",
    );
    console.log(
      "[ForcePush]  CONFIRMED: Force-push without backup = DATA LOSS",
    );
    console.log(
      "[ForcePush]  The LICENSE file and original HEAD commit are gone.",
    );
    console.log(
      "[ForcePush] ════════════════════════════════════════════════════\n",
    );
  });

  // ── F4: Restore source, re-mirror, then test WITH backup ─────────────────

  test("F4: Restore source repo to a good state and re-mirror", async ({
    request,
  }) => {
    // To test the backup path we need a clean slate. Re-create the original
    // my-project content in the source repo so it has known good history.
    mutateSourceRepo(MY_PROJECT_BARE, "my-project-restore", (workDir) => {
      git("checkout main", workDir);

      // Remove the force-push marker
      try {
        execSync("rm -f FORCE_PUSH_MARKER.txt", { cwd: workDir });
      } catch {
        // may not exist
      }

      // Restore README
      writeFileSync(
        join(workDir, "README.md"),
        "# My Project\n\nA sample project for E2E testing.\n\n" +
          "## Features\n- Greeting module\n- Math utilities\n",
      );

      // Restore LICENSE
      writeFileSync(
        join(workDir, "LICENSE"),
        "MIT License\n\nCopyright (c) 2024 E2E Test\n",
      );

      git("add -A", workDir);
      execSync(
        'git commit -m "Restore original content after force-push test"',
        {
          cwd: workDir,
          encoding: "utf-8",
          stdio: ["pipe", "pipe", "pipe"],
          env: {
            ...process.env,
            GIT_AUTHOR_NAME: "E2E Test Bot",
            GIT_AUTHOR_EMAIL: "e2e-bot@test.local",
            GIT_COMMITTER_NAME: "E2E Test Bot",
            GIT_COMMITTER_EMAIL: "e2e-bot@test.local",
          },
        },
      );

      const newHead = git("log --oneline -1", workDir);
      console.log(`[ForcePush] Restored source HEAD: ${newHead}`);
    });

    // Sync Gitea to pick up the restored state
    const synced = await giteaApi.triggerMirrorSync(
      GITEA_MIRROR_ORG,
      "my-project",
    );
    console.log(`[ForcePush] Gitea mirror-sync for restore: ${synced}`);
    await new Promise((r) => setTimeout(r, 15_000));

    // Verify Gitea has the restored content
    await waitFor(
      async () => {
        const readme = await giteaApi.getFileContent(
          GITEA_MIRROR_ORG,
          "my-project",
          "README.md",
        );
        return readme !== null && readme.includes("Features");
      },
      {
        timeout: 60_000,
        interval: 5_000,
        label: "Gitea picks up restored content",
      },
    );

    const license = await giteaApi.getFileContent(
      GITEA_MIRROR_ORG,
      "my-project",
      "LICENSE",
    );
    expect(license, "LICENSE should be restored").toBeTruthy();
    console.log("[ForcePush] Gitea restored to good state");

    // Record the new "good" SHA for the next force-push test
    const restoredBranch = await giteaApi.getBranch(
      GITEA_MIRROR_ORG,
      "my-project",
      "main",
    );
    originalMainSha = restoredBranch.commit.id;
    console.log(
      `[ForcePush] Restored main SHA: ${originalMainSha.substring(0, 12)}`,
    );
  });

  // ── F5: Force-push AGAIN, this time with backup enabled ──────────────────

  test("F5: Enable backup, force-push, and sync", async ({ request }) => {
    if (!appCookies) {
      appCookies = await getAppSessionCookies(request);
    }

    const giteaToken = giteaApi.getTokenValue();

    // Enable backup with "always" strategy
    await saveConfig(request, giteaToken, appCookies, {
      giteaConfig: {
        backupStrategy: "always",
        blockSyncOnBackupFailure: false, // don't block — we want to see both backup + sync happen
        backupRetentionCount: 5,
        backupDirectory: "data/repo-backups",
      },
    });
    console.log("[ForcePush] Backup enabled (strategy=always) for protected sync test");

    // Force-push again
    mutateSourceRepo(MY_PROJECT_BARE, "my-project-rewrite2", (workDir) => {
      git("checkout main", workDir);

      writeFileSync(
        join(workDir, "README.md"),
        "# My Project\n\nSECOND FORCE-PUSH — backup should have preserved old state.\n",
      );
      writeFileSync(
        join(workDir, "SECOND_FORCE_PUSH.txt"),
        `Second force-push at ${new Date().toISOString()}\n`,
      );
      // Remove LICENSE again to simulate destructive rewrite
      try {
        execSync("rm -f LICENSE", { cwd: workDir });
      } catch {
        // may not exist
      }
      git("add -A", workDir);
      execSync('git commit -m "SECOND FORCE PUSH: backup should catch this"', {
        cwd: workDir,
        encoding: "utf-8",
        stdio: ["pipe", "pipe", "pipe"],
        env: {
          ...process.env,
          GIT_AUTHOR_NAME: "Force Push Bot",
          GIT_AUTHOR_EMAIL: "force-push@test.local",
          GIT_COMMITTER_NAME: "Force Push Bot",
          GIT_COMMITTER_EMAIL: "force-push@test.local",
        },
      });
    });

    console.log("[ForcePush] Second force-push applied to source repo");

    // Use the app's sync-repo to trigger the sync (this goes through
    // syncGiteaRepoEnhanced which runs the backup code path)
    const { ids: repoIds } = await getRepositoryIds(request, appCookies);
    // Find the my-project repo ID
    const dashResp = await request.get(`${APP_URL}/api/dashboard`, {
      headers: { Cookie: appCookies },
      failOnStatusCode: false,
    });
    let myProjectId = "";
    if (dashResp.ok()) {
      const data = await dashResp.json();
      const repos: any[] = data.repositories ?? [];
      const myProj = repos.find((r: any) => r.name === "my-project");
      if (myProj) myProjectId = myProj.id;
    }

    if (myProjectId) {
      console.log(
        `[ForcePush] Triggering app sync-repo for my-project (${myProjectId})`,
      );
      const status = await triggerSyncRepo(
        request,
        appCookies,
        [myProjectId],
        25_000,
      );
      console.log(`[ForcePush] App sync-repo response: ${status}`);
    } else {
      // Fallback: trigger via Gitea API directly
      console.log(
        "[ForcePush] Could not find my-project ID, using Gitea API directly",
      );
      await giteaApi.triggerMirrorSync(GITEA_MIRROR_ORG, "my-project");
      await new Promise((r) => setTimeout(r, 15_000));
    }
  });

  // ── F6: Verify Gitea picked up the second force-push ─────────────────────

  test("F6: Verify Gitea reflects second force-push", async () => {
    await waitFor(
      async () => {
        const branch = await giteaApi.getBranch(
          GITEA_MIRROR_ORG,
          "my-project",
          "main",
        );
        if (!branch) return false;
        return branch.commit.id !== originalMainSha;
      },
      {
        timeout: 60_000,
        interval: 5_000,
        label: "Gitea main branch updates after second force-push",
      },
    );

    const newBranch = await giteaApi.getBranch(
      GITEA_MIRROR_ORG,
      "my-project",
      "main",
    );
    const newSha = newBranch.commit.id;
    console.log(
      `[ForcePush] After 2nd force-push: main=${newSha.substring(0, 12)}, ` +
        `msg="${newBranch.commit.message?.trim()}"`,
    );
    expect(newSha).not.toBe(originalMainSha);

    // Verify the second force-push marker
    const marker = await giteaApi.getFileContent(
      GITEA_MIRROR_ORG,
      "my-project",
      "SECOND_FORCE_PUSH.txt",
    );
    expect(marker, "Second force-push marker should exist").toBeTruthy();

    // LICENSE should be gone again
    const license = await giteaApi.getFileContent(
      GITEA_MIRROR_ORG,
      "my-project",
      "LICENSE",
    );
    expect(license, "LICENSE gone again after 2nd force-push").toBeNull();
    console.log("[ForcePush] Second force-push verified in Gitea");
  });

  // ── F7: Verify backup activity was logged for the second force-push ──────

  test("F7: Verify backup activity was recorded for protected sync", async ({
    request,
  }) => {
    if (!appCookies) {
      appCookies = await getAppSessionCookies(request);
    }

    const activitiesResp = await request.get(`${APP_URL}/api/activities`, {
      headers: { Cookie: appCookies },
      failOnStatusCode: false,
    });

    if (!activitiesResp.ok()) {
      console.log(
        `[ForcePush] Could not fetch activities: ${activitiesResp.status()}`,
      );
      return;
    }

    const activities = await activitiesResp.json();
    const jobs: any[] = Array.isArray(activities)
      ? activities
      : (activities.jobs ?? activities.activities ?? []);

    // Filter to backup/snapshot entries for my-project
    const backupJobs = jobs.filter(
      (j: any) =>
        (j.repositoryName === "my-project" ||
          j.repositoryName === "my-project") &&
        (j.message?.toLowerCase().includes("snapshot") ||
          j.message?.toLowerCase().includes("backup") ||
          j.details?.toLowerCase().includes("snapshot") ||
          j.details?.toLowerCase().includes("backup") ||
          j.details?.toLowerCase().includes("bundle")),
    );

    console.log(
      `[ForcePush] Backup activity for my-project: ${backupJobs.length} entries`,
    );
    for (const j of backupJobs) {
      console.log(
        `[ForcePush]   • [${j.status}] ${j.message ?? ""} | ${(j.details ?? "").substring(0, 100)}`,
      );
    }

    // The backup system should have been invoked and must succeed.
    expect(
      backupJobs.length,
      "At least one backup/snapshot activity should exist for my-project " +
        "when backupStrategy is 'always'",
    ).toBeGreaterThan(0);

    // Check whether any backups actually succeeded
    const successfulBackups = backupJobs.filter(
      (j: any) =>
        j.status === "syncing" ||
        j.message?.includes("Snapshot created") ||
        j.details?.includes("Pre-sync snapshot created"),
    );
    const failedBackups = backupJobs.filter(
      (j: any) =>
        j.status === "failed" &&
        (j.message?.includes("Snapshot failed") ||
          j.details?.includes("snapshot failed")),
    );

    if (successfulBackups.length > 0) {
      console.log(
        `[ForcePush] ✓ ${successfulBackups.length} backup(s) SUCCEEDED — ` +
          `old state was preserved in bundle`,
      );
    }
    if (failedBackups.length > 0) {
      console.log(
        `[ForcePush] ⚠ ${failedBackups.length} backup(s) FAILED`,
      );
      // Extract and log the first failure reason for visibility
      const firstFailure = failedBackups[0];
      console.log(
        `[ForcePush]   Failure reason: ${firstFailure.details?.substring(0, 200)}`,
      );
    }

    console.log(
      "[ForcePush] ════════════════════════════════════════════════════",
    );
    if (successfulBackups.length > 0) {
      console.log(
        "[ForcePush]  RESULT: Backup system PROTECTED against force-push",
      );
    } else {
      console.log("[ForcePush]  RESULT: Backup system was INVOKED but FAILED.");
    }
    console.log(
      "[ForcePush] ════════════════════════════════════════════════════\n",
    );

    // Fail the test if any backups failed
    expect(
      failedBackups.length,
      `Expected all backups to succeed, but ${failedBackups.length} backup(s) failed. ` +
        `First failure: ${failedBackups[0]?.details || "unknown error"}`,
    ).toBe(0);
  });

  // ── F8: Restore source repo for subsequent test suites ───────────────────

  test("F8: Restore source repo to clean state for other tests", async () => {
    mutateSourceRepo(MY_PROJECT_BARE, "my-project-final-restore", (workDir) => {
      git("checkout main", workDir);

      // Remove force-push artifacts
      try {
        execSync("rm -f FORCE_PUSH_MARKER.txt SECOND_FORCE_PUSH.txt", {
          cwd: workDir,
        });
      } catch {
        // ignore
      }

      // Restore content
      writeFileSync(
        join(workDir, "README.md"),
        "# My Project\n\nA sample project for E2E testing.\n\n" +
          "## Features\n- Greeting module\n- Math utilities\n",
      );
      writeFileSync(
        join(workDir, "LICENSE"),
        "MIT License\n\nCopyright (c) 2024 E2E Test\n",
      );
      git("add -A", workDir);
      execSync(
        'git commit --allow-empty -m "Final restore after force-push tests"',
        {
          cwd: workDir,
          encoding: "utf-8",
          stdio: ["pipe", "pipe", "pipe"],
          env: {
            ...process.env,
            GIT_AUTHOR_NAME: "E2E Test Bot",
            GIT_AUTHOR_EMAIL: "e2e-bot@test.local",
            GIT_COMMITTER_NAME: "E2E Test Bot",
            GIT_COMMITTER_EMAIL: "e2e-bot@test.local",
          },
        },
      );
    });

    // Sync Gitea
    await giteaApi.triggerMirrorSync(GITEA_MIRROR_ORG, "my-project");
    await new Promise((r) => setTimeout(r, 10_000));

    // Verify restoration
    const license = await giteaApi.getFileContent(
      GITEA_MIRROR_ORG,
      "my-project",
      "LICENSE",
    );
    if (license) {
      console.log("[ForcePush] Source repo restored for subsequent tests");
    } else {
      console.log(
        "[ForcePush] Warning: restoration may not have synced yet (Gitea async)",
      );
    }
  });
});
