/**
 * Field Library API routes
 *
 * CRUD over the workspace's reusable custom field definitions (the field
 * library). A definition is *soft* metadata — it drives the field picker and
 * agent awareness, but it never feeds SchemaRegistry, so applying a field is
 * an ordinary entity frontmatter write and an off-list value is never
 * rejected here.
 *
 * Auth: any authenticated member (no owner gate) — the global auth hook
 * already rejects unauthenticated callers when users exist. Open mode / API
 * key are admin-equivalent (no req.user), same as other routes.
 *
 * Persistence mirrors config-api: Workspace.writeConfig(next) →
 * workspaceManager.reloadConfig() (re-reads workspace.json into the live
 * in-memory config). No SchemaRegistry rebuild is needed — the library is not
 * compiled into Zod.
 *
 *   GET    /api/field-library
 *   POST   /api/field-library
 *   PUT    /api/field-library/:key
 *   DELETE /api/field-library/:key
 *   GET    /api/field-library/:key/usage?value=
 */
import { Workspace } from '../../core/workspace.js';
import { addFieldDef, updateFieldDef, removeFieldDef, getFieldDef, getFieldLibrary, FieldLibraryError, } from '../../core/field-library.js';
import { reqUser } from './graph-api-access.js';
function mapError(err) {
    switch (err.code) {
        case 'key_exists': return { status: 409, code: err.code };
        case 'key_not_found': return { status: 404, code: err.code };
        case 'invalid_field': return { status: 400, code: err.code };
        default: return { status: 400, code: 'invalid_field' };
    }
}
export async function registerFieldLibraryApiRoutes(fastify, workspaceManager, _authService) {
    /** Persist a config mutation: write workspace.json + refresh the live config. */
    async function persist(next) {
        const workspace = new Workspace(workspaceManager.getWorkspacePath());
        workspace.writeConfig(next);
        workspaceManager.reloadConfig();
    }
    // GET /api/field-library — list all definitions.
    fastify.get('/api/field-library', async (_req, reply) => {
        return reply.send({ fields: getFieldLibrary(workspaceManager.getConfig()) });
    });
    // POST /api/field-library — define a new field.
    fastify.post('/api/field-library', async (req, reply) => {
        const { key, label, options } = req.body ?? {};
        try {
            const next = addFieldDef(workspaceManager.getConfig(), {
                key,
                options,
                ...(label !== undefined ? { label } : {}),
                ...(reqUser(req)?.handle ? { created_by: reqUser(req).handle } : {}),
            });
            await persist(next);
        }
        catch (err) {
            if (err instanceof FieldLibraryError) {
                const { status, code } = mapError(err);
                return reply.status(status).send({ code, error: err.message });
            }
            throw err;
        }
        return reply.send({ ok: true, fields: getFieldLibrary(workspaceManager.getConfig()) });
    });
    // PUT /api/field-library/:key — edit options/label. Returns affected-entry
    // counts for any option values dropped by the edit (orphan warning).
    fastify.put('/api/field-library/:key', async (req, reply) => {
        const { key } = req.params;
        const body = req.body ?? {};
        const before = getFieldDef(workspaceManager.getConfig(), key);
        const affected = {};
        if (before?.options && Array.isArray(body.options)) {
            const nextSet = new Set(body.options);
            for (const v of before.options) {
                if (!nextSet.has(v))
                    affected[v] = workspaceManager.countEntitiesWithFieldValue(key, v);
            }
        }
        try {
            const next = updateFieldDef(workspaceManager.getConfig(), key, {
                ...(body.options !== undefined ? { options: body.options } : {}),
                ...(body.label !== undefined ? { label: body.label } : {}),
            });
            await persist(next);
        }
        catch (err) {
            if (err instanceof FieldLibraryError) {
                const { status, code } = mapError(err);
                return reply.status(status).send({ code, error: err.message });
            }
            throw err;
        }
        return reply.send({ ok: true, fields: getFieldLibrary(workspaceManager.getConfig()), affected });
    });
    // DELETE /api/field-library/:key — remove the definition. Entry values are
    // left on disk. Returns the count of entries that still held the field.
    fastify.delete('/api/field-library/:key', async (req, reply) => {
        const { key } = req.params;
        const affected = workspaceManager.countEntitiesWithFieldValue(key);
        try {
            const next = removeFieldDef(workspaceManager.getConfig(), key);
            await persist(next);
        }
        catch (err) {
            if (err instanceof FieldLibraryError) {
                const { status, code } = mapError(err);
                return reply.status(status).send({ code, error: err.message });
            }
            throw err;
        }
        return reply.send({ ok: true, fields: getFieldLibrary(workspaceManager.getConfig()), affected });
    });
    // GET /api/field-library/:key/usage?value= — entry counts behind the
    // orphan-warning before an option/field removal.
    fastify.get('/api/field-library/:key/usage', async (req, reply) => {
        const { key } = req.params;
        const { value } = req.query;
        const total = workspaceManager.countEntitiesWithFieldValue(key);
        const forValue = value !== undefined ? workspaceManager.countEntitiesWithFieldValue(key, value) : undefined;
        return reply.send({ total, ...(forValue !== undefined ? { value, count: forValue } : {}) });
    });
}
//# sourceMappingURL=field-library-api.js.map