import type {
  PolicyDefaultAction,
  PolicyEvaluationContext,
  PolicyRule,
  WalletOperationFamily,
} from "@sdp/types";
import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest";
import { getDb } from "@/db";
import { createTenantScope } from "@/lib/tenant-scope";
import { ApiKeyService } from "@/services/api-key.service";
import { ApiKeyPolicyStore } from "@/services/policy/api-key-policy.store";
import { PostgresPolicyEnforcementStore } from "@/services/policy/enforcement.store";
import { WalletPolicyStore } from "@/services/policy/wallet-policy.store";
import { TEST_API_KEY } from "@/test/fixtures/api-keys";
import { TEST_CUSTODY_CONFIG, TEST_CUSTODY_WALLET } from "@/test/fixtures/custody";
import { TEST_ORG, TEST_USER } from "@/test/fixtures/organizations";
import { TEST_PROJECT } from "@/test/fixtures/tokens";
import { env } from "@/test/helpers/env";
import { clearTestDatabase, seedTestDatabase } from "@/test/mocks/db";
import type {
  ApiKeyControlProfileRevisionRow,
  ApiKeyControlProfileRow,
  CreateWalletControlProfileInput,
  PolicyRepository,
} from "./policy.repository";
import { createPostgresPolicyRepository } from "./policy.repository.postgres";

/**
 * Compose the per-scope policy stores behind the flat method surface these
 * tests were written against.
 *
 * @param repo - The repository under test.
 * @returns The composed store methods.
 */
function policyStores(repo: PolicyRepository) {
  const wallet = new WalletPolicyStore(repo);
  const apiKey = new ApiKeyPolicyStore(repo);
  const enforcement = new PostgresPolicyEnforcementStore(repo);
  return {
    resolveEffectiveWalletPolicy: wallet.resolveEffectiveWalletPolicy.bind(wallet),
    resolveEffectiveApiKeyPolicy: apiKey.resolveEffectiveApiKeyPolicy.bind(apiKey),
    resolveApiKeyWalletPolicyScope: apiKey.resolveApiKeyWalletPolicyScope.bind(apiKey),
    upsertApiKeyWalletPolicyBinding: apiKey.upsertApiKeyWalletPolicyBinding.bind(apiKey),
    recordWalletOperation: enforcement.createWalletOperation.bind(enforcement),
  };
}

const SECOND_CUSTODY_WALLET = {
  id: "cw_policy_second",
  walletId: "wallet_policy_second",
  publicKey: "SecondPolicyWallet1111111111111111111111111",
  label: "Second policy wallet",
  purpose: "payments",
};

const DUPLICATE_PROVIDER_CUSTODY_CONFIG_ID = "ccfg_policy_duplicate_provider_wallet";
const DUPLICATE_PROVIDER_CUSTODY_WALLET = {
  id: "cw_policy_duplicate_provider_wallet",
  walletId: TEST_CUSTODY_WALLET.walletId,
  publicKey: "DuplicateProviderPolicyWallet11111111111111111",
  label: "Duplicate provider policy wallet",
  purpose: "payments",
};

const OTHER_PROJECT = {
  id: "prj_policy_other",
  name: "Other policy project",
  slug: "other-policy-project",
  environment: "sandbox",
};

const OTHER_PROJECT_CUSTODY_CONFIG_ID = "ccfg_policy_other_project";
const TEST_SCOPE = createTenantScope({
  organizationId: TEST_ORG.id,
  projectId: TEST_PROJECT.id,
});
const OTHER_PROJECT_CUSTODY_WALLET = {
  id: "cw_policy_other_project",
  walletId: "wallet_policy_other_project",
  publicKey: "OtherProjectWallet1111111111111111111111",
  label: "Other project policy wallet",
  purpose: "payments",
};

