import { chunkDocument } from "./chunking/chunker-runner.js";
import { createCapsule } from "./capsule-lifecycle.js";
import { insertDocumentRow, insertParsedUnitRow } from "./discovery/persist.js";
import { embedChunkBatch } from "./indexing/embedding-batcher.js";
import { addSourceToCapsule } from "./source-lifecycle.js";
const DEFAULT_EMBEDDING = {
    provider: "openai",
    modelId: "text-embedding-3-small",
    vectorDimensions: 1536,
    vectorMetric: "cosine",
};
export function deterministicVector(input, dimensions) {
    const vec = new Float32Array(dimensions);
    let hash = 0;
    for (let i = 0; i < input.length; i += 1) {
        hash = (hash * 31 + input.charCodeAt(i)) | 0;
    }
    vec[0] = input.length;
    for (let i = 1; i < dimensions; i += 1) {
        vec[i] = ((hash + i * 7) & 0xffff) / 0xffff;
    }
    return vec;
}
export function scriptedAdapter(options = {}) {
    const identity = options.identity ?? DEFAULT_EMBEDDING;
    const responder = options.responder ??
        ((request) => ({
            ok: true,
            value: {
                vector: deterministicVector(request.input, identity.vectorDimensions),
                modelId: identity.modelId,
                ...(identity.modelRevision !== undefined ? { modelRevision: identity.modelRevision } : {}),
            },
        }));
    return {
        endpoint: options.endpoint ?? "https://example.test/v1",
        apiKey: options.apiKey ?? ["sk-", "test"].join(""),
        request: async (request) => Promise.resolve(responder(request)),
    };
}
function sampleCapsuleInput(overrides) {
    return {
        id: overrides.id,
        displayName: overrides.displayName ?? "Engineering Capsule",
        tags: ["alpha", "beta"],
        retrievalEffort: "default",
        outputMode: "answers",
        answerGroundingPolicy: "require-citations",
        embeddingModelIdentity: overrides.embeddingModelIdentity,
        lifecycleState: "draft",
        storageReference: "engineering/capsule-1",
    };
}
function sampleSourceInput(id) {
    return {
        id,
        displayName: `Source ${String(id)}`,
        tags: [],
        scope: {
            kind: "folder",
            rootPath: "/srv/docs",
            recursive: true,
        },
    };
}
function composeUnit(unit, documentId, textLength) {
    if (unit !== undefined) {
        return { ...unit, documentId };
    }
    return {
        kind: "page",
        documentId,
        pageNumber: 7,
        pageLabel: "vii",
        characterStart: 0,
        characterEnd: textLength,
    };
}
function normalizeSeedText(unit, text) {
    const baseText = text ?? "alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu xi";
    const requiredEnd = unit !== undefined && unit.kind !== "unsupported-media" ? unit.characterEnd : 0;
    return baseText.length >= requiredEnd ? baseText : baseText.padEnd(requiredEnd, " x");
}
function resolveSeedOptions(options) {
    const capsuleId = (options.capsuleId ?? "cap-1");
    const sourceId = (options.sourceId ?? "src-1");
    const documentId = (options.documentId ?? "doc-1");
    const identity = options.identity ?? DEFAULT_EMBEDDING;
    const text = normalizeSeedText(options.unit, options.text);
    return {
        capsuleId,
        displayName: options.displayName ?? "Engineering Capsule",
        sourceId,
        documentId,
        identity,
        text,
        contentHash: options.contentHash ?? "a".repeat(64),
        safeDisplayName: options.safeDisplayName ?? "sample.txt",
        unit: composeUnit(options.unit, documentId, text.length),
        chunkingOptions: options.chunkingOptions ?? { maxTokens: 2, minTokens: 0, overlapTokens: 0 },
    };
}
function insertSeedRows(store, options) {
    createCapsule(store, sampleCapsuleInput({
        id: options.capsuleId,
        displayName: options.displayName,
        embeddingModelIdentity: options.identity,
    }));
    addSourceToCapsule(store, options.capsuleId, sampleSourceInput(options.sourceId));
    insertDocumentRow(store._internal.db, {
        id: options.documentId,
        capsuleId: options.capsuleId,
        sourceId: String(options.sourceId),
        documentPath: "docs/sample.txt",
        sizeBytes: 1024,
        mediaType: "text/plain",
        contentHash: options.contentHash,
        parserId: "text",
        parserVersion: "1",
        lastExtractedAt: 1_700_000_000_000,
        status: "extracted",
        safeDisplayName: options.safeDisplayName,
    });
    insertParsedUnitRow(store._internal.db, options.capsuleId, `unit-${String(options.capsuleId)}`, options.unit);
}
function buildSeedChunks(store, options) {
    const chunkResult = chunkDocument(store, {
        capsuleId: options.capsuleId,
        sourceId: options.sourceId,
        documentId: options.documentId,
        sourceText: options.text,
    }, options.chunkingOptions);
    return {
        chunkIds: chunkResult.chunkIds,
        chunks: chunkResult.chunkIds.map((id, index) => ({
            id,
            capsuleId: options.capsuleId,
            sourceId: options.sourceId,
            documentId: options.documentId,
            text: `chunk-${String(index)}-${String(options.capsuleId)}`,
        })),
    };
}
async function embedSeedChunks(store, identity, chunks) {
    let counter = 0;
    await embedChunkBatch(chunks, {
        adapter: scriptedAdapter({ identity }),
        store,
        pinnedIdentity: identity,
        concurrency: 2,
        now: () => 1_700_000_000_000,
        idSource: () => {
            counter += 1;
            return `storage-${String(counter)}`;
        },
    });
}
export async function seedCapsuleWithVectors(store, options = {}) {
    const resolved = resolveSeedOptions(options);
    insertSeedRows(store, resolved);
    const { chunkIds, chunks } = buildSeedChunks(store, resolved);
    await embedSeedChunks(store, resolved.identity, chunks);
    return {
        capsuleId: resolved.capsuleId,
        sourceId: resolved.sourceId,
        documentId: resolved.documentId,
        chunkIds,
        vectorTexts: chunks.map((chunk) => chunk.text),
    };
}
