import { describe, expect, it } from "vitest";

import { evaluateWhen, type WhenContext } from "./when";

const allFalse: WhenContext = {
  projectOpen: false,
  gitRepository: false,
  agentSelected: false,
  terminalFocused: false,
  layoutCellFocused: false,
};

describe("evaluateWhen", () => {
  it("treats an absent expression as always true", () => {
    expect(evaluateWhen(undefined, allFalse)).toEqual({ ok: true, value: true });
  });

  it("reads a single variable", () => {
    expect(evaluateWhen("projectOpen", { ...allFalse, projectOpen: true })).toEqual({
      ok: true,
      value: true,
    });
    expect(evaluateWhen("projectOpen", allFalse)).toEqual({ ok: true, value: false });
  });

  it("evaluates &&, ||, ! and parentheses with correct precedence", () => {
    const ctx: WhenContext = { ...allFalse, projectOpen: true, gitRepository: false };
    expect(evaluateWhen("projectOpen && gitRepository", ctx)).toEqual({ ok: true, value: false });
    expect(evaluateWhen("projectOpen || gitRepository", ctx)).toEqual({ ok: true, value: true });
    expect(evaluateWhen("!gitRepository && projectOpen", ctx)).toEqual({ ok: true, value: true });
    expect(evaluateWhen("!(projectOpen && gitRepository)", ctx)).toEqual({ ok: true, value: true });
  });

  it("disables (does not crash) on an unknown variable", () => {
    const result = evaluateWhen("somethingUnknown", allFalse);
    expect(result.ok).toBe(false);
  });

  it("disables (does not crash) on malformed syntax", () => {
    expect(evaluateWhen("projectOpen &&", allFalse).ok).toBe(false);
    expect(evaluateWhen("(projectOpen", allFalse).ok).toBe(false);
    expect(evaluateWhen("projectOpen $ gitRepository", allFalse).ok).toBe(false);
  });
});