describe("PolicyRepository (postgres)", () => {
  let repo: PolicyRepository;

  beforeAll(async () => {
    await seedTestDatabase(env as Parameters<typeof seedTestDatabase>[0]);
  });

  afterAll(async () => {
    await clearTestDatabase(env as Parameters<typeof clearTestDatabase>[0]);
  });

  beforeEach(async () => {
    await clearTestDatabase(env as Parameters<typeof clearTestDatabase>[0]);
    await seedPolicyFoundationFixtures();
    repo = createPostgresPolicyRepository(getDb(env), TEST_SCOPE);
  });

  it("resolves API key creators without crossing organization or project scope", async () => {
    const organizationRepo = createPostgresPolicyRepository(
      getDb(env),
      createTenantScope({ organizationId: TEST_ORG.id, projectId: null })
    );
    const otherProjectRepo = createPostgresPolicyRepository(
      getDb(env),
      createTenantScope({ organizationId: TEST_ORG.id, projectId: OTHER_PROJECT.id })
    );
    const foreignOrganizationRepo = createPostgresPolicyRepository(
      getDb(env),
      createTenantScope({ organizationId: "org_policy_foreign", projectId: null })
    );

    await expect(organizationRepo.getApiKeyCreatorUserId(TEST_API_KEY.id)).resolves.toBe(
      TEST_USER.id
    );
    await expect(repo.getApiKeyCreatorUserId(TEST_API_KEY.id)).resolves.toBe(TEST_USER.id);
    await expect(otherProjectRepo.getApiKeyCreatorUserId(TEST_API_KEY.id)).resolves.toBeNull();
    await expect(
      foreignOrganizationRepo.getApiKeyCreatorUserId(TEST_API_KEY.id)
    ).resolves.toBeNull();
  });

  it("resolves implicit default allow when no customer-authored profiles exist", async () => {
    const service = policyStores(repo);

    await expect(
      service.resolveEffectiveWalletPolicy(TEST_CUSTODY_WALLET.id)
    ).resolves.toMatchObject({
      source: "implicit_default_allow",
      profile: null,
      revision: null,
      defaultAction: "allow",
    });

    await expect(service.resolveEffectiveApiKeyPolicy(TEST_API_KEY.id)).resolves.toMatchObject({
      source: "implicit_default_allow",
      profile: null,
      revision: null,
      defaultAction: "allow",
    });
  });

  it("stores wallet profile revisions as insert-only rows and changes active revision explicitly", async () => {
    const profile = await repo.createWalletControlProfile({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      name: "Treasury controls",
      createdBy: TEST_USER.id,
    });
    expect(profile).not.toBeNull();

    const revision1 = await repo.createWalletControlProfileRevision({
      profileId: profile?.id ?? "",
      rules: [{ kind: "operation_family", family: "payment" }],
      defaultAction: "allow",
      createdBy: TEST_USER.id,
    });
    const activated1 = await repo.activateWalletControlProfileRevision({
      profileId: profile?.id ?? "",
      revisionId: revision1?.id ?? "",
      activatedAt: "2026-06-17T00:00:00.000Z",
    });
    expect(activated1?.profile.active_revision_id).toBe(revision1?.id);

    const revision2 = await repo.createWalletControlProfileRevision({
      profileId: profile?.id ?? "",
      rules: [{ kind: "destination", allowlist: ["recipient_1"] }],
      defaultAction: "review",
      createdBy: TEST_USER.id,
    });
    expect(revision2?.revision_number).toBe(2);

    const activeBefore = await repo.getActiveWalletControlProfileByCustodyWalletId(
      TEST_CUSTODY_WALLET.id
    );
    expect(activeBefore?.revision?.id).toBe(revision1?.id);

    const activated2 = await repo.activateWalletControlProfileRevision({
      profileId: profile?.id ?? "",
      revisionId: revision2?.id ?? "",
      activatedAt: "2026-06-17T01:00:00.000Z",
    });
    expect(activated2?.profile.active_revision_id).toBe(revision2?.id);

    const persistedRevision1 = await getDb(env)
      .prepare("SELECT rules, default_action FROM wallet_control_profile_revisions WHERE id = ?")
      .bind(revision1?.id)
      .first<{ rules: Record<string, unknown>[]; default_action: string }>();
    expect(persistedRevision1?.rules).toEqual([{ kind: "operation_family", family: "payment" }]);
    expect(persistedRevision1?.default_action).toBe("allow");
  });

  it("returns null when creating revisions for missing profiles", async () => {
    await expect(
      repo.createWalletControlProfileRevision({
        profileId: "wcp_missing",
        rules: [{ kind: "amount", max: "10" }],
      })
    ).resolves.toBeNull();

    await expect(
      repo.createApiKeyControlProfileRevision({
        profileId: "akcp_missing",
        rules: [{ kind: "destination", allowlist: ["recipient_1"] }],
      })
    ).resolves.toBeNull();
  });

  it("records wallet operations and policy evaluations with revision references", async () => {
    const walletProfile = await repo.createWalletControlProfile({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      name: "Payment controls",
      createdBy: TEST_USER.id,
    });
    const walletRevision = await repo.createWalletControlProfileRevision({
      profileId: walletProfile?.id ?? "",
      rules: [{ kind: "amount", max: "100" }],
    });
    await repo.activateWalletControlProfileRevision({
      profileId: walletProfile?.id ?? "",
      revisionId: walletRevision?.id ?? "",
    });

    const apiKeyProfile = await repo.createApiKeyControlProfile({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      apiKeyId: TEST_API_KEY.id,
      name: "Payment key controls",
      createdBy: TEST_USER.id,
    });
    const apiKeyRevision = await repo.createApiKeyControlProfileRevision({
      profileId: apiKeyProfile?.id ?? "",
      rules: [{ kind: "destination", allowlist: ["recipient_1"] }],
    });
    await repo.activateApiKeyControlProfileRevision({
      profileId: apiKeyProfile?.id ?? "",
      revisionId: apiKeyRevision?.id ?? "",
    });

    const operation = await repo.createWalletOperation({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      walletId: TEST_CUSTODY_WALLET.walletId,
      apiKeyId: TEST_API_KEY.id,
      actor: { type: "api_key", id: TEST_API_KEY.id, apiKeyId: TEST_API_KEY.id },
      operationFamily: "payment",
      operationType: "payment_request",
      asset: "USDC",
      amount: "12.50",
      destination: "recipient_1",
      context: { requestId: "req_policy_1" },
      providerExtensions: { provider: "future-provider" },
      rawPayload: { paymentRequestId: "payreq_1" },
    });
    expect(operation?.raw_payload).toEqual({
      paymentRequestId: "payreq_1",
      actor: { type: "api_key", id: TEST_API_KEY.id, apiKeyId: TEST_API_KEY.id },
      context: { requestId: "req_policy_1" },
      providerExtensions: { provider: "future-provider" },
    });
    const evaluationContext = {
      operation: {
        id: operation?.id ?? "",
        organizationId: TEST_ORG.id,
        projectId: TEST_PROJECT.id,
        custodyWalletId: TEST_CUSTODY_WALLET.id,
        walletId: TEST_CUSTODY_WALLET.walletId,
        apiKeyId: TEST_API_KEY.id,
        actor: { type: "api_key", id: TEST_API_KEY.id, apiKeyId: TEST_API_KEY.id },
        source: "api",
        operationFamily: "payment" as const,
        operationType: "payment_request",
        asset: "USDC",
        amount: "12.50",
        destination: "recipient_1",
        context: { requestId: "req_policy_1" },
        providerExtensions: { provider: "future-provider" },
        idempotencyKey: null,
        rawPayload: {
          paymentRequestId: "payreq_1",
          actor: { type: "api_key", id: TEST_API_KEY.id, apiKeyId: TEST_API_KEY.id },
          context: { requestId: "req_policy_1" },
          providerExtensions: { provider: "future-provider" },
        },
        createdAt: operation?.created_at ?? "",
      },
      walletPolicy: {
        source: "customer_profile" as const,
        profileId: walletProfile?.id ?? null,
        revisionId: walletRevision?.id ?? null,
        defaultAction: "allow" as const,
        decision: "allow" as const,
        requiresApproval: false,
      },
      apiKeyPolicy: {
        source: "customer_profile" as const,
        profileId: apiKeyProfile?.id ?? null,
        revisionId: apiKeyRevision?.id ?? null,
        defaultAction: "allow" as const,
        decision: "allow" as const,
        requiresApproval: false,
      },
    };

    const evaluation = await repo.createPolicyEvaluation({
      walletOperationId: operation?.id ?? "",
      walletPolicyRevisionId: walletRevision?.id,
      apiKeyPolicyRevisionId: apiKeyRevision?.id,
      decision: "allow",
      reasonCode: "wallet_policy_match",
      matchedRules: [{ ruleId: "amount-limit" }],
      evaluationContext,
    });

    expect(evaluation).toMatchObject({
      wallet_operation_id: operation?.id,
      wallet_policy_revision_id: walletRevision?.id,
      api_key_policy_revision_id: apiKeyRevision?.id,
      decision: "allow",
      reason_code: "wallet_policy_match",
      matched_rules: [{ ruleId: "amount-limit" }],
      evaluation_context: evaluationContext,
    });

    const updatedOperation = await repo.updateWalletOperationStatus(
      operation?.id ?? "",
      "pending_approval"
    );
    expect(updatedOperation).toMatchObject({
      id: operation?.id,
      status: "pending_approval",
    });
    expect(updatedOperation?.updated_at).not.toBe(operation?.updated_at);
  });

  it("rejects mismatched custody and wallet identifiers on operations and bindings", async () => {
    await seedOtherProjectCustodyWallet();

    await expect(
      repo.createWalletOperation({
        organizationId: TEST_ORG.id,
        projectId: TEST_PROJECT.id,
        custodyWalletId: TEST_CUSTODY_WALLET.id,
        walletId: OTHER_PROJECT_CUSTODY_WALLET.walletId,
        operationFamily: "payment",
        operationType: "payment_transfer",
      })
    ).resolves.toBeNull();

    await expect(
      repo.upsertApiKeyWalletPolicyBinding({
        apiKeyId: TEST_API_KEY.id,
        bindingScope: "selected",
        walletId: TEST_CUSTODY_WALLET.walletId,
        custodyWalletId: OTHER_PROJECT_CUSTODY_WALLET.id,
      })
    ).resolves.toBeNull();

    await expect(
      repo.replaceApiKeyWalletPolicyBindings({
        apiKeyId: TEST_API_KEY.id,
        bindings: [
          {
            apiKeyId: TEST_API_KEY.id,
            bindingScope: "selected",
            walletId: TEST_CUSTODY_WALLET.walletId,
            custodyWalletId: OTHER_PROJECT_CUSTODY_WALLET.id,
          },
        ],
      })
    ).resolves.toEqual([]);

    await expect(repo.listApiKeyWalletPolicyBindings(TEST_API_KEY.id)).resolves.toEqual([]);
  });

  it("rejects a tenant-bearing input that omits its project claim", async () => {
    const inputWithoutProject = {
      organizationId: TEST_ORG.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      name: "Canonical tenant scope",
    } as unknown as CreateWalletControlProfileInput;

    await expect(repo.createWalletControlProfile(inputWithoutProject)).rejects.toThrow(
      "cannot override the repository project scope"
    );
  });

  it("applies active organization wallet and API key policies as project fallbacks", async () => {
    await getDb(env)
      .prepare("UPDATE custody_configs SET project_id = NULL WHERE id = ?")
      .bind(TEST_CUSTODY_CONFIG.id)
      .run();

    const organizationRepo = createPostgresPolicyRepository(
      getDb(env),
      createTenantScope({ organizationId: TEST_ORG.id, projectId: null })
    );
    const walletProfile = await organizationRepo.createWalletControlProfile({
      organizationId: TEST_ORG.id,
      projectId: null,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      name: "Organization wallet controls",
    });
    const walletRevision = await organizationRepo.createWalletControlProfileRevision({
      profileId: walletProfile?.id ?? "",
      defaultAction: "deny",
    });
    await organizationRepo.activateWalletControlProfileRevision({
      profileId: walletProfile?.id ?? "",
      revisionId: walletRevision?.id ?? "",
    });

    await getDb(env).batch([
      getDb(env)
        .prepare(
          `INSERT INTO api_key_control_profiles (
             id, organization_id, project_id, api_key_id, name, status, active_revision_id
           ) VALUES ('akcp_org_fallback', ?, NULL, ?, 'Organization key controls', 'active', 'akcpr_org_fallback')`
        )
        .bind(TEST_ORG.id, TEST_API_KEY.id),
      getDb(env).prepare(
        `INSERT INTO api_key_control_profile_revisions (
             id, profile_id, revision_number, rules, default_action, activated_at
           ) VALUES ('akcpr_org_fallback', 'akcp_org_fallback', 1, '[]'::jsonb, 'deny', sdp_iso_now())`
      ),
    ]);

    const service = policyStores(repo);
    await expect(
      service.resolveEffectiveWalletPolicy(TEST_CUSTODY_WALLET.id)
    ).resolves.toMatchObject({
      source: "customer_profile",
      profile: { id: walletProfile?.id },
      defaultAction: "deny",
    });
    await expect(service.resolveEffectiveApiKeyPolicy(TEST_API_KEY.id)).resolves.toMatchObject({
      source: "customer_profile",
      profile: { id: "akcp_org_fallback" },
      defaultAction: "deny",
    });
  });

  it("lists recent policy evaluations scoped to a wallet for audit review", async () => {
    await seedAdditionalCustodyWallet();

    const operation = await repo.createWalletOperation({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      walletId: TEST_CUSTODY_WALLET.walletId,
      apiKeyId: TEST_API_KEY.id,
      operationFamily: "ramp",
      operationType: "onramp_quote",
      asset: "USDC",
      amount: "25.00",
      destination: "recipient_1",
      status: "pending_approval",
    });
    expect(operation).not.toBeNull();

    const approvalRequest = await repo.createApprovalRequest({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      walletOperationId: operation?.id ?? "",
      provider: "future-provider",
      providerReference: "provider_approval_1",
    });
    expect(approvalRequest).not.toBeNull();

    const evaluation = await repo.createPolicyEvaluation({
      walletOperationId: operation?.id ?? "",
      decision: "approval_required",
      reasonCode: "wallet_policy_match",
      reason: "Ramp operation matched approval policy.",
      matchedRules: [{ ruleId: "approval-required" }],
      evaluationContext: buildPolicyEvaluationContext({
        operationId: operation?.id ?? "",
        custodyWalletId: TEST_CUSTODY_WALLET.id,
        walletId: TEST_CUSTODY_WALLET.walletId,
        operationFamily: "ramp",
        operationType: "onramp_quote",
      }),
      requiresApproval: true,
      approvalRequestId: approvalRequest?.id,
    });
    expect(evaluation).not.toBeNull();

    const otherWalletOperation = await repo.createWalletOperation({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: SECOND_CUSTODY_WALLET.id,
      walletId: SECOND_CUSTODY_WALLET.walletId,
      apiKeyId: TEST_API_KEY.id,
      operationFamily: "payment",
      operationType: "payment_transfer",
      status: "failed",
    });
    expect(otherWalletOperation).not.toBeNull();

    await repo.createPolicyEvaluation({
      walletOperationId: otherWalletOperation?.id ?? "",
      decision: "deny",
      reasonCode: "wallet_policy_match",
      evaluationContext: buildPolicyEvaluationContext({
        operationId: otherWalletOperation?.id ?? "",
        custodyWalletId: SECOND_CUSTODY_WALLET.id,
        walletId: SECOND_CUSTODY_WALLET.walletId,
        operationFamily: "payment",
        operationType: "payment_transfer",
      }),
    });

    const audits = await repo.listWalletPolicyEvaluationAudits({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      pageSize: 10,
    });

    expect(audits.total).toBe(1);
    expect(audits.rows).toHaveLength(1);
    expect(audits.rows[0]).toMatchObject({
      wallet_operation_id: operation?.id,
      policy_evaluation_id: evaluation?.id,
      operation_family: "ramp",
      operation_type: "onramp_quote",
      asset: "USDC",
      amount: "25.00",
      destination: "recipient_1",
      operation_status: "pending_approval",
      decision: "approval_required",
      reason_code: "wallet_policy_match",
      reason: "Ramp operation matched approval policy.",
      requires_approval: true,
      approval_request_id: approvalRequest?.id,
    });
  });

  it("maps legacy policy evaluation rows without a structured context to null", async () => {
    const operation = await repo.createWalletOperation({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      walletId: TEST_CUSTODY_WALLET.walletId,
      operationFamily: "transfer",
      operationType: "legacy_transfer",
    });
    expect(operation).not.toBeNull();

    await getDb(env)
      .prepare(
        `INSERT INTO policy_evaluations (
           id,
           wallet_operation_id,
           decision,
           reason_code,
           matched_rules,
           evaluation_context
         ) VALUES (?, ?, ?, ?, ?::jsonb, ?::jsonb)`
      )
      .bind("peval_legacy_context", operation?.id, "allow", "legacy_policy_evaluation", "[]", "{}")
      .run();

    const evaluations = await repo.listPolicyEvaluationsForOperation(operation?.id ?? "");

    expect(evaluations).toHaveLength(1);
    expect(evaluations[0]?.evaluation_context).toBeNull();
  });

  it("creates one approval request per wallet operation and resolves it idempotently", async () => {
    const operation = await repo.createWalletOperation({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      walletId: TEST_CUSTODY_WALLET.walletId,
      apiKeyId: TEST_API_KEY.id,
      operationFamily: "payment",
      operationType: "payment_transfer",
      status: "pending_approval",
    });
    expect(operation).not.toBeNull();

    const request = await repo.createApprovalRequest({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      walletOperationId: operation?.id ?? "",
      provider: "fireblocks",
      providerReference: "fb_tx_1",
      providerPayload: { provider: "fireblocks", providerReference: "fb_tx_1" },
      requestedBy: TEST_USER.id,
    });
    const duplicate = await repo.createApprovalRequest({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      walletOperationId: operation?.id ?? "",
      provider: "fireblocks",
      providerReference: "fb_tx_1",
    });

    expect(duplicate?.id).toBe(request?.id);
    expect(request).toMatchObject({
      wallet_operation_id: operation?.id,
      status: "pending",
      provider: "fireblocks",
      provider_reference: "fb_tx_1",
      provider_payload: { provider: "fireblocks", providerReference: "fb_tx_1" },
      requested_by: TEST_USER.id,
    });

    await expect(
      repo.updateApprovalRequestStatus({
        organizationId: "org_other",
        projectId: TEST_PROJECT.id,
        approvalRequestId: request?.id ?? "",
        status: "approved",
        operationStatus: "executing",
        resolvedBy: TEST_USER.id,
      })
    ).rejects.toThrowError("cannot override the repository organization scope");

    await expect(
      repo.updateApprovalRequestStatus({
        organizationId: TEST_ORG.id,
        projectId: TEST_PROJECT.id,
        approvalRequestId: request?.id ?? "",
        status: "approved",
        operationStatus: "executing",
        resolvedBy: TEST_USER.id,
        resolvedAt: "2026-06-18T02:00:00.000Z",
      })
    ).resolves.toMatchObject({
      id: request?.id,
      status: "approved",
      resolved_by: TEST_USER.id,
    });
    await expect(
      repo.updateApprovalRequestStatus({
        organizationId: TEST_ORG.id,
        projectId: TEST_PROJECT.id,
        approvalRequestId: request?.id ?? "",
        status: "approved",
        operationStatus: "executing",
        resolvedBy: TEST_USER.id,
      })
    ).resolves.toMatchObject({
      id: request?.id,
      status: "approved",
    });

    const updatedOperation = await repo.getWalletOperationById(operation?.id ?? "");
    expect(updatedOperation?.status).toBe("executing");
  });

  it("lists approval request details scoped by project and status", async () => {
    await seedOtherProjectCustodyWallet();

    const operation = await repo.createWalletOperation({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      walletId: TEST_CUSTODY_WALLET.walletId,
      apiKeyId: TEST_API_KEY.id,
      operationFamily: "payment",
      operationType: "payment_transfer",
      asset: "USDC",
      amount: "25.00",
      destination: "recipient_1",
      status: "pending_approval",
    });
    expect(operation).not.toBeNull();

    const request = await repo.createApprovalRequest({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      walletOperationId: operation?.id ?? "",
      requestedBy: TEST_USER.id,
    });
    expect(request).not.toBeNull();

    await repo.createPolicyEvaluation({
      walletOperationId: operation?.id ?? "",
      decision: "approval_required",
      reasonCode: "wallet_policy_match",
      reason: "Payment matched approval policy.",
      matchedRules: [{ ruleId: "payment-approval" }],
      evaluationContext: buildPolicyEvaluationContext({
        operationId: operation?.id ?? "",
        custodyWalletId: TEST_CUSTODY_WALLET.id,
        walletId: TEST_CUSTODY_WALLET.walletId,
        operationFamily: "payment",
        operationType: "payment_transfer",
      }),
      requiresApproval: true,
      approvalRequestId: request?.id,
    });

    const otherProjectRepo = createPostgresPolicyRepository(
      getDb(env),
      createTenantScope({
        organizationId: TEST_ORG.id,
        projectId: OTHER_PROJECT.id,
      })
    );
    const organizationRepo = createPostgresPolicyRepository(
      getDb(env),
      createTenantScope({
        organizationId: TEST_ORG.id,
        projectId: null,
      })
    );
    const otherOperation = await otherProjectRepo.createWalletOperation({
      organizationId: TEST_ORG.id,
      projectId: OTHER_PROJECT.id,
      custodyWalletId: OTHER_PROJECT_CUSTODY_WALLET.id,
      walletId: OTHER_PROJECT_CUSTODY_WALLET.walletId,
      operationFamily: "payment",
      operationType: "payment_transfer",
      status: "pending_approval",
    });
    expect(otherOperation).not.toBeNull();

    const otherRequest = await otherProjectRepo.createApprovalRequest({
      organizationId: TEST_ORG.id,
      projectId: OTHER_PROJECT.id,
      walletOperationId: otherOperation?.id ?? "",
    });
    expect(otherRequest).not.toBeNull();

    const projectRows = await repo.listApprovalRequestDetails({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      status: "pending",
      limit: 10,
    });

    expect(projectRows).toHaveLength(1);
    expect(projectRows[0]).toMatchObject({
      approval_request_id: request?.id,
      project_id: TEST_PROJECT.id,
      wallet_operation_id: operation?.id,
      wallet_id: TEST_CUSTODY_WALLET.walletId,
      wallet_public_key: TEST_CUSTODY_WALLET.publicKey,
      operation_family: "payment",
      operation_type: "payment_transfer",
      decision: "approval_required",
      reason_code: "wallet_policy_match",
      matched_rules: [{ ruleId: "payment-approval" }],
      requires_approval: true,
    });

    await expect(
      repo.getApprovalRequestDetail({
        organizationId: TEST_ORG.id,
        projectId: TEST_PROJECT.id,
        approvalRequestId: request?.id ?? "",
      })
    ).resolves.toMatchObject({ approval_request_id: request?.id });
    await expect(
      repo.getApprovalRequestDetail({
        organizationId: TEST_ORG.id,
        projectId: TEST_PROJECT.id,
        approvalRequestId: otherRequest?.id ?? "",
      })
    ).resolves.toBeNull();

    await expect(
      repo.updateApprovalRequestStatus({
        organizationId: TEST_ORG.id,
        projectId: TEST_PROJECT.id,
        approvalRequestId: otherRequest?.id ?? "",
        status: "approved",
        operationStatus: "executing",
      })
    ).resolves.toBeNull();
    await expect(
      organizationRepo.getApprovalRequestDetail({
        organizationId: TEST_ORG.id,
        projectId: null,
        approvalRequestId: otherRequest?.id ?? "",
      })
    ).resolves.toMatchObject({
      approval_request_id: otherRequest?.id,
      approval_status: "pending",
      operation_status: "pending_approval",
    });

    const orgRows = await organizationRepo.listApprovalRequestDetails({
      organizationId: TEST_ORG.id,
      projectId: null,
      status: "pending",
      limit: 10,
    });
    expect(orgRows.map((row) => row.approval_request_id)).toEqual(
      expect.arrayContaining([request?.id, otherRequest?.id])
    );
  });

  it("preserves an explicit null wallet operation actor through service mapping", async () => {
    const service = policyStores(repo);

    const operation = await service.recordWalletOperation({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      walletId: TEST_CUSTODY_WALLET.walletId,
      apiKeyId: TEST_API_KEY.id,
      actor: null,
      operationFamily: "program",
      operationType: "program_call",
      rawPayload: { programId: "program_1" },
    });

    expect(operation).toMatchObject({
      apiKeyId: TEST_API_KEY.id,
      actor: null,
      rawPayload: {
        programId: "program_1",
        actor: null,
      },
    });
  });

  it("stores policy-scoped wallet bindings separately from endpoint wallet permissions", async () => {
    const apiKeyProfile = await repo.createApiKeyControlProfile({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      apiKeyId: TEST_API_KEY.id,
      name: "Selected wallet controls",
    });

    const binding = await repo.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
      walletId: TEST_CUSTODY_WALLET.walletId,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      apiKeyControlProfileId: apiKeyProfile?.id,
    });
    expect(binding?.api_key_control_profile_id).toBe(apiKeyProfile?.id);

    await repo.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
      walletId: TEST_CUSTODY_WALLET.walletId,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      apiKeyControlProfileId: null,
    });

    const bindings = await repo.listApiKeyWalletPolicyBindings(TEST_API_KEY.id);
    expect(bindings).toHaveLength(1);
    expect(bindings[0]).toMatchObject({
      binding_scope: "selected",
      wallet_id: TEST_CUSTODY_WALLET.walletId,
      custody_wallet_id: TEST_CUSTODY_WALLET.id,
      api_key_control_profile_id: null,
    });
  });

  it("keeps selected policy bindings distinct when provider wallet IDs collide", async () => {
    await seedDuplicateProviderCustodyWallet();

    await repo.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
      walletId: TEST_CUSTODY_WALLET.walletId,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
    });
    await repo.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
      walletId: DUPLICATE_PROVIDER_CUSTODY_WALLET.walletId,
      custodyWalletId: DUPLICATE_PROVIDER_CUSTODY_WALLET.id,
    });

    const bindings = await repo.listApiKeyWalletPolicyBindings(TEST_API_KEY.id);
    expect(bindings).toHaveLength(2);
    expect(bindings.map((binding) => binding.custody_wallet_id).sort()).toEqual(
      [TEST_CUSTODY_WALLET.id, DUPLICATE_PROVIDER_CUSTODY_WALLET.id].sort()
    );

    await expect(
      repo.getApiKeyWalletPolicyBindingResolution(TEST_API_KEY.id, TEST_CUSTODY_WALLET.id)
    ).resolves.toMatchObject({
      binding: { custody_wallet_id: TEST_CUSTODY_WALLET.id },
    });
    await expect(
      repo.getApiKeyWalletPolicyBindingResolution(
        TEST_API_KEY.id,
        DUPLICATE_PROVIDER_CUSTODY_WALLET.id
      )
    ).resolves.toMatchObject({
      binding: { custody_wallet_id: DUPLICATE_PROVIDER_CUSTODY_WALLET.id },
    });
  });

  it("resolves an all-wallet API key policy binding for every in-scope wallet", async () => {
    const service = policyStores(repo);
    await seedAdditionalCustodyWallet();
    const { profile } = await createActiveApiKeyControlProfile(repo, {
      name: "Shared all-wallet controls",
      defaultAction: "review",
    });

    const binding = await service.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "all",
      apiKeyControlProfileId: profile.id,
    });
    expect(binding.bindingScope).toBe("all");
    expect(binding.walletId).toBeNull();

    await expect(
      service.resolveApiKeyWalletPolicyScope({
        apiKeyId: TEST_API_KEY.id,
        custodyWalletId: TEST_CUSTODY_WALLET.id,
      })
    ).resolves.toMatchObject({
      binding: { bindingScope: "all", apiKeyControlProfileId: profile.id },
      apiKeyPolicy: { profile: { id: profile.id }, defaultAction: "review" },
    });

    await expect(
      service.resolveApiKeyWalletPolicyScope({
        apiKeyId: TEST_API_KEY.id,
        custodyWalletId: SECOND_CUSTODY_WALLET.id,
      })
    ).resolves.toMatchObject({
      binding: { bindingScope: "all", apiKeyControlProfileId: profile.id },
      apiKeyPolicy: { profile: { id: profile.id }, defaultAction: "review" },
    });
  });

  it("resolves selected-wallet API key policy bindings for multiple endpoint-scoped wallets", async () => {
    const service = policyStores(repo);
    await seedAdditionalCustodyWallet();
    await seedEndpointWalletPermission("akw_policy_selected_primary", TEST_CUSTODY_WALLET.walletId);
    await seedEndpointWalletPermission(
      "akw_policy_selected_second",
      SECOND_CUSTODY_WALLET.walletId
    );
    const { profile } = await createActiveApiKeyControlProfile(repo, {
      name: "Selected wallet controls",
      defaultAction: "approval_required",
    });

    await service.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
      walletId: TEST_CUSTODY_WALLET.walletId,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      apiKeyControlProfileId: profile.id,
    });
    await service.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
      walletId: SECOND_CUSTODY_WALLET.walletId,
      custodyWalletId: SECOND_CUSTODY_WALLET.id,
      apiKeyControlProfileId: profile.id,
    });

    const primary = await service.resolveApiKeyWalletPolicyScope({
      apiKeyId: TEST_API_KEY.id,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
    });
    const second = await service.resolveApiKeyWalletPolicyScope({
      apiKeyId: TEST_API_KEY.id,
      custodyWalletId: SECOND_CUSTODY_WALLET.id,
    });

    expect(primary).toMatchObject({
      binding: { bindingScope: "selected", walletId: TEST_CUSTODY_WALLET.walletId },
      apiKeyPolicy: { profile: { id: profile.id }, defaultAction: "approval_required" },
    });
    expect(second).toMatchObject({
      binding: { bindingScope: "selected", walletId: SECOND_CUSTODY_WALLET.walletId },
      apiKeyPolicy: { profile: { id: profile.id }, defaultAction: "approval_required" },
    });
  });

  it("prefers a selected per-wallet policy override over an all-wallet shared policy", async () => {
    const service = policyStores(repo);
    await seedAdditionalCustodyWallet();
    const shared = await createActiveApiKeyControlProfile(repo, {
      name: "Shared key controls",
      defaultAction: "allow",
    });
    const override = await createActiveApiKeyControlProfile(repo, {
      name: "Second wallet override",
      defaultAction: "review",
    });

    await service.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "all",
      apiKeyControlProfileId: shared.profile.id,
    });
    await service.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
      walletId: SECOND_CUSTODY_WALLET.walletId,
      custodyWalletId: SECOND_CUSTODY_WALLET.id,
      apiKeyControlProfileId: override.profile.id,
    });

    await expect(
      service.resolveApiKeyWalletPolicyScope({
        apiKeyId: TEST_API_KEY.id,
        custodyWalletId: TEST_CUSTODY_WALLET.id,
      })
    ).resolves.toMatchObject({
      binding: { bindingScope: "all" },
      apiKeyPolicy: { profile: { id: shared.profile.id }, defaultAction: "allow" },
    });

    await expect(
      service.resolveApiKeyWalletPolicyScope({
        apiKeyId: TEST_API_KEY.id,
        custodyWalletId: SECOND_CUSTODY_WALLET.id,
      })
    ).resolves.toMatchObject({
      binding: { bindingScope: "selected", walletId: SECOND_CUSTODY_WALLET.walletId },
      apiKeyPolicy: { profile: { id: override.profile.id }, defaultAction: "review" },
    });
  });

  it("fails closed when policy bindings exist but the requested wallet has no binding", async () => {
    const service = policyStores(repo);
    await seedAdditionalCustodyWallet();
    const { profile } = await createActiveApiKeyControlProfile(repo, {
      name: "Primary wallet only",
      defaultAction: "review",
    });

    await service.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
      walletId: TEST_CUSTODY_WALLET.walletId,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      apiKeyControlProfileId: profile.id,
    });

    await expect(
      service.resolveApiKeyWalletPolicyScope({
        apiKeyId: TEST_API_KEY.id,
        custodyWalletId: SECOND_CUSTODY_WALLET.id,
      })
    ).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "API key policy binding is not configured for the requested wallet",
    });
  });

  it("fails closed when an all-wallet policy binding would exceed selected endpoint wallet access", async () => {
    const service = policyStores(repo);
    await seedAdditionalCustodyWallet();
    await seedEndpointWalletPermission("akw_policy_endpoint_primary", TEST_CUSTODY_WALLET.walletId);
    const { profile } = await createActiveApiKeyControlProfile(repo, {
      name: "All policy selected endpoint",
      defaultAction: "review",
    });

    await service.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "all",
      apiKeyControlProfileId: profile.id,
    });

    await expect(
      service.resolveApiKeyWalletPolicyScope({
        apiKeyId: TEST_API_KEY.id,
        custodyWalletId: SECOND_CUSTODY_WALLET.id,
      })
    ).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "API key is not authorized for the requested wallet",
    });
  });

  it("fails closed when an all-wallet policy binding is requested for another project wallet", async () => {
    const service = policyStores(repo);
    await seedOtherProjectCustodyWallet();
    const { profile } = await createActiveApiKeyControlProfile(repo, {
      name: "All policy project boundary",
      defaultAction: "review",
    });

    await service.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "all",
      apiKeyControlProfileId: profile.id,
    });

    await expect(
      service.resolveApiKeyWalletPolicyScope({
        apiKeyId: TEST_API_KEY.id,
        custodyWalletId: OTHER_PROJECT_CUSTODY_WALLET.id,
      })
    ).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "API key is not authorized for the requested wallet",
    });
  });

  it("rejects all-wallet policy bindings that reference inactive API key profiles", async () => {
    const service = policyStores(repo);
    const profile = await repo.createApiKeyControlProfile({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      apiKeyId: TEST_API_KEY.id,
      name: "Inactive all-wallet controls",
      createdBy: TEST_USER.id,
    });
    expect(profile).not.toBeNull();

    await expect(
      service.upsertApiKeyWalletPolicyBinding({
        apiKeyId: TEST_API_KEY.id,
        bindingScope: "all",
        apiKeyControlProfileId: profile?.id,
      })
    ).rejects.toMatchObject({
      code: "FORBIDDEN",
      message: "API key policy profile is not active for the requested wallet binding",
    });

    await expect(repo.listApiKeyWalletPolicyBindings(TEST_API_KEY.id)).resolves.toHaveLength(0);
  });

  it("rejects all-wallet policy bindings with wallet-specific profile references", async () => {
    const service = policyStores(repo);

    await expect(
      service.upsertApiKeyWalletPolicyBinding({
        apiKeyId: TEST_API_KEY.id,
        bindingScope: "all",
        walletControlProfileId: "wcp_unscoped",
      })
    ).rejects.toMatchObject({
      code: "BAD_REQUEST",
      message: "walletControlProfileId cannot be used with all-wallet policy bindings",
    });

    await expect(repo.listApiKeyWalletPolicyBindings(TEST_API_KEY.id)).resolves.toHaveLength(0);
  });

  it("rejects policy wallet bindings that do not match their scope before querying Postgres", async () => {
    const selectedWithoutWalletId = {
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
    } as const;

    await expect(
      // @ts-expect-error selected policy bindings require a wallet ID at compile time.
      repo.upsertApiKeyWalletPolicyBinding(selectedWithoutWalletId)
    ).rejects.toMatchObject({
      code: "BAD_REQUEST",
      message: "walletId is required for selected API key wallet policy bindings",
    });

    const selectedWithNullWalletId = {
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
      walletId: null,
    } as const;

    await expect(
      // @ts-expect-error selected policy bindings require a non-null wallet ID.
      repo.upsertApiKeyWalletPolicyBinding(selectedWithNullWalletId)
    ).rejects.toMatchObject({
      code: "BAD_REQUEST",
      message: "walletId is required for selected API key wallet policy bindings",
    });

    const allWithWalletTarget = {
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "all",
      walletId: TEST_CUSTODY_WALLET.walletId,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
    } as const;

    await expect(
      // @ts-expect-error all-wallet policy bindings cannot carry a selected-wallet target.
      repo.upsertApiKeyWalletPolicyBinding(allWithWalletTarget)
    ).rejects.toMatchObject({
      code: "BAD_REQUEST",
      message: "walletId and custodyWalletId must be omitted for all-wallet policy bindings",
    });

    const bindings = await repo.listApiKeyWalletPolicyBindings(TEST_API_KEY.id);
    expect(bindings).toHaveLength(0);
  });

  it("preserves policy-scoped wallet bindings when an API key is rotated", async () => {
    await getDb(env)
      .prepare(
        `INSERT INTO api_key_wallet_permissions (id, api_key_id, wallet_id, permissions)
         VALUES ('akw_rotate_policy_test', ?, ?, '["payments:write"]')`
      )
      .bind(TEST_API_KEY.id, TEST_CUSTODY_WALLET.walletId)
      .run();

    const apiKeyProfile = await repo.createApiKeyControlProfile({
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      apiKeyId: TEST_API_KEY.id,
      name: "Rotation controls",
      createdBy: TEST_USER.id,
    });
    const apiKeyRevision = await repo.createApiKeyControlProfileRevision({
      profileId: apiKeyProfile?.id ?? "",
      rules: [{ kind: "destination", allowlist: ["recipient_1"] }],
      defaultAction: "review",
      createdBy: TEST_USER.id,
    });
    await repo.activateApiKeyControlProfileRevision({
      profileId: apiKeyProfile?.id ?? "",
      revisionId: apiKeyRevision?.id ?? "",
    });
    await repo.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "all",
      apiKeyControlProfileId: apiKeyProfile?.id,
    });
    await repo.upsertApiKeyWalletPolicyBinding({
      apiKeyId: TEST_API_KEY.id,
      bindingScope: "selected",
      walletId: TEST_CUSTODY_WALLET.walletId,
      custodyWalletId: TEST_CUSTODY_WALLET.id,
      apiKeyControlProfileId: apiKeyProfile?.id,
    });

    const rotation = await new ApiKeyService(getDb(env), TEST_SCOPE).rotateApiKey(
      TEST_API_KEY.id,
      TEST_ORG.id,
      TEST_PROJECT.id,
      24,
      "pepper"
    );
    expect(rotation).not.toBeNull();

    const clonedBindings = await repo.listApiKeyWalletPolicyBindings(rotation?.apiKey.id ?? "");
    expect(clonedBindings).toHaveLength(2);
    const clonedAllBinding = clonedBindings.find((binding) => binding.binding_scope === "all");
    const clonedSelectedBinding = clonedBindings.find(
      (binding) => binding.binding_scope === "selected"
    );
    expect(clonedAllBinding).toMatchObject({
      wallet_id: null,
      custody_wallet_id: null,
    });
    expect(clonedSelectedBinding?.wallet_id).toBe(TEST_CUSTODY_WALLET.walletId);
    expect(clonedSelectedBinding?.custody_wallet_id).toBe(TEST_CUSTODY_WALLET.id);
    expect(clonedAllBinding?.api_key_control_profile_id).not.toBe(apiKeyProfile?.id);
    expect(clonedSelectedBinding?.api_key_control_profile_id).not.toBe(apiKeyProfile?.id);

    const clonedProfile = await repo.getActiveApiKeyControlProfileByApiKeyId(
      rotation?.apiKey.id ?? ""
    );
    expect(clonedProfile?.profile.name).toBe("Rotation controls");
    expect(clonedProfile?.revision?.rules).toEqual([
      { kind: "destination", allowlist: ["recipient_1"] },
    ]);
    expect(clonedAllBinding?.api_key_control_profile_id).toBe(clonedProfile?.profile.id);
    expect(clonedSelectedBinding?.api_key_control_profile_id).toBe(clonedProfile?.profile.id);

    const clonedEndpointPermissions = await getDb(env)
      .prepare("SELECT permissions FROM api_key_wallet_permissions WHERE api_key_id = ?")
      .bind(rotation?.apiKey.id)
      .all<{ permissions: string }>();
    expect(clonedEndpointPermissions.results).toHaveLength(1);
    expect(JSON.parse(clonedEndpointPermissions.results[0].permissions)).toEqual([
      "payments:write",
    ]);
  });
});

