import { randomUUID } from "node:crypto";
import { writeFile, unlink } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { getSession } from "../lib/neo4j.js";
import { memoryIngestExtract } from "./memory-ingest-extract.js";
import { withWriteEvent } from "../lib/log-ingest.js";
const TITLE_MAX = 200;
function cap(s) {
    return s.length > TITLE_MAX ? s.slice(0, TITLE_MAX) : s;
}
export function extractTitle(content, url, callerTitle) {
    if (callerTitle) {
        const trimmed = callerTitle.trim();
        if (trimmed.length > 0)
            return { title: cap(trimmed), source: "caller" };
    }
    const h1Match = content.match(/^#\s+(.+)$/m);
    if (h1Match) {
        const t = h1Match[1].trim();
        if (t.length > 0)
            return { title: cap(t), source: "h1" };
    }
    const slug = urlSlug(url);
    if (slug)
        return { title: cap(slug), source: "url-slug" };
    return { title: url, source: "url" };
}
function urlSlug(url) {
    let pathname;
    try {
        pathname = new URL(url).pathname;
    }
    catch {
        return null;
    }
    const segments = pathname.split("/").filter((s) => s.length > 0);
    if (segments.length === 0)
        return null;
    const last = segments[segments.length - 1];
    const cleaned = last
        .replace(/\.[a-zA-Z0-9]{1,5}$/, "")
        .replace(/[-_]+/g, " ")
        .trim();
    return cleaned.length > 0 ? cleaned : null;
}
async function checkExistingDocument(url, accountId) {
    const session = getSession();
    try {
        const result = await session.run(`MATCH (d:KnowledgeDocument { sourceUrl: $url, accountId: $accountId })
       RETURN elementId(d) AS nodeId, d.name AS name, d.summary AS summary, d.createdAt AS createdAt
       LIMIT 1`, { url, accountId });
        if (result.records.length === 0)
            return undefined;
        const r = result.records[0];
        return {
            nodeId: r.get("nodeId"),
            name: r.get("name"),
            summary: r.get("summary"),
            ingestedAt: r.get("createdAt"),
        };
    }
    catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        console.error(`[memory-ingest-web] dedup check failed (skipping): ${msg}`);
        return undefined;
    }
    finally {
        await session.close();
    }
}
export async function memoryIngestWeb(params) {
    return withWriteEvent({ tool: "memory-ingest-web", accountId: params.accountId, name: params.url }, () => memoryIngestWebImpl(params), (r) => ({ elementId: r.attachmentId, name: r.title }));
}
async function memoryIngestWebImpl(params) {
    const { accountId, url, content, scope, title: callerTitle } = params;
    const t0 = Date.now();
    const log = (stage, detail) => console.error(`[memory-ingest-web] [${url.slice(0, 60)}] ${stage}${detail ? ` — ${detail}` : ""} (${Date.now() - t0}ms)`);
    log("start", `${content.length} chars, scope=${scope ?? "public"}`);
    const trimmed = content.trim();
    if (trimmed.length === 0) {
        throw new Error("Web content is empty. The page may not have readable text, " +
            "or WebFetch may have failed to extract content from this URL.");
    }
    log("dedup-check");
    const existingDocument = await checkExistingDocument(url, accountId);
    if (existingDocument) {
        log("dedup-found", `existing: ${existingDocument.nodeId.slice(0, 12)}, ingested ${existingDocument.ingestedAt}`);
    }
    const { title, source: titleSource } = extractTitle(trimmed, url, callerTitle);
    log("title", `${title.slice(0, 80)} (title-source=${titleSource})`);
    const attachmentId = randomUUID();
    const tempPath = join(tmpdir(), `maxy-web-${attachmentId}.md`);
    try {
        log("temp-write", tempPath);
        await writeFile(tempPath, trimmed, "utf-8");
        log("extract-start");
        const extract = await memoryIngestExtract({
            storagePath: tempPath,
            filename: title,
            mimeType: "text/markdown",
            attachmentId,
        });
        log("extract-done", `${extract.textLength} chars cached`);
        return { attachmentId, title, titleSource, extract, existingDocument };
    }
    finally {
        try {
            await unlink(tempPath);
        }
        catch {
            // Best-effort cleanup — tmp dir is periodically cleaned by OS
        }
    }
}
//# sourceMappingURL=memory-ingest-web.js.map