/**
 * groups/ltm.ts — LTM (Long-Term Memory) HTTP API group
 *
 * 외부 앱(chowriter 등)이 saeeol LTM에 기억을 저장/검색하는 엔드포인트.
 */

import { Schema } from "effect"
import { HttpApi, HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
import { Authorization } from "../middleware/authorization"
import { InstanceContextMiddleware } from "../middleware/instance-context"
import { WorkspaceRoutingMiddleware } from "../middleware/workspace-routing"
import { described } from "./metadata"

const root = "/ltm"

// Request schemas
const IngestPayload = Schema.Struct({
  type: Schema.Literal("episodic", "semantic", "procedural"),
  content: Schema.String,
  summary: Schema.String,
  projectID: Schema.optional(Schema.String),
  sessionID: Schema.optional(Schema.String),
  tags: Schema.optional(Schema.mutable(Schema.Array(Schema.String))),
})

const SearchPayload = Schema.Struct({
  query: Schema.String,
  topK: Schema.optional(Schema.Number),
  minScore: Schema.optional(Schema.Number),
  type: Schema.optional(Schema.Literal("episodic", "semantic", "procedural")),
  projectID: Schema.optional(Schema.String),
})

const DeletePayload = Schema.Struct({
  ids: Schema.mutable(Schema.Array(Schema.String)),
})

// Response schemas
const MemoryEntry = Schema.Struct({
  id: Schema.String,
  type: Schema.String,
  summary: Schema.String,
  content: Schema.String,
  score: Schema.optional(Schema.Number),
  metadata: Schema.Struct({
    source: Schema.String,
    timestamp: Schema.Number,
    projectID: Schema.optional(Schema.String),
    tags: Schema.mutable(Schema.Array(Schema.String)),
  }),
})

const IngestResponse = Schema.Struct({
  id: Schema.String,
  success: Schema.Boolean,
})

const SearchResponse = Schema.Struct({
  memories: Schema.mutable(Schema.Array(MemoryEntry)),
  count: Schema.Number,
})

const DeleteResponse = Schema.Struct({
  removed: Schema.Number,
})

export const LTMHttpApi = HttpApi.make("ltm")
  .add(
    HttpApiGroup.make(root, "ltm")
      .add(
        HttpApiEndpoint.post("ingest", `${root}/ingest`)
          .setPayload(IngestPayload)
          .addSuccess(IngestResponse)
          .annotateMerge(OpenApi.annotations({ identifier: "ltm.ingest", summary: "Store a memory in LTM" })),
      )
      .add(
        HttpApiEndpoint.post("search", `${root}/search`)
          .setPayload(SearchPayload)
          .addSuccess(SearchResponse)
          .annotateMerge(OpenApi.annotations({ identifier: "ltm.search", summary: "Search LTM memories by query" })),
      )
      .add(
        HttpApiEndpoint.post("delete", `${root}/delete`)
          .setPayload(DeletePayload)
          .addSuccess(DeleteResponse)
          .annotateMerge(OpenApi.annotations({ identifier: "ltm.delete", summary: "Delete LTM memories by ID" })),
      )
      .add(
        HttpApiEndpoint.get("status", `${root}/status`)
          .addSuccess(Schema.Struct({ enabled: Schema.Boolean, memoryCount: Schema.Number }))
          .annotateMerge(OpenApi.annotations({ identifier: "ltm.status", summary: "Get LTM status" })),
      ),
  )
