/**
 * Integration tests for the Intelligent Agent Memory System.
 *
 * These tests exercise the MCP tools end-to-end via the Harmony API.
 * Prerequisites:
 *   1. `supabase db push` (migration applied)
 *   2. MCP server configured with valid API key
 *   3. Active workspace and project set
 *
 * Run with: bun test packages/mcp-server/src/__tests__/integration-memory-system.test.ts
 *
 * These tests create real entities and clean them up afterwards.
 * If a test fails mid-way, you may need to manually delete leftover entities.
 */
import { afterAll, describe, expect, test } from "bun:test";
import { getClient } from "../api-client.js";
import { getActiveProjectId, getActiveWorkspaceId, isConfigured, loadConfig, } from "../config.js";
// Track entities created during tests for cleanup
const createdEntityIds = [];
// Skip all tests if MCP server isn't configured
const configured = (() => {
    try {
        loadConfig();
        return isConfigured() && !!getActiveWorkspaceId();
    }
    catch {
        return false;
    }
})();
// Check if the tier migration has been applied by testing a create
const migrationApplied = await (async () => {
    if (!configured)
        return false;
    try {
        const client = getClient();
        const result = await client.createMemoryEntity({
            workspace_id: getActiveWorkspaceId(),
            project_id: getActiveProjectId() || undefined,
            type: "context",
            scope: getActiveProjectId() ? "project" : "workspace",
            memory_tier: "draft",
            title: "[TEST] Migration check - delete me",
            content: "Checking if memory_tier column exists.",
            agent_identifier: "test-runner",
        });
        const entity = result.entity;
        const hasTier = entity.memory_tier === "draft";
        // Clean up probe entity
        if (entity.id) {
            await client.deleteMemoryEntity(entity.id).catch(() => { });
        }
        return hasTier;
    }
    catch {
        return false;
    }
})();
const describeIf = configured ? describe : describe.skip;
const describeIfMigrated = configured && migrationApplied ? describe : describe.skip;
// Cleanup: delete all test entities
afterAll(async () => {
    if (!configured || createdEntityIds.length === 0)
        return;
    const client = getClient();
    for (const id of createdEntityIds) {
        try {
            await client.deleteMemoryEntity(id);
        }
        catch {
            // Entity may already be deleted
        }
    }
});
describeIfMigrated("Memory Tier System (integration)", () => {
    test("create entity with explicit tier", async () => {
        const client = getClient();
        const workspaceId = getActiveWorkspaceId();
        const projectId = getActiveProjectId() || undefined;
        const result = await client.createMemoryEntity({
            workspace_id: workspaceId,
            project_id: projectId,
            type: "context",
            scope: projectId ? "project" : "workspace",
            memory_tier: "draft",
            title: "[TEST] Draft memory tier test",
            content: "This is a test draft memory.",
            tags: ["test", "integration"],
            agent_identifier: "test-runner",
        });
        const entity = result.entity;
        expect(entity.id).toBeTruthy();
        expect(entity.memory_tier).toBe("draft");
        createdEntityIds.push(entity.id);
    });
    test("create entity with default tier based on type", async () => {
        const client = getClient();
        const workspaceId = getActiveWorkspaceId();
        const projectId = getActiveProjectId() || undefined;
        // 'lesson' type should default to 'episode' tier
        const result = await client.createMemoryEntity({
            workspace_id: workspaceId,
            project_id: projectId,
            type: "lesson",
            scope: projectId ? "project" : "workspace",
            title: "[TEST] Lesson tier default",
            content: "Testing that lessons default to episode tier.",
            tags: ["test", "integration"],
            agent_identifier: "test-runner",
        });
        const entity = result.entity;
        expect(entity.id).toBeTruthy();
        expect(entity.memory_tier).toBe("episode");
        createdEntityIds.push(entity.id);
    });
    test("create pattern defaults to reference tier", async () => {
        const client = getClient();
        const workspaceId = getActiveWorkspaceId();
        const projectId = getActiveProjectId() || undefined;
        const result = await client.createMemoryEntity({
            workspace_id: workspaceId,
            project_id: projectId,
            type: "pattern",
            scope: projectId ? "project" : "workspace",
            title: "[TEST] Pattern tier default",
            content: "Testing that patterns default to reference tier.",
            tags: ["test", "integration"],
            agent_identifier: "test-runner",
        });
        const entity = result.entity;
        expect(entity.memory_tier).toBe("reference");
        createdEntityIds.push(entity.id);
    });
    test("update entity tier via promote", async () => {
        const client = getClient();
        const workspaceId = getActiveWorkspaceId();
        const projectId = getActiveProjectId() || undefined;
        // Create a draft
        const createResult = await client.createMemoryEntity({
            workspace_id: workspaceId,
            project_id: projectId,
            type: "context",
            scope: projectId ? "project" : "workspace",
            memory_tier: "draft",
            title: "[TEST] Promotion test draft",
            content: "Draft that will be promoted.",
            tags: ["test", "integration"],
            agent_identifier: "test-runner",
        });
        const entityId = createResult.entity
            .id;
        createdEntityIds.push(entityId);
        // Promote to episode
        const updateResult = await client.updateMemoryEntity(entityId, {
            memory_tier: "episode",
            metadata: {
                promoted_from_tier: "draft",
                promotion_reason: "test promotion",
                promoted_at: new Date().toISOString(),
            },
        });
        const updated = updateResult.entity;
        expect(updated.memory_tier).toBe("episode");
    });
});
describeIf("Context Assembly (integration)", () => {
    test("search returns entities with tier info", async () => {
        const client = getClient();
        const workspaceId = getActiveWorkspaceId();
        const projectId = getActiveProjectId() || undefined;
        // Create a searchable entity
        const createResult = await client.createMemoryEntity({
            workspace_id: workspaceId,
            project_id: projectId,
            type: "solution",
            scope: projectId ? "project" : "workspace",
            memory_tier: "reference",
            title: "[TEST] Unique search term xyzzy42",
            content: "A solution for testing context assembly search.",
            confidence: 0.95,
            tags: ["test", "context-assembly"],
            agent_identifier: "test-runner",
        });
        const entityId = createResult.entity
            .id;
        createdEntityIds.push(entityId);
        // Search for it
        const searchResult = await client.searchMemoryEntities(workspaceId, "xyzzy42", { project_id: projectId, limit: 5 });
        expect(searchResult.entities.length).toBeGreaterThan(0);
        const found = searchResult.entities.find((e) => e.id === entityId);
        expect(found).toBeTruthy();
        expect(found.memory_tier).toBe("reference");
    });
});
describeIf("Graph Walk (integration)", () => {
    test("create entities with relations and traverse", async () => {
        const client = getClient();
        const workspaceId = getActiveWorkspaceId();
        const projectId = getActiveProjectId() || undefined;
        const scope = projectId ? "project" : "workspace";
        // Create two related entities
        const errorResult = await client.createMemoryEntity({
            workspace_id: workspaceId,
            project_id: projectId,
            type: "error",
            scope,
            memory_tier: "reference",
            title: "[TEST] Graph walk error",
            content: "An error for graph walk testing.",
            tags: ["test", "graph-walk"],
            agent_identifier: "test-runner",
        });
        const errorId = errorResult.entity
            .id;
        createdEntityIds.push(errorId);
        const solutionResult = await client.createMemoryEntity({
            workspace_id: workspaceId,
            project_id: projectId,
            type: "solution",
            scope,
            memory_tier: "reference",
            title: "[TEST] Graph walk solution",
            content: "A solution for graph walk testing.",
            tags: ["test", "graph-walk"],
            agent_identifier: "test-runner",
        });
        const solutionId = solutionResult.entity
            .id;
        createdEntityIds.push(solutionId);
        // Create relation
        const relResult = await client.createMemoryRelation({
            source_id: errorId,
            target_id: solutionId,
            relation_type: "resolved_by",
            confidence: 1.0,
        });
        expect(relResult.relation.id).toBeTruthy();
        // Verify relations via getRelatedEntities
        const related = await client.getRelatedEntities(errorId);
        expect(related.outgoing.length).toBeGreaterThan(0);
        // API returns relations with embedded target entity, not flat target_id
        const outRel = related.outgoing.find((r) => {
            const rel = r;
            const target = rel.target;
            return target?.id === solutionId || rel.target_id === solutionId;
        });
        expect(outRel).toBeTruthy();
    });
});
describeIf("Vault Index with Tiers (integration)", () => {
    test("vault index includes tier information", async () => {
        const client = getClient();
        const workspaceId = getActiveWorkspaceId();
        const projectId = getActiveProjectId() || undefined;
        let result;
        try {
            result = await client.getVaultIndex({
                workspace_id: workspaceId,
                project_id: projectId,
                limit: 10,
            });
        }
        catch (e) {
            // Endpoint may not be deployed yet - skip gracefully
            const msg = e instanceof Error ? e.message : String(e);
            if (msg.includes("Unknown endpoint")) {
                console.log("Skipping: vault index endpoint not deployed yet");
                return;
            }
            throw e;
        }
        expect(result.entities).toBeDefined();
        // If there are entities, check they have tier info
        if (result.entities.length > 0) {
            const first = result.entities[0];
            // memory_tier might be present if migration is applied
            if (first.memory_tier !== undefined) {
                expect(["draft", "episode", "reference"]).toContain(first.memory_tier);
            }
        }
    });
});
