/**
 * Interests storage
 *
 * Per-(agent, user) "interests" memory, backed by the org-scoped `kv` table.
 * Scoped by agent so each agent keeps its own view — agent A never sees or
 * updates agent B's interests for the same user. The curator/agent rewrites
 * the whole list, so the shape is intentionally tiny.
 */

import type { KVStorage } from "./kv";

export interface Interest {
  title: string;
  summary: string;
}

export interface InterestsDoc {
  /** Ordered, most important first. */
  interests: Interest[];
}

/** Reserved `kv` key prefix for interests docs. The generic kv REST API
 *  rejects keys under this prefix so per-agent memory can't be read or
 *  tampered with by other org members through `/api/:org/kv/:key`. */
export const INTERESTS_KEY_PREFIX = "interests:";

const key = (agentId: string, userId: string) =>
  `${INTERESTS_KEY_PREFIX}${agentId}:${userId}`;

/** Defensively coerce a raw kv row into a doc — guards against malformed or
 *  externally-written values that don't match the expected shape. */
function toInterestsDoc(
  row: Record<string, unknown> | null,
): InterestsDoc | null {
  if (!row || !Array.isArray(row.interests)) return null;
  return { interests: row.interests as Interest[] };
}

export interface InterestsStorage {
  getForAgent(
    orgId: string,
    agentId: string,
    userId: string,
  ): Promise<InterestsDoc | null>;
  setForAgent(
    orgId: string,
    agentId: string,
    userId: string,
    doc: InterestsDoc,
  ): Promise<void>;
}

export class KyselyInterestsStorage implements InterestsStorage {
  constructor(private kv: KVStorage) {}

  async getForAgent(
    orgId: string,
    agentId: string,
    userId: string,
  ): Promise<InterestsDoc | null> {
    const row = await this.kv.get(orgId, key(agentId, userId));
    return toInterestsDoc(row);
  }

  async setForAgent(
    orgId: string,
    agentId: string,
    userId: string,
    doc: InterestsDoc,
  ): Promise<void> {
    await this.kv.set(
      orgId,
      key(agentId, userId),
      doc as unknown as Record<string, unknown>,
    );
  }
}