async function seedPolicyFoundationFixtures(): Promise<void> {
  const db = getDb(env);

  await db
    .prepare(
      "INSERT INTO organizations (id, name, slug, tier, status) VALUES (?, ?, ?, 'individual', 'active')"
    )
    .bind(TEST_ORG.id, TEST_ORG.name, TEST_ORG.slug)
    .run();

  await db
    .prepare("INSERT INTO users (id, email, email_verified, status) VALUES (?, ?, 1, 'active')")
    .bind(TEST_USER.id, TEST_USER.email)
    .run();

  await db
    .prepare(
      `INSERT INTO projects (id, organization_id, name, slug, environment, status, created_by)
       VALUES (?, ?, ?, ?, ?, 'active', ?)`
    )
    .bind(
      TEST_PROJECT.id,
      TEST_ORG.id,
      TEST_PROJECT.name,
      TEST_PROJECT.slug,
      TEST_PROJECT.environment,
      TEST_USER.id
    )
    .run();

  await db
    .prepare(
      `INSERT INTO api_keys (
         id,
         organization_id,
         project_id,
         created_by,
         name,
         key_prefix,
         key_hash,
         role,
         permissions,
         status
       ) VALUES (?, ?, ?, ?, 'Test key', ?, 'hash_policy_foundation', 'api_admin', '["*"]', 'active')`
    )
    .bind(TEST_API_KEY.id, TEST_ORG.id, TEST_PROJECT.id, TEST_USER.id, TEST_API_KEY.prefix)
    .run();

  await db
    .prepare(
      `INSERT INTO custody_configs (
         id,
         organization_id,
         project_id,
         provider,
         config_encrypted,
         default_wallet_id,
         status
       ) VALUES (?, ?, ?, 'local', 'encrypted', ?, 'active')`
    )
    .bind(TEST_CUSTODY_CONFIG.id, TEST_ORG.id, TEST_PROJECT.id, TEST_CUSTODY_WALLET.walletId)
    .run();

  await db
    .prepare(
      `INSERT INTO custody_wallets (
         id,
         custody_config_id,
         wallet_id,
         public_key,
         label,
         purpose,
         status
       ) VALUES (?, ?, ?, ?, ?, ?, 'active')`
    )
    .bind(
      TEST_CUSTODY_WALLET.id,
      TEST_CUSTODY_CONFIG.id,
      TEST_CUSTODY_WALLET.walletId,
      TEST_CUSTODY_WALLET.publicKey,
      TEST_CUSTODY_WALLET.label,
      TEST_CUSTODY_WALLET.purpose
    )
    .run();
}

