/**
 * GDPR Subject Access Export (Article 15).
 *
 * Gathers all data held on a specific contact across Neo4j stores:
 *   Person → AccessGrants (via relationship)
 *   Person → Conversations + Messages (via Person.sessionId → Conversation.sessionId)
 *   Person → email-source KnowledgeDocuments (via Person.email matching the KD's FROM/TO/CC edges)
 *
 * Returns a self-contained JSON document suitable for handing to the data subject.
 */
import { getSession } from "../lib/neo4j.js";
import { resolvePersonMatch } from "../lib/resolve-person.js";
export async function contactExport(params) {
    const { nodeId, email, telephone, accountId } = params;
    const startMs = Date.now();
    const { matchClause, queryParams } = resolvePersonMatch({ nodeId, email, telephone }, accountId);
    const session = getSession();
    try {
        // Step 1: Resolve Person node
        const personResult = await session.run(`${matchClause} RETURN p, elementId(p) AS nodeId`, queryParams);
        if (personResult.records.length === 0) {
            const identifier = email ?? telephone ?? nodeId ?? "unknown";
            console.error(JSON.stringify({
                tool: "contact-export",
                status: "not-found",
                identifier,
                latencyMs: Date.now() - startMs,
            }));
            throw new Error("Contact not found");
        }
        const personRecord = personResult.records[0];
        const personNodeId = personRecord.get("nodeId");
        const personProps = personRecord.get("p").properties;
        const person = {
            nodeId: personNodeId,
            properties: personProps,
        };
        // Step 2: Gather AccessGrants via relationship
        const grantsResult = await session.run(`MATCH (p:Person)-[:HAS_ACCESS]->(g:AccessGrant)
       WHERE elementId(p) = $personNodeId
       RETURN g, elementId(g) AS gNodeId`, { personNodeId });
        const accessGrants = grantsResult.records.map((r) => ({
            nodeId: r.get("gNodeId"),
            properties: r.get("g").properties,
        }));
        // Step 3: Gather Conversations + Messages via Person.sessionId
        const conversations = [];
        const sessionId = personProps.sessionId;
        if (sessionId) {
            const convResult = await session.run(`MATCH (c:Conversation {sessionId: $sessionId, accountId: $accountId})
         RETURN c, elementId(c) AS cNodeId`, { sessionId, accountId });
            for (const convRecord of convResult.records) {
                const cNodeId = convRecord.get("cNodeId");
                const convProps = convRecord.get("c").properties;
                const msgResult = await session.run(`MATCH (m:Message)-[:PART_OF]->(c:Conversation)
           WHERE elementId(c) = $cNodeId
           RETURN m, elementId(m) AS mNodeId
           ORDER BY m.createdAt ASC`, { cNodeId });
                const messages = msgResult.records.map((r) => ({
                    nodeId: r.get("mNodeId"),
                    properties: r.get("m").properties,
                }));
                conversations.push({
                    nodeId: cNodeId,
                    properties: convProps,
                    messages,
                });
            }
        }
        // Step 4: Gather email-source :KnowledgeDocument threads via Person edges.
        // Task 321 retired :Email; an email thread is one :KD{source:'email'}
        // with FROM/TO/CC edges to :Person.
        const emails = [];
        const personEmail = personProps.email;
        if (personEmail) {
            const emailResult = await session.run(`MATCH (kd:KnowledgeDocument {source: 'email', accountId: $accountId})
         MATCH (p:Person {email: $personEmail})
         WHERE (kd)-[:FROM]->(p) OR (kd)-[:TO]->(p) OR (kd)-[:CC]->(p)
         RETURN kd, elementId(kd) AS eNodeId
         ORDER BY kd.lastReceivedAt DESC`, { personEmail, accountId });
            for (const r of emailResult.records) {
                emails.push({
                    nodeId: r.get("eNodeId"),
                    properties: r.get("kd").properties,
                });
            }
        }
        const totalMessages = conversations.reduce((sum, c) => sum + c.messages.length, 0);
        console.error(JSON.stringify({
            tool: "contact-export",
            status: "success",
            identifier: email ?? telephone ?? nodeId,
            attributionPaths: [
                ...(sessionId ? ["sessionId"] : []),
                ...(personEmail ? ["email"] : []),
            ],
            counts: {
                accessGrants: accessGrants.length,
                conversations: conversations.length,
                messages: totalMessages,
                emails: emails.length,
            },
            latencyMs: Date.now() - startMs,
        }));
        return {
            person,
            accessGrants,
            conversations,
            emails,
            summary: {
                accessGrantCount: accessGrants.length,
                conversationCount: conversations.length,
                messageCount: totalMessages,
                emailCount: emails.length,
            },
        };
    }
    finally {
        await session.close();
    }
}
//# sourceMappingURL=contact-export.js.map