/**
 * Knowledge Base AI Service
 *
 * Provides AI-powered answers using Gemini based on the user's
 * Knowledge Base content (FAQs and document chunks).
 *
 * Features:
 * - Searches user's KnowledgeBaseFAQ and KnowledgeBaseDocument chunks
 * - Uses Gemini API to generate contextual answers
 * - Respects user's KnowledgeBaseSettings (isEnabled, maxChunksPerQuery, etc.)
 * - Supports both English and Arabic responses
 */

import { GoogleGenAI } from '@google/genai';
import {
  knowledgeBaseSettingsAdapter,
  knowledgeBaseChunkAdapter,
  knowledgeBaseFAQAdapter,
} from '@/lib/adapters/voice-agents';
import { logger } from '@/lib/logger';
import type { KnowledgeBaseFAQ } from '@/lib/types/knowledge-base.types';

const scopedLogger = logger.scope('KBAIService');

// Initialize Gemini client
let geminiClient: GoogleGenAI | null = null;

function getGeminiClient(): GoogleGenAI {
  if (!geminiClient) {
    const apiKey = process.env.GOOGLE_API_KEY;
    if (!apiKey) {
      throw new Error('GOOGLE_API_KEY environment variable is not set');
    }
    geminiClient = new GoogleGenAI({ apiKey });
  }
  return geminiClient;
}

// Model for AI answer generation
const AI_MODEL = process.env.GEMINI_KB_MODEL || 'gemini-2.0-flash';

/**
 * Source reference for AI-generated answers
 */
export interface KBSource {
  type: 'faq' | 'document';
  id: string;
  title: string;
  excerpt?: string;
}

/**
 * AI Answer response
 */
export interface KBAIResponse {
  success: boolean;
  answer: string;
  sources: KBSource[];
  metadata: {
    queryTimeMs: number;
    model: string;
    language: 'en' | 'ar';
    chunksUsed: number;
    faqsUsed: number;
  };
  error?: string;
}

/**
 * Search result from local knowledge base
 */
interface SearchResult {
  chunks: Array<{
    id: string;
    documentId: string;
    documentTitle: string;
    content: string;
    relevanceScore: number;
  }>;
  faqs: Array<{
    id: string;
    questionEn: string;
    questionAr: string | null;
    answerEn: string;
    answerAr: string | null;
    category: string;
  }>;
}

/**
 * Knowledge Base AI Service
 * Generates AI-powered answers using user's knowledge base content
 */
export class KBAIService {
  /**
   * Check if the AI service is properly configured
   */
  static isConfigured(): boolean {
    return !!process.env.GOOGLE_API_KEY;
  }

