import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { test } from "bun:test";
import { createApp } from "vue";
import { createPinia, setActivePinia } from "pinia";
import { PiniaColada, useQueryCache } from "@pinia/colada";

import { createWorkbenchServerState, type WorkbenchServerState } from "./workbench-server-state";
import { workbenchColadaKeys } from "./workbench-colada-keys";
import { useWorkbenchColadaReducer } from "./workbench-colada-reducer";

const storeDir = path.dirname(fileURLToPath(import.meta.url));

function installColadaContext(): ReturnType<typeof createApp> {
  const app = createApp({});
  const pinia = createPinia();
  app.use(pinia);
  app.use(PiniaColada, {});
  setActivePinia(pinia);
  return app;
}

test("workbench colada keys keep serializable hierarchical cache scopes", () => {
  assert.deepEqual(workbenchColadaKeys.sessions({ limit: 50, includeSessionId: "ses_colada", cursor: "cur_2" }), ["workbench", "snapshot", "sessions", { cursor: "cur_2", includeSessionId: "ses_colada", limit: 50 }]);
  assert.deepEqual(workbenchColadaKeys.sessionMessages("ses_colada", { limit: 20 }), ["workbench", "history", "session-messages", "ses_colada", { cursor: null, limit: 20 }]);
  assert.deepEqual(workbenchColadaKeys.traceEvents("trc_colada", { afterProjectedSeq: 4, limit: 25 }), ["workbench", "detail", "trace-events", "trc_colada", { afterProjectedSeq: 4, limit: 25 }]);
});

test("workbench colada reducer stores projection state in the query cache", () => {
  const app = installColadaContext();
  app.runWithContext(() => {
    const reducer = useWorkbenchColadaReducer();
    const queryCache = useQueryCache();
    const key = workbenchColadaKeys.serverState();

    assert.deepEqual(reducer.readServerState(), createWorkbenchServerState());

    reducer.reduceServerState({ type: "session.detail", session: { sessionId: "ses_colada", status: "running", messages: [] } });
    const cached = queryCache.getQueryData<WorkbenchServerState>(key);

    assert.equal(cached?.sessionsById.ses_colada?.sessionId, "ses_colada");
    assert.equal(reducer.serverState.value.sessionsById.ses_colada?.sessionId, "ses_colada");
  });
});

test("workbench colada read path preserves freshness governance", () => {
  const source = fs.readFileSync(path.join(storeDir, "workbench-colada-queries.ts"), "utf8");
  assert.match(source, /const state = await queryCache\.refresh\(entry\);/u);
  assert.doesNotMatch(source, /queryCache\.fetch\(entry/u);
});

test("workbench colada has no automatic HTTP live repair query scope", () => {
  const querySource = fs.readFileSync(path.join(storeDir, "workbench-colada-queries.ts"), "utf8");
  const mutationSource = fs.readFileSync(path.join(storeDir, "workbench-colada-mutations.ts"), "utf8");
  const storeSource = fs.readFileSync(path.join(storeDir, "workbench.ts"), "utf8");

  assert.doesNotMatch(querySource, /fetchSyncReplay|syncReplay|\/v1\/workbench\/sync/u);
  assert.doesNotMatch(storeSource, /fetchSyncReplay|refreshWorkbenchSyncReplay|\/v1\/workbench\/sync/u);

  assert.doesNotMatch(mutationSource, /workbenchColadaKeys\.syncRoot\(\)/u);
  assert.match(mutationSource, /workbenchColadaKeys\.snapshotRoot\(\)/u);
  assert.match(mutationSource, /workbenchColadaKeys\.historySessionMessagesRoot\(\)/u);
  assert.match(mutationSource, /workbenchColadaKeys\.detailRoot\(\)/u);
  assert.doesNotMatch(mutationSource, /workbenchColadaKeys\.traceEventsRoot\(\)\.concat/u);
});
