import { prisma } from "@/lib/db/prisma";
import type { KnowledgeSource } from "@/lib/ai/types";

function plainText(value: unknown): string {
  if (typeof value === "string") return value;
  if (Array.isArray(value)) return value.map(plainText).join(" ");
  if (value && typeof value === "object") {
    const node = value as Record<string, unknown>;
    return [typeof node.text === "string" ? node.text : "", plainText(node.content)].filter(Boolean).join(" ");
  }
  return "";
}

export async function retrieveKnowledge(question: string, preferredMaterialId?: string, classId?: string): Promise<KnowledgeSource[]> {
  const keywords = [...new Set(question.toLowerCase().split(/[^a-z0-9+#.]+/i).filter((word) => word.length >= 3))].slice(0, 6);
  const access = { OR: [{ visibility: "PUBLIC" as const }, ...(classId ? [{ visibility: "STUDENT_ONLY" as const, classId }] : [])] };
  const preferred = preferredMaterialId ? await prisma.material.findFirst({ where: { id: preferredMaterialId, status: "PUBLISHED", ...access }, select: { title: true, slug: true, description: true, content: true } }) : null;
  if (!keywords.length) return preferred ? [{ title: preferred.title, slug: preferred.slug, excerpt: `${preferred.description ?? ""}\n${plainText(preferred.content)}`.replace(/\s+/g, " ").trim().slice(0, 4000) }] : [];
  const materials = await prisma.material.findMany({
    where: { status: "PUBLISHED", ...access, AND: { OR: keywords.flatMap((word) => [{ title: { contains: word } }, { description: { contains: word } }]) }, ...(preferredMaterialId ? { id: { not: preferredMaterialId } } : {}) },
    orderBy: [{ viewCount: "desc" }, { publishedAt: "desc" }],
    take: 5,
    select: { title: true, slug: true, description: true, content: true },
  });
  return [...(preferred ? [preferred] : []), ...materials].slice(0, 5).map((material) => ({ title: material.title, slug: material.slug, excerpt: `${material.description ?? ""}\n${plainText(material.content)}`.replace(/\s+/g, " ").trim().slice(0, 4000) }));
}