  /**
   * Ask a question and get an AI-generated answer
   *
   * @param userId - The user's ID
   * @param query - The question to answer
   * @param options - Optional configuration
   * @returns AI-generated answer with source references
   */
  static async ask(
    userId: string,
    query: string,
    options?: {
      language?: 'en' | 'ar';
    }
  ): Promise<KBAIResponse> {
    const startTime = Date.now();
    const language = options?.language || 'en';

    try {
      // Get user's KB settings
      const settings = await knowledgeBaseSettingsAdapter.findUnique({
        where: { userId },
      }) as Record<string, unknown> | null;

      // Check if KB is enabled
      if (settings && !settings.isEnabled) {
        return {
          success: false,
          answer: language === 'ar'
            ? 'قاعدة المعرفة معطلة حالياً.'
            : 'Knowledge base is currently disabled.',
          sources: [],
          metadata: {
            queryTimeMs: Date.now() - startTime,
            model: AI_MODEL,
            language,
            chunksUsed: 0,
            faqsUsed: 0,
          },
          error: 'KNOWLEDGE_BASE_DISABLED',
        };
      }

      const maxChunks = (settings?.maxChunksPerQuery as number) || 5;
      const customInstructions = (settings?.customInstructions as string) || null;

      // Search the knowledge base for relevant content
      const searchResults = await this.searchKnowledgeBase(userId, query, {
        maxResults: maxChunks,
        language,
      });

      // Check if we found any content
      if (searchResults.chunks.length === 0 && searchResults.faqs.length === 0) {
        return {
          success: true,
          answer: language === 'ar'
            ? 'لم أتمكن من العثور على معلومات ذات صلة بسؤالك في قاعدة المعرفة. يرجى المحاولة بسؤال مختلف أو الاتصال بالدعم.'
            : 'I could not find relevant information in the knowledge base for your question. Please try a different question or contact support.',
          sources: [],
          metadata: {
            queryTimeMs: Date.now() - startTime,
            model: AI_MODEL,
            language,
            chunksUsed: 0,
            faqsUsed: 0,
          },
        };
      }

      // Generate AI answer using Gemini
      const aiResponse = await this.generateAnswer(
        query,
        searchResults,
        language,
        customInstructions
      );

      // Build source references
      const sources: KBSource[] = [];

      // Add FAQ sources
      for (const faq of searchResults.faqs) {
        sources.push({
          type: 'faq',
          id: faq.id,
          title: language === 'ar' && faq.questionAr
            ? faq.questionAr
            : faq.questionEn,
        });
      }

      // Add document chunk sources
      const seenDocIds = new Set<string>();
      for (const chunk of searchResults.chunks) {
        if (!seenDocIds.has(chunk.documentId)) {
          seenDocIds.add(chunk.documentId);
          sources.push({
            type: 'document',
            id: chunk.documentId,
            title: chunk.documentTitle,
            excerpt: chunk.content.slice(0, 150) + (chunk.content.length > 150 ? '...' : ''),
          });
        }
      }

      scopedLogger.info('AI answer generated', {
        userId,
        queryLength: query.length,
        language,
        chunksUsed: searchResults.chunks.length,
        faqsUsed: searchResults.faqs.length,
        queryTimeMs: Date.now() - startTime,
      });

      return {
        success: true,
        answer: aiResponse,
        sources,
        metadata: {
          queryTimeMs: Date.now() - startTime,
          model: AI_MODEL,
          language,
          chunksUsed: searchResults.chunks.length,
          faqsUsed: searchResults.faqs.length,
        },
      };
    } catch (error) {
      scopedLogger.error('Failed to generate AI answer', error, { userId });

      return {
        success: false,
        answer: language === 'ar'
          ? 'حدث خطأ أثناء معالجة سؤالك. يرجى المحاولة مرة أخرى.'
          : 'An error occurred while processing your question. Please try again.',
        sources: [],
        metadata: {
          queryTimeMs: Date.now() - startTime,
          model: AI_MODEL,
          language,
          chunksUsed: 0,
          faqsUsed: 0,
        },
        error: error instanceof Error ? error.message : 'Unknown error',
      };
    }
  }

  /**
   * Search the knowledge base for relevant content
   */
  private static async searchKnowledgeBase(
    userId: string,
    query: string,
    options: {
      maxResults: number;
      language: 'en' | 'ar';
    }
  ): Promise<SearchResult> {
    const { maxResults } = options;
    // Note: language parameter reserved for future language-specific search

    // Search for relevant document chunks
    // Using simple keyword matching - in production, use vector search
    const chunks = await (knowledgeBaseChunkAdapter.findMany as (args: Record<string, unknown>) => Promise<unknown[]>)({
      where: {
        KnowledgeBaseDocument: {
          userId,
          status: 'COMPLETED',
          deletedAt: null,
        },
        content: { contains: query, mode: 'insensitive' },
      },
      include: {
        KnowledgeBaseDocument: {
          select: { id: true, title: true, originalName: true },
        },
      },
      take: maxResults,
      orderBy: { chunkIndex: 'asc' },
    });

    // Search for relevant FAQs
    const faqs = await (knowledgeBaseFAQAdapter.findMany as (args: Record<string, unknown>) => Promise<unknown[]>)({
      where: {
        userId,
        isActive: true,
        OR: [
          { questionEn: { contains: query, mode: 'insensitive' } },
          { questionAr: { contains: query, mode: 'insensitive' } },
          { answerEn: { contains: query, mode: 'insensitive' } },
          { answerAr: { contains: query, mode: 'insensitive' } },
        ],
      },
      orderBy: [{ priority: 'desc' }, { createdAt: 'desc' }],
      take: maxResults,
    });

    return {
      chunks: (chunks as Array<Record<string, unknown>>).map((chunk, index) => ({
        id: chunk.id as string,
        documentId: chunk.documentId as string,
        documentTitle: ((chunk.KnowledgeBaseDocument as Record<string, unknown>)?.title as string) ||
          ((chunk.KnowledgeBaseDocument as Record<string, unknown>)?.originalName as string),
        content: chunk.content as string,
        relevanceScore: 1 - index * 0.1, // Simple scoring
      })),
      faqs: (faqs as Array<Record<string, unknown>>).map((faq) => ({
        id: faq.id as string,
        questionEn: faq.questionEn as string,
        questionAr: faq.questionAr as string | null,
        answerEn: faq.answerEn as string,
        answerAr: faq.answerAr as string | null,
        category: faq.category as string,
      })),
    };
  }