async function seedAdditionalCustodyWallet(): Promise<void> {
  await getDb(env)
    .prepare(
      `INSERT INTO custody_wallets (
         id,
         custody_config_id,
         wallet_id,
         public_key,
         label,
         purpose,
         status
       ) VALUES (?, ?, ?, ?, ?, ?, 'active')`
    )
    .bind(
      SECOND_CUSTODY_WALLET.id,
      TEST_CUSTODY_CONFIG.id,
      SECOND_CUSTODY_WALLET.walletId,
      SECOND_CUSTODY_WALLET.publicKey,
      SECOND_CUSTODY_WALLET.label,
      SECOND_CUSTODY_WALLET.purpose
    )
    .run();
}

/**
 * Seed a second custody row that shares the primary wallet's provider identifier.
 *
 * @returns A promise that resolves when the duplicate provider wallet is stored.
 */
async function seedDuplicateProviderCustodyWallet(): Promise<void> {
  const db = getDb(env);
  await db
    .prepare(
      `INSERT INTO custody_configs (
         id,
         organization_id,
         project_id,
         provider,
         config_encrypted,
         default_wallet_id,
         status
       ) VALUES (?, ?, ?, 'privy', 'encrypted', ?, 'active')`
    )
    .bind(
      DUPLICATE_PROVIDER_CUSTODY_CONFIG_ID,
      TEST_ORG.id,
      TEST_PROJECT.id,
      DUPLICATE_PROVIDER_CUSTODY_WALLET.walletId
    )
    .run();

  await db
    .prepare(
      `INSERT INTO custody_wallets (
         id,
         custody_config_id,
         wallet_id,
         public_key,
         label,
         purpose,
         status
       ) VALUES (?, ?, ?, ?, ?, ?, 'active')`
    )
    .bind(
      DUPLICATE_PROVIDER_CUSTODY_WALLET.id,
      DUPLICATE_PROVIDER_CUSTODY_CONFIG_ID,
      DUPLICATE_PROVIDER_CUSTODY_WALLET.walletId,
      DUPLICATE_PROVIDER_CUSTODY_WALLET.publicKey,
      DUPLICATE_PROVIDER_CUSTODY_WALLET.label,
      DUPLICATE_PROVIDER_CUSTODY_WALLET.purpose
    )
    .run();
}

