/**
 * Knowledge Base Query API
 * POST - Query the knowledge base using Pinecone multimodal RAG (primary)
 *        with fallback to keyword search
 */

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { getAuthenticatedUser } from "@/lib/utils/auth-helpers.util";
import { KnowledgeBaseService } from "@/lib/services/knowledge-base.service";
import { PineconeMultimodalService } from "@/lib/services/pinecone-multimodal.service";
import { validateCSRFToken } from "@/lib/csrf";
import { rateLimiters, applyRateLimit } from "@/lib/rate-limiter";
import { logger } from "@/lib/logger";

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

/**
 * POST /api/dashboard/knowledge-base/query
 * Query the knowledge base using Pinecone multimodal RAG (primary)
 * or fallback to keyword search when Pinecone is not configured.
 *
 * Supports:
 * - JSON body: { query, language, maxResults, useGeminiRAG }
 * - multipart/form-data with image field for image-based similarity search
 */
export async function POST(request: NextRequest) {
  try {
    // Rate limiting - more aggressive for queries
    const rateLimitResponse = await applyRateLimit(
      request,
      rateLimiters.authGeneral,
    );
    if (rateLimitResponse) {
      return rateLimitResponse;
    }

    const user = await getAuthenticatedUser(request, auth);

    if (!user) {
      return NextResponse.json(
        { success: false, error: "Unauthorized" },
        { status: 401 },
      );
    }

    // CSRF protection
    if (!validateCSRFToken(request)) {
      return NextResponse.json(
        { success: false, error: "Invalid CSRF token" },
        { status: 403 },
      );
    }

    // Parse request — handle both JSON and multipart/form-data (image queries)
    const contentType = request.headers.get("content-type") || "";
    let query: string = "";
    let language: string = "en";
    let maxResults: number | undefined;
    let useGeminiRAG = false;
    let imageBuffer: Buffer | null = null;

    if (contentType.includes("multipart/form-data")) {
      // Image-based query
      const formData = await request.formData();
      const imageFile = formData.get("image") as File | null;
      if (imageFile) {
        const arrayBuffer = await imageFile.arrayBuffer();
        imageBuffer = Buffer.from(arrayBuffer);
      }
      query =
        (formData.get("query") as string) || "Find similar items to this image";
      language = (formData.get("language") as string) || "en";
      maxResults = formData.get("maxResults")
        ? parseInt(formData.get("maxResults") as string, 10)
        : undefined;
    } else {
      // Text-based query (JSON)
      const body = await request.json();
      query = body.query;
      language = body.language || "en";
      maxResults = body.maxResults;
      useGeminiRAG = body.useGeminiRAG === true;
    }

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

    // Check if knowledge base is enabled
    const settings = await KnowledgeBaseService.getOrCreateSettings(
      user.userId,
    );

    if (!settings.isEnabled) {
      return NextResponse.json(
        { success: false, error: "Knowledge base is disabled" },
        { status: 403 },
      );
    }

    // --- PRIMARY: Pinecone multimodal RAG ---
    if (PineconeMultimodalService.isConfigured() && !useGeminiRAG) {
      scopedLogger.info("Using Pinecone multimodal RAG", {
        userId: user.userId,
        hasImage: !!imageBuffer,
      });

      // If an image was provided, generate a text description for query
      let effectiveQuery = query.trim();
      if (imageBuffer) {
        try {
          // Generate a description of the image to use as the query text
          const embedding = await PineconeMultimodalService.generateEmbedding(
            imageBuffer,
            "image/jpeg",
          );
          // Use the image embedding directly via queryMultimodal won't work here,
          // so we generate a description and use text-based query
          void embedding; // embedding generated as side effect of description
        } catch {
          scopedLogger.warn(
            "Image description generation failed, using text query only",
          );
        }
      }

      const result = await PineconeMultimodalService.queryAndGenerate(
        user.userId,
        effectiveQuery,
        {
          language: language as "en" | "ar",
          topK: maxResults || 10,
          customInstructions: settings.customInstructions || undefined,
        },
      );

      return NextResponse.json({
        success: result.success,
        answer: result.answer,
        sources: result.citations.map((c) => ({
          id: c.documentId,
          documentId: c.documentId,
          documentTitle: c.documentTitle,
          content: c.excerpt,
          relevanceScore: c.relevanceScore || 0,
          mediaType: c.mediaType,
          mediaUrl: c.mediaUrl,
        })),
        mediaResults: result.mediaResults || [],
        aiMetadata: {
          model: result.metadata.model,
          queryTimeMs: result.metadata.queryTimeMs,
          ragEngine: "pinecone-multimodal",
          totalMatches: result.metadata.totalMatches,
        },
      });
    }

    // --- FALLBACK: Keyword search ---
    scopedLogger.info("Falling back to keyword search", {
      userId: user.userId,
      reason: PineconeMultimodalService.isConfigured()
        ? "useGeminiRAG explicitly requested"
        : "Pinecone not configured",
    });

    // Search the knowledge base
    const results = await KnowledgeBaseService.searchKnowledgeBase(
      user.userId,
      query.trim(),
      {
        maxResults: maxResults || settings.maxChunksPerQuery,
        includeChunks: true,
        includeFAQs: true,
      },
    );

    // Format response based on language preference
    const isArabic = language === "ar";
    const formattedFAQs = results.faqs.map((faq) => ({
      id: faq.id,
      question: isArabic && faq.questionAr ? faq.questionAr : faq.questionEn,
      answer: isArabic && faq.answerAr ? faq.answerAr : faq.answerEn,
      category: faq.category,
    }));

    scopedLogger.info("Knowledge base queried (keyword fallback)", {
      userId: user.userId,
      queryLength: query.length,
      resultsCount: results.chunks.length + results.faqs.length,
    });

    return NextResponse.json({
      success: true,
      sources: results.chunks,
      relatedFAQs: formattedFAQs,
      aiMetadata: {
        ragEngine: "keyword-search",
      },
    });
  } catch (error) {
    scopedLogger.error("Failed to query knowledge base", error);
    return NextResponse.json(
      { success: false, error: "Failed to query knowledge base" },
      { status: 500 },
    );
  }
}