  /**
   * Generate an AI answer using Gemini
   */
  private static async generateAnswer(
    query: string,
    context: SearchResult,
    language: 'en' | 'ar',
    customInstructions: string | null
  ): Promise<string> {
    const client = getGeminiClient();

    // Build context from search results
    let contextText = '';

    // Add FAQ context
    if (context.faqs.length > 0) {
      contextText += language === 'ar'
        ? '\n\n--- الأسئلة الشائعة ---\n'
        : '\n\n--- Frequently Asked Questions ---\n';

      for (const faq of context.faqs) {
        const question = language === 'ar' && faq.questionAr
          ? faq.questionAr
          : faq.questionEn;
        const answer = language === 'ar' && faq.answerAr
          ? faq.answerAr
          : faq.answerEn;

        contextText += `Q: ${question}\nA: ${answer}\n\n`;
      }
    }

    // Add document chunk context
    if (context.chunks.length > 0) {
      contextText += language === 'ar'
        ? '\n\n--- محتوى المستندات ---\n'
        : '\n\n--- Document Content ---\n';

      for (const chunk of context.chunks) {
        contextText += `[${chunk.documentTitle}]:\n${chunk.content}\n\n`;
      }
    }

    // Build the prompt
    const systemPrompt = language === 'ar'
      ? `أنت مساعد ذكي ودود يجيب على أسئلة العملاء بناءً على قاعدة المعرفة المقدمة.

القواعد:
1. أجب فقط بناءً على المعلومات الموجودة في السياق المقدم
2. إذا لم تجد إجابة في السياق، اعترف بذلك بلطف
3. كن موجزاً ومفيداً
4. استخدم اللغة العربية في الإجابة
5. لا تخترع معلومات غير موجودة في السياق

${customInstructions ? `\nتعليمات إضافية: ${customInstructions}` : ''}`
      : `You are a helpful and friendly AI assistant that answers customer questions based on the provided knowledge base.

Rules:
1. Only answer based on the information in the provided context
2. If you cannot find an answer in the context, politely acknowledge it
3. Be concise and helpful
4. Respond in English
5. Do not make up information that is not in the context

${customInstructions ? `\nAdditional instructions: ${customInstructions}` : ''}`;

    const userPrompt = language === 'ar'
      ? `السياق المتاح:
${contextText}

سؤال العميل: ${query}

الرجاء الإجابة على سؤال العميل بناءً على السياق أعلاه.`
      : `Available context:
${contextText}

Customer question: ${query}

Please answer the customer's question based on the context above.`;

    const response = await client.models.generateContent({
      model: AI_MODEL,
      contents: [
        { role: 'user', parts: [{ text: systemPrompt + '\n\n' + userPrompt }] },
      ],
    });

    return response.text || (language === 'ar'
      ? 'لم أتمكن من إنشاء إجابة.'
      : 'Unable to generate a response.');
  }

  /**
   * Get a quick FAQ match without AI (for instant responses)
   */
  static async getQuickFAQMatch(
    userId: string,
    query: string,
    language: 'en' | 'ar' = 'en'
  ): Promise<{ faq: KnowledgeBaseFAQ; answer: string } | null> {
    // Look for exact or very close FAQ matches
    const normalizedQuery = query.toLowerCase().trim();

    const faqs = await (knowledgeBaseFAQAdapter.findMany as (args: Record<string, unknown>) => Promise<unknown[]>)({
      where: {
        userId,
        isActive: true,
      },
      orderBy: { priority: 'desc' },
    });

    for (const faq of faqs as Array<Record<string, unknown>>) {
      const questionEn = (faq.questionEn as string).toLowerCase();
      const questionAr = (faq.questionAr as string | null)?.toLowerCase() || '';

      // Check for close match
      if (
        questionEn.includes(normalizedQuery) ||
        normalizedQuery.includes(questionEn) ||
        questionAr.includes(normalizedQuery) ||
        normalizedQuery.includes(questionAr)
      ) {
        return {
          faq: faq as unknown as KnowledgeBaseFAQ,
          answer: language === 'ar' && faq.answerAr
            ? faq.answerAr as string
            : faq.answerEn as string,
        };
      }
    }

    return null;
  }
}

// Export singleton-style functions for convenience
export const kbAIService = {
  isConfigured: KBAIService.isConfigured.bind(KBAIService),
  ask: KBAIService.ask.bind(KBAIService),
  getQuickFAQMatch: KBAIService.getQuickFAQMatch.bind(KBAIService),
};