async function seedOtherProjectCustodyWallet(): Promise<void> {
  const db = getDb(env);

  await db
    .prepare(
      `INSERT INTO projects (id, organization_id, name, slug, environment, status, created_by)
       VALUES (?, ?, ?, ?, ?, 'active', ?)`
    )
    .bind(
      OTHER_PROJECT.id,
      TEST_ORG.id,
      OTHER_PROJECT.name,
      OTHER_PROJECT.slug,
      OTHER_PROJECT.environment,
      TEST_USER.id
    )
    .run();

  await db
    .prepare(
      `INSERT INTO custody_configs (
         id,
         organization_id,
         project_id,
         provider,
         config_encrypted,
         default_wallet_id,
         status
       ) VALUES (?, ?, ?, 'local', 'encrypted', ?, 'active')`
    )
    .bind(
      OTHER_PROJECT_CUSTODY_CONFIG_ID,
      TEST_ORG.id,
      OTHER_PROJECT.id,
      OTHER_PROJECT_CUSTODY_WALLET.walletId
    )
    .run();

  await db
    .prepare(
      `INSERT INTO custody_wallets (
         id,
         custody_config_id,
         wallet_id,
         public_key,
         label,
         purpose,
         status
       ) VALUES (?, ?, ?, ?, ?, ?, 'active')`
    )
    .bind(
      OTHER_PROJECT_CUSTODY_WALLET.id,
      OTHER_PROJECT_CUSTODY_CONFIG_ID,
      OTHER_PROJECT_CUSTODY_WALLET.walletId,
      OTHER_PROJECT_CUSTODY_WALLET.publicKey,
      OTHER_PROJECT_CUSTODY_WALLET.label,
      OTHER_PROJECT_CUSTODY_WALLET.purpose
    )
    .run();
}

