import { randomUUID } from "node:crypto";
import { getSession } from "../lib/neo4j.js";
import { notTrashed } from "../../../../../lib/graph-trash/dist/index.js";
import { stampCreatedBy } from "../../../../../lib/graph-write/dist/index.js";
function generateGroupSlug(name) {
    const base = name
        .toLowerCase()
        .replace(/[^a-z0-9]+/g, "-")
        .replace(/^-|-$/g, "")
        .slice(0, 40);
    return base || "group";
}
export async function groupCreate(params) {
    const { groupName, agentSlug, participants, accountId, createdBy } = params;
    if (!participants || participants.length < 2) {
        throw new Error("At least 2 participants are required to create a group.");
    }
    const sessionId = randomUUID();
    let groupSlug = generateGroupSlug(groupName);
    const session = getSession();
    try {
        // Check slug uniqueness — only against live conversations. A trashed
        // conversation holding the same slug would otherwise force an
        // unnecessary slug suffix.
        const existing = await session.run(`MATCH (c:Conversation {groupSlug: $slug, accountId: $accountId})
       WHERE ${notTrashed("c")}
       RETURN count(c) AS cnt`, { slug: groupSlug, accountId });
        if ((existing.records[0]?.get("cnt")?.toNumber?.() ?? 0) > 0) {
            groupSlug = `${groupSlug}-${randomUUID().slice(0, 4)}`;
        }
        // Pre-resolve every participant so we reject the whole call if fewer
        // than one matches — creating a group Conversation with zero live
        // participants is a write-doctrine orphan. Participant
        // PARTICIPATES_IN edges are added inside the same transaction as the
        // Conversation node to guarantee ≥1 adjacency at commit time.
        const resolvedParticipants = [];
        const notFound = [];
        for (const identifier of participants) {
            const r = await session.run(`MATCH (p:Person {accountId: $accountId})
         WHERE (p.givenName + COALESCE(' ' + p.familyName, '') = $identifier
            OR p.email = $identifier
            OR p.telephone = $identifier)
           AND ${notTrashed("p")}
         RETURN elementId(p) AS id, p.givenName AS name LIMIT 1`, { accountId, identifier });
            if (r.records.length > 0) {
                resolvedParticipants.push({
                    identifier,
                    personId: r.records[0].get("id"),
                    givenName: r.records[0].get("name"),
                });
            }
            else {
                notFound.push(identifier);
            }
        }
        if (resolvedParticipants.length === 0) {
            throw new Error(`Write doctrine violated: group-create could not resolve any of the ${participants.length} participant(s) (${notFound.join(", ")}). A group Conversation with no live participants is an orphan.`);
        }
        const convoProps = stampCreatedBy({
            sessionId,
            accountId,
            agentType: "public",
            agentSlug,
            channel: "webchat",
            type: "group",
            groupName,
            groupSlug,
            createdBy: "admin",
        }, createdBy);
        await session.executeWrite(async (tx) => {
            await tx.run(`CREATE (c:Conversation $props)
         SET c.createdAt = datetime(), c.updatedAt = datetime()
         WITH c
         UNWIND $participantIds AS pid
         MATCH (p) WHERE elementId(p) = pid
         MERGE (p)-[r:PARTICIPATES_IN]->(c)
         ON CREATE SET r.joinedAt = datetime(), r.displayName = p.givenName`, {
                props: convoProps,
                participantIds: resolvedParticipants.map((p) => p.personId),
            });
        });
        const joined = resolvedParticipants.map((p) => p.givenName);
        const brandResult = await session.run(`MATCH (b:LocalBusiness {accountId: $accountId})
       RETURN b.hostname AS hostname`, { accountId });
        const hostname = brandResult.records[0]?.get("hostname");
        const baseUrl = hostname ? `https://${hostname}` : "https://maxy.bot";
        const shareableUrl = `${baseUrl}/g/${groupSlug}`;
        console.error(`[group] created id=${sessionId.slice(0, 8)}… slug=${groupSlug} participants=${joined.length}${notFound.length > 0 ? ` notFound=${notFound.length}` : ""}`);
        return { sessionId, groupSlug, joined, notFound, shareableUrl };
    }
    finally {
        await session.close();
    }
}
//# sourceMappingURL=group-create.js.map