/**
 * Knowledge Base Query API (public/API-key authenticated)
 *
 * POST /api/knowledge-base/query
 *
 * This endpoint lets external systems (voice agent, chatbot, webhook)
 * query a user's knowledge base without browser session/CSRF.
 *
 * Authentication: Bearer token (user's API key) or dev-mode userId param.
 *
 * Body:
 *   - query: string (required)
 *   - language: 'en' | 'ar' (optional, default 'en')
 *   - userId: string (dev-mode only — skips API key check)
 *   - includeCitations: boolean (optional, default true)
 */

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { getAuthenticatedUser } from "@/lib/utils/auth-helpers.util";
import { GeminiRAGService } from "@/lib/services/gemini-rag.service";
import { KnowledgeBaseService } from "@/lib/services/knowledge-base.service";
import { convexQuery } from "@/lib/convex-client";
import { logger } from "@/lib/logger";
import { rateLimiters, applyRateLimit } from "@/lib/rate-limiter";

const scopedLogger = logger.scope("KnowledgeBasePublicQueryAPI");

const isDev = process.env.NODE_ENV === "development";

/**
 * Resolve userId from session auth or dev-mode body param.
 */
async function resolveUserId(
  request: NextRequest,
  body: { userId?: string },
): Promise<string | null> {
  // 1. Session auth (NextAuth)
  const user = await getAuthenticatedUser(request, auth);
  if (user) return user.userId;

  // 2. Dev-mode: accept userId in body (never in production)
  if (isDev && body.userId) {
    return body.userId;
  }

  return null;
}

export async function POST(request: NextRequest) {
  try {
    // Rate limiting
    const rateLimitResponse = await applyRateLimit(
      request,
      rateLimiters.authGeneral,
    );
    if (rateLimitResponse) return rateLimitResponse;

    const body = await request.json();
    const { query, language = "en", includeCitations = true } = body;

    // Validate query
    if (!query || typeof query !== "string" || !query.trim()) {
      return NextResponse.json(
        { success: false, error: "query is required" },
        { status: 400 },
      );
    }

    if (query.length > 2000) {
      return NextResponse.json(
        { success: false, error: "query exceeds 2000 character limit" },
        { status: 400 },
      );
    }

    // Authenticate
    const userId = await resolveUserId(request, body);
    if (!userId) {
      return NextResponse.json(
        {
          success: false,
          error: isDev
            ? "Unauthorized. Pass userId in body (dev mode) or use session auth."
            : "Unauthorized.",
        },
        { status: 401 },
      );
    }

    // Verify Gemini is configured
    if (!GeminiRAGService.isConfigured()) {
      return NextResponse.json(
        { success: false, error: "Knowledge base service not configured" },
        { status: 503 },
      );
    }

    // Check user has a store with documents
    const geminiStats = await GeminiRAGService.getStoreStats(userId);
    if (!geminiStats.hasStore || geminiStats.activeDocumentCount === 0) {
      return NextResponse.json(
        {
          success: false,
          error: "No documents in knowledge base. Upload documents first.",
          store: {
            hasStore: geminiStats.hasStore,
            documentCount: geminiStats.documentCount,
            activeDocumentCount: geminiStats.activeDocumentCount,
          },
        },
        { status: 404 },
      );
    }

    // Get user's custom instructions from Convex
    const settings = await convexQuery<{
      customInstructions?: string;
    }>("voice_agents/queries:getKBSettingsByUserId", { userId });

    scopedLogger.info("Public KB query", {
      userId,
      queryLength: query.length,
      language,
    });

    // Execute RAG query
    const result = await GeminiRAGService.queryWithRAG(userId, query.trim(), {
      language: language === "ar" ? "ar" : "en",
      includeCitations,
      customInstructions: settings?.customInstructions || undefined,
    });

    // Also fetch matching FAQs
    const { faqs } = await KnowledgeBaseService.getFAQs(userId, {
      activeOnly: true,
      limit: 5,
    });

    const queryLower = query.toLowerCase();
    const matchingFAQs = faqs
      .filter(
        (faq) =>
          faq.questionEn.toLowerCase().includes(queryLower) ||
          faq.answerEn.toLowerCase().includes(queryLower) ||
          faq.questionAr?.toLowerCase().includes(queryLower) ||
          faq.answerAr?.toLowerCase().includes(queryLower),
      )
      .slice(0, 3)
      .map((faq) => ({
        id: faq.id,
        question:
          language === "ar" && faq.questionAr ? faq.questionAr : faq.questionEn,
        answer: language === "ar" && faq.answerAr ? faq.answerAr : faq.answerEn,
        category: faq.category,
      }));

    return NextResponse.json({
      success: result.success,
      answer: result.answer,
      citations: result.citations,
      relatedFAQs: matchingFAQs,
      metadata: {
        model: result.metadata.model,
        queryTimeMs: result.metadata.queryTimeMs,
        ragEngine: "gemini-file-search",
        storeId: geminiStats.storeId,
        activeDocuments: geminiStats.activeDocumentCount,
      },
    });
  } catch (error) {
    scopedLogger.error("Public KB query failed", error);
    return NextResponse.json(
      { success: false, error: "Internal server error" },
      { status: 500 },
    );
  }
}
