import test from "node:test";
import assert from "node:assert/strict";
import { initialChangesState, reduceChangesState } from "./changes-state.js";

test("new session clears files and diff", () => {
  const state = reduceChangesState({ files: [{ path: "a" }], selectedDiff: { path: "a" }, available: true }, { type: "session.changed" });
  assert.deepEqual(state, initialChangesState);
});

test("loaded files clear old diff", () => {
  const files = [{ path: "b" }];
  const state = reduceChangesState({ ...initialChangesState, selectedDiff: { path: "old" } }, { type: "files.loaded", files, available: false });
  assert.equal(state.files, files);
  assert.equal(state.available, false);
  assert.equal(state.selectedDiff, null);
});

test("file list failure preserves files and selected diff", () => {
  const current = {
    files: [{ path: "kept.js" }],
    selectedDiff: { path: "kept.js", lines: [] },
    available: true,
    pending: "files",
    error: ""
  };
  const state = reduceChangesState(current, { type: "files.failed" });

  assert.equal(state.files, current.files);
  assert.equal(state.selectedDiff, current.selectedDiff);
  assert.equal(state.pending, "");
  assert.equal(state.error, "changes_list_failed");
});

test("diff failure preserves files and previous selected diff", () => {
  const current = {
    files: [{ path: "kept.js" }],
    selectedDiff: { path: "kept.js", lines: [] },
    available: true,
    pending: "diff",
    error: ""
  };
  const state = reduceChangesState(current, { type: "diff.failed" });

  assert.equal(state.files, current.files);
  assert.equal(state.selectedDiff, current.selectedDiff);
  assert.equal(state.pending, "");
  assert.equal(state.error, "changes_diff_failed");
});

test("loaded patch diffs replace the loading state", () => {
  const diffs = [{ path: "a.js", lines: [] }, { path: "b.js", error: "changes_diff_failed", lines: [] }];
  const loading = reduceChangesState(initialChangesState, { type: "diffs.started" });
  const loaded = reduceChangesState(loading, { type: "diffs.loaded", diffs });

  assert.equal(loading.pending, "diffs");
  assert.equal(loaded.selectedDiffs, diffs);
  assert.equal(loaded.pending, "");
});

test("completed patch diffs become visible while the remaining files are loading", () => {
  const loading = reduceChangesState(initialChangesState, { type: "diffs.started" });
  const first = reduceChangesState(loading, { type: "diffs.itemLoaded", diff: { path: "fast.js", lines: [] } });
  const second = reduceChangesState(first, { type: "diffs.itemLoaded", diff: { path: "slow.js", lines: [] } });

  assert.deepEqual(second.selectedDiffs.map((diff) => diff.path), ["fast.js", "slow.js"]);
  assert.equal(second.pending, "diffs");
});