async function seedEndpointWalletPermission(id: string, walletId: string): Promise<void> {
  await getDb(env)
    .prepare(
      `INSERT INTO api_key_wallet_permissions (id, api_key_id, wallet_id, permissions)
       VALUES (?, ?, ?, '["payments:write"]')`
    )
    .bind(id, TEST_API_KEY.id, walletId)
    .run();
}

function buildPolicyEvaluationContext(input: {
  operationId: string;
  custodyWalletId: string;
  walletId: string;
  operationFamily: WalletOperationFamily;
  operationType: string;
}): PolicyEvaluationContext {
  return {
    operation: {
      id: input.operationId,
      organizationId: TEST_ORG.id,
      projectId: TEST_PROJECT.id,
      custodyWalletId: input.custodyWalletId,
      walletId: input.walletId,
      apiKeyId: TEST_API_KEY.id,
      actor: { type: "api_key", id: TEST_API_KEY.id, apiKeyId: TEST_API_KEY.id },
      source: "api",
      operationFamily: input.operationFamily,
      operationType: input.operationType,
      asset: null,
      amount: null,
      destination: null,
      context: {},
      providerExtensions: {},
      idempotencyKey: null,
      rawPayload: {},
      createdAt: "2026-06-18T00:00:00.000Z",
    },
    walletPolicy: {
      source: "implicit_default_allow",
      profileId: null,
      revisionId: null,
      defaultAction: "allow",
      decision: "allow",
      requiresApproval: false,
    },
    apiKeyPolicy: null,
  };
}

async function createActiveApiKeyControlProfile(
  repository: PolicyRepository,
  input: {
    name: string;
    defaultAction?: PolicyDefaultAction;
    rules?: PolicyRule[];
  }
): Promise<{
  profile: ApiKeyControlProfileRow;
  revision: ApiKeyControlProfileRevisionRow;
}> {
  const profile = await repository.createApiKeyControlProfile({
    organizationId: TEST_ORG.id,
    projectId: TEST_PROJECT.id,
    apiKeyId: TEST_API_KEY.id,
    name: input.name,
    createdBy: TEST_USER.id,
  });
  expect(profile).not.toBeNull();

  const revision = await repository.createApiKeyControlProfileRevision({
    profileId: profile?.id ?? "",
    rules: input.rules,
    defaultAction: input.defaultAction,
    createdBy: TEST_USER.id,
  });
  expect(revision).not.toBeNull();

  await repository.activateApiKeyControlProfileRevision({
    profileId: profile?.id ?? "",
    revisionId: revision?.id ?? "",
  });

  return {
    profile: profile as ApiKeyControlProfileRow,
    revision: revision as ApiKeyControlProfileRevisionRow,
  };
}
