/**
 * Shared test fixture for `MycoRequestContext` — used to build `RouteRequest`
 * mocks that satisfy D5's strictness gate in `projectScopeFromRequestContext`.
 *
 * Production middleware always sets `requestContext` on every `RouteRequest`,
 * so D5 hardened the contract to throw on missing context. Test fixtures that
 * historically relied on the silent `{kind:'all'}` fallthrough must now thread
 * a real `MycoRequestContext` through. Use `TEST_REQUEST_CONTEXT` (a static
 * Grove-bound default) for handler tests; use `makeTestRequestContext` to
 * build a custom one with overrides.
 *
 * Tests that DO want to exercise cross-project / admin-style reads should
 * pass `ALL_PROJECTS_SCOPE` to the query helper directly rather than building
 * a context-less request. The strict throw exists precisely to make that
 * choice explicit.
 */

import { resolveLegacyRequestContext } from '@myco/grove/request-context.js';
import type { MycoRequestContext } from '@myco/grove/request-context.js';

const TEST_VAULT_DIR = '/tmp/myco-test/.myco';
const TEST_PROJECT_ID = 'proj_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as const;

/**
 * Static, LEGACY (non-Grove) request context used as the default for handler
 * tests that don't care about scope details. `groveId: null` means
 * `projectScopeFromRequestContext` returns `GLOBAL_SCOPE` (kind: 'global'),
 * matching the NULL project_id behavior of test fixtures that insert rows
 * via `makeCandidate` / `makeRow` helpers without setting project_id.
 *
 * Tests that DO want Grove-bound scope behavior (e.g. tests that exercise
 * Grove-specific filtering) should construct their own context via
 * `makeTestRequestContext({ groveId: 'grove_...' })`.
 */
export const TEST_REQUEST_CONTEXT: MycoRequestContext = resolveLegacyRequestContext(TEST_VAULT_DIR, {
  projectId: TEST_PROJECT_ID,
  groveId: null,
  machineId: 'test-machine',
  // These fixtures stand in for a legitimate caller-supplied request context
  // (the kind production transports hand handlers). The scope seam
  // (projectScopeFromRequestContext) now binds a Grove-bound context to its
  // project scope ONLY when tenancy is caller-asserted; a synthesized context
  // resolves to GLOBAL_SCOPE. Default to 'caller' so Grove-bound fixtures keep
  // exercising project-scoped reads. Tests that specifically need a synthesized
  // context pass `tenancySource: 'synthesized'`.
  tenancySource: 'caller',
});

/**
 * Build a custom test request context. Use when a test needs a specific
 * projectId / groveId / sessionId combination. The defaults match
 * `TEST_REQUEST_CONTEXT` so spreads work cleanly.
 */
export function makeTestRequestContext(
  overrides: Partial<{
    vaultDir: string;
    projectId: string;
    groveId: string | null;
    machineId: string;
    sessionId: string | null;
    tenancySource: MycoRequestContext['tenancySource'];
  }> = {},
): MycoRequestContext {
  return resolveLegacyRequestContext(overrides.vaultDir ?? TEST_VAULT_DIR, {
    projectId: (overrides.projectId ?? TEST_PROJECT_ID) as MycoRequestContext['projectId'],
    groveId: overrides.groveId ?? null,
    machineId: overrides.machineId ?? 'test-machine',
    sessionId: overrides.sessionId ?? null,
    tenancySource: overrides.tenancySource ?? 'caller',
  });
}
