import test from "node:test";
import assert from "node:assert/strict";
import { mkdtemp, readFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { createAccountTokenUsageStore } from "./account-token-usage-store.js";

test("token usage snapshots survive account removal and same-identity reconnection", async () => {
  const dir = await mkdtemp(join(tmpdir(), "account-token-usage-"));
  try {
    const first = createAccountTokenUsageStore(dir);
    await first.record("old-account", {
      dailyUsageBuckets: [{ startDate: "2026-07-16", tokens: 1200 }],
      summary: { lifetimeTokens: 1200 }
    }, new Date("2026-07-16T12:00:00.000Z"));
    await first.detach("old-account", "person@example.com");

    const restored = createAccountTokenUsageStore(dir);
    await restored.attach("new-account", "PERSON@example.com");

    assert.deepEqual(await restored.read("new-account"), {
      dailyUsageBuckets: [{ startDate: "2026-07-16", tokens: 1200 }],
      summary: {
        lifetimeTokens: 1200,
        peakDailyTokens: null,
        currentStreakDays: null,
        longestStreakDays: null,
        longestRunningTurnSec: null
      }
    });
    const persisted = await readFile(join(dir, "account-token-usage.json"), "utf8");
    assert.doesNotMatch(persisted, /person@example\.com|codexHome|auth\.json/i);
  } finally {
    await rm(dir, { recursive: true, force: true });
  }
});

test("token usage recording keeps graph buckets monotonic across an empty refresh", async () => {
  const store = createAccountTokenUsageStore("");
  await store.record("a", {
    dailyUsageBuckets: [
      { startDate: "2026-07-15", tokens: 900 },
      { startDate: "2026-07-16", tokens: 1200 }
    ],
    summary: { lifetimeTokens: 2100, peakDailyTokens: 1200 }
  });

  const merged = await store.record("a", {
    dailyUsageBuckets: [{ startDate: "2026-07-16", tokens: 0 }],
    summary: { lifetimeTokens: 0, peakDailyTokens: 0 }
  });

  assert.deepEqual(merged.dailyUsageBuckets, [
    { startDate: "2026-07-15", tokens: 900 },
    { startDate: "2026-07-16", tokens: 1200 }
  ]);
  assert.equal(merged.summary.lifetimeTokens, 2100);
  assert.equal(merged.summary.peakDailyTokens, 1200);
});

test("token usage keeps configured account IDs isolated", async () => {
  const store = createAccountTokenUsageStore("");
  await store.record("account-a", {
    dailyUsageBuckets: [{ startDate: "2026-07-16", tokens: 1200 }]
  });
  await store.record("account-b", {
    dailyUsageBuckets: [{ startDate: "2026-07-16", tokens: 300 }]
  });

  assert.equal((await store.read("account-a")).dailyUsageBuckets[0].tokens, 1200);
  assert.equal((await store.read("account-b")).dailyUsageBuckets[0].tokens, 300);
});

test("token usage store rejects unsafe account ids and ignores unsafe response fields", async () => {
  const store = createAccountTokenUsageStore("");
  await assert.rejects(store.record("../outside", { dailyUsageBuckets: [], summary: {} }), /invalid_account_id/);

  const usage = await store.record("safe", {
    dailyUsageBuckets: [
      { startDate: "2026-07-16", tokens: 42, secret: "hidden" },
      { startDate: "invalid", tokens: 10 }
    ],
    summary: { lifetimeTokens: 42, secret: "hidden" },
    secret: "hidden"
  });

  assert.deepEqual(usage.dailyUsageBuckets, [{ startDate: "2026-07-16", tokens: 42 }]);
  assert.equal(JSON.stringify(usage).includes("hidden"), false);
});
