import { Injectable, Logger, BadRequestException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ChatOpenAI } from '@langchain/openai';
import axios from 'axios';
import {
  AIConversation,
  MessageRole,
  ConversationMessage,
} from '../../database/entities';
import { Child } from '../../database/entities/child.entity';
import { Activity } from '../../database/entities/activity.entity';
import { ContextManager } from './context/context-manager';
import { MedicalSafetyService } from './safety/medical-safety.service';
import { ResponseModerationService } from './safety/response-moderation.service';
import { AISafetyService } from './safety/ai-safety.service';
import { AIRateLimitService } from './safety/ai-rate-limit.service';
import {
  MultiLanguageService,
  SupportedLanguage,
} from './localization/multilanguage.service';
import { ConversationMemoryService } from './memory/conversation-memory.service';
import { EmbeddingsService } from './embeddings/embeddings.service';
import { AuditService } from '../../common/services/audit.service';

export interface ChatMessageDto {
  message: string;
  conversationId?: string;
  language?: SupportedLanguage;
}

export interface ChatResponseDto {
  conversationId: string;
  message: string;
  timestamp: Date;
  metadata?: {
    model?: string;
    provider?: 'openai' | 'azure';
    reasoningTokens?: number;
    totalTokens?: number;
  };
}

interface AzureGPT5Response {
  id: string;
  object: string;
  created: number;
  model: string;
  choices: Array<{
    index: number;
    message: {
      role: string;
      content: string;
    };
    finish_reason: string;
    reasoning_tokens?: number; // GPT-5 specific
  }>;
  usage: {
    prompt_tokens: number;
    completion_tokens: number;
    reasoning_tokens?: number; // GPT-5 specific
    total_tokens: number;
  };
}

@Injectable()
export class AIService {
  private chatModel: ChatOpenAI;
  private readonly logger = new Logger('AIService');
  private aiProvider: 'openai' | 'azure';
  private azureEnabled: boolean;

  // Azure configuration - separate keys for each deployment
  private azureChatEndpoint: string;
  private azureChatDeployment: string;
  private azureChatApiVersion: string;
  private azureChatApiKey: string;
  private azureReasoningEffort: 'minimal' | 'low' | 'medium' | 'high';

  constructor(
    private configService: ConfigService,
    private contextManager: ContextManager,
    private medicalSafetyService: MedicalSafetyService,
    private responseModerationService: ResponseModerationService,
    private aiSafetyService: AISafetyService,
    private aiRateLimitService: AIRateLimitService,
    private multiLanguageService: MultiLanguageService,
    private conversationMemoryService: ConversationMemoryService,
    private embeddingsService: EmbeddingsService,
    private auditService: AuditService,
    @InjectRepository(AIConversation)
    private conversationRepository: Repository<AIConversation>,
    @InjectRepository(Child)
    private childRepository: Repository<Child>,
    @InjectRepository(Activity)
    private activityRepository: Repository<Activity>,
  ) {
    this.aiProvider = this.configService.get('AI_PROVIDER', 'openai') as any;
    this.azureEnabled =
      this.configService.get('AZURE_OPENAI_ENABLED', 'false') === 'true';

    // Azure OpenAI configuration - each deployment has its own API key
    if (this.aiProvider === 'azure' || this.azureEnabled) {
      this.azureChatEndpoint = this.configService.get(
        'AZURE_OPENAI_CHAT_ENDPOINT',
      );
      this.azureChatDeployment = this.configService.get(
        'AZURE_OPENAI_CHAT_DEPLOYMENT',
      );
      this.azureChatApiVersion = this.configService.get(
        'AZURE_OPENAI_CHAT_API_VERSION',
      );
      this.azureChatApiKey = this.configService.get(
        'AZURE_OPENAI_CHAT_API_KEY',
      );
      this.azureReasoningEffort = this.configService.get(
        'AZURE_OPENAI_REASONING_EFFORT',
        'medium',
      ) as any;

      if (!this.azureChatApiKey || !this.azureChatEndpoint) {
        this.logger.warn(
          'Azure OpenAI Chat not properly configured. Falling back to OpenAI.',
        );
        this.aiProvider = 'openai';
      } else {
        this.logger.log(
          `Azure OpenAI Chat configured: ${this.azureChatDeployment} at ${this.azureChatEndpoint}`,
        );
      }
    }

    // OpenAI configuration (fallback or primary)
    if (this.aiProvider === 'openai') {
      const openaiApiKey = this.configService.get<string>('OPENAI_API_KEY');

      if (!openaiApiKey) {
        this.logger.warn(
          'OPENAI_API_KEY not configured. AI features will be disabled.',
        );
      } else {
        const modelName = this.configService.get('OPENAI_MODEL', 'gpt-4o-mini');
        const maxTokens = parseInt(
          this.configService.get('OPENAI_MAX_TOKENS', '1000'),
          10,
        );

        this.chatModel = new ChatOpenAI({
          openAIApiKey: openaiApiKey,
          modelName,
          temperature: 0.7,
          maxTokens,
        });

        this.logger.log(`OpenAI configured: ${modelName}`);
      }
    }
  }

  /**
   * Send a chat message and get AI response
   */
  async chat(
    userId: string,
    chatDto: ChatMessageDto,
  ): Promise<ChatResponseDto> {
    // Validate AI service is configured
    if (this.aiProvider === 'openai' && !this.chatModel) {
      throw new BadRequestException('AI service not configured');
    }

    if (this.aiProvider === 'azure' && !this.azureChatApiKey) {
      throw new BadRequestException('Azure OpenAI Chat service not configured');
    }

    try {
      // Check rate limit FIRST (TODO: Get isPremium from user entity)
      const isPremium = false; // TODO: Fetch from user.subscriptionTier === 'premium'
      const rateLimitCheck = await this.aiRateLimitService.checkRateLimit(
        userId,
        isPremium,
      );

      if (!rateLimitCheck.allowed) {
        throw new BadRequestException(
          rateLimitCheck.reason ||
            `Rate limit exceeded. ${rateLimitCheck.remaining || 0} queries remaining.`,
        );
      }

      // Sanitize input and check for prompt injection
      const sanitizedMessage = this.sanitizeInput(chatDto.message, userId);

      // Detect language if not provided
      const userLanguage =
        chatDto.language ||
        this.multiLanguageService.detectLanguage(sanitizedMessage);

      // Enhanced safety check with comprehensive keyword detection
      const comprehensiveSafetyCheck =
        this.aiSafetyService.checkInputSafety(sanitizedMessage, userId);

      // If emergency or crisis, return safety response immediately
      if (
        !comprehensiveSafetyCheck.isSafe &&
        comprehensiveSafetyCheck.recommendedResponse
      ) {
        this.logger.warn(
          `Safety trigger (${comprehensiveSafetyCheck.trigger}) for user ${userId}: ${comprehensiveSafetyCheck.keywords?.join(', ')}`,
        );

        return {
          conversationId: chatDto.conversationId || 'safety-override',
          message: comprehensiveSafetyCheck.recommendedResponse,
          timestamp: new Date(),
          metadata: {
            model: 'safety-override',
            provider: this.aiProvider,
            isSafetyOverride: true,
            trigger: comprehensiveSafetyCheck.trigger,
            language: userLanguage,
          } as any,
        };
      }

      // Check for medical safety concerns (use localized disclaimers)
      const safetyCheck =
        this.medicalSafetyService.checkMessage(sanitizedMessage);

      if (safetyCheck.severity === 'emergency') {
        // For emergencies, return localized disclaimer immediately without AI response
        this.logger.warn(
          `Emergency medical keywords detected for user ${userId}: ${safetyCheck.detectedKeywords.join(', ')}`,
        );

        const localizedDisclaimer =
          this.multiLanguageService.getMedicalDisclaimer(
            userLanguage,
            'emergency',
          );

        return {
          conversationId: chatDto.conversationId || 'emergency',
          message: localizedDisclaimer,
          timestamp: new Date(),
          metadata: {
            model: 'safety-override',
            provider: this.aiProvider,
            isSafetyOverride: true,
            severity: 'emergency',
            language: userLanguage,
          } as any,
        };
      }

      // Get or create conversation
      let conversation: AIConversation;

      if (chatDto.conversationId) {
        conversation = await this.conversationRepository.findOne({
          where: { id: chatDto.conversationId, userId },
        });

        if (!conversation) {
          throw new BadRequestException('Conversation not found');
        }
      } else {
        // Create new conversation
        conversation = this.conversationRepository.create({
          userId,
          title: this.generateConversationTitle(chatDto.message),
          messages: [],
          totalTokens: 0,
          metadata: {},
        });
      }

      // Add user message to history (using sanitized message)
      const userMessage: ConversationMessage = {
        role: MessageRole.USER,
        content: sanitizedMessage,
        timestamp: new Date(),
      };
      conversation.messages.push(userMessage);

      // Build context with user's children and recent activities
      const userChildren = await this.childRepository.find({
        where: { familyId: userId },
      });

      const recentActivities = await this.activityRepository.find({
        where: { loggedBy: userId },
        order: { startedAt: 'DESC' },
        take: 20,
      });

      // Use enhanced conversation memory with semantic search
      const { context: memoryContext } =
        await this.conversationMemoryService.getConversationWithSemanticMemory(
          conversation.id,
          sanitizedMessage, // Use current query for semantic search
        );

      // Build context with localized system prompt
      const userPreferences = {
        language: userLanguage,
        tone: 'friendly',
      };

      let contextMessages = await this.contextManager.buildContext(
        memoryContext,
        userChildren,
        recentActivities,
        userPreferences,
      );

      // Apply base safety prompt with guardrails
      const baseSafetyPrompt = this.aiSafetyService.getBaseSafetyPrompt();

      // Add safety override if medical/crisis/developmental triggers detected
      let safetyOverridePrompt = '';
      if (comprehensiveSafetyCheck.trigger) {
        switch (comprehensiveSafetyCheck.trigger) {
          case 'medical':
            safetyOverridePrompt =
              this.aiSafetyService.getMedicalSafetyOverride();
            break;
          case 'crisis':
            safetyOverridePrompt =
              this.aiSafetyService.getCrisisSafetyOverride();
            break;
        }
      }

      // Apply multi-language system prompt enhancement
      const baseSystemPrompt =
        contextMessages.find((m) => m.role === MessageRole.SYSTEM)?.content ||
        '';

      // Combine base safety prompt + safety override + existing system prompt
      const enhancedSystemPrompt = `${baseSafetyPrompt}\n\n${safetyOverridePrompt ? `${safetyOverridePrompt}\n\n` : ''}${baseSystemPrompt}`;

      const localizedSystemPrompt =
        this.multiLanguageService.buildLocalizedSystemPrompt(
          enhancedSystemPrompt,
          userLanguage,
        );

      // Replace system prompt with enhanced localized version
      contextMessages = contextMessages.map((msg) =>
        msg.role === MessageRole.SYSTEM
          ? { ...msg, content: localizedSystemPrompt }
          : msg,
      );

      // Prune context to fit token budget
      contextMessages = this.conversationMemoryService.pruneConversation(
        contextMessages,
        4000,
      );

      // Generate AI response based on provider
      let responseContent: string;
      let reasoningTokens: number | undefined;
      let totalTokens: number | undefined;

      if (this.aiProvider === 'azure') {
        const azureResponse = await this.generateWithAzure(contextMessages);
        responseContent = azureResponse.content;
        reasoningTokens = azureResponse.reasoningTokens;
        totalTokens = azureResponse.totalTokens;
      } else {
        const openaiResponse = await this.generateWithOpenAI(contextMessages);
        responseContent = openaiResponse;
      }

      // Check output safety for unsafe patterns (dosages, diagnoses, etc.)
      const outputSafetyCheck =
        this.aiSafetyService.checkOutputSafety(responseContent);

      if (!outputSafetyCheck.isSafe) {
        this.logger.warn(
          `Unsafe AI response pattern detected for user ${userId}, prepending disclaimer`,
        );
        // Prepend medical disclaimer if response contains unsafe medical patterns
        const disclaimer = this.aiSafetyService.getMedicalDisclaimer();
        responseContent = `${disclaimer}\n\n---\n\n${responseContent}`;
      }

      // Moderate AI response for safety and appropriateness
      const moderationResult =
        this.responseModerationService.moderateResponse(responseContent);

      if (!moderationResult.isAppropriate) {
        this.logger.warn(
          `Inappropriate AI response blocked for user ${userId}: ${moderationResult.reason}`,
        );
        responseContent = moderationResult.filteredResponse!;
      } else if (moderationResult.filtered) {
        this.logger.debug(`AI response filtered/softened for user ${userId}`);
        responseContent = moderationResult.filteredResponse!;
      }

      // Validate response quality
      const qualityCheck =
        this.responseModerationService.validateResponseQuality(responseContent);
      if (!qualityCheck.isValid) {
        this.logger.warn(`AI response quality issue: ${qualityCheck.reason}`);
        throw new Error('Generated response did not meet quality standards');
      }

      // Inject safety-specific responses based on comprehensive safety check
      if (comprehensiveSafetyCheck.trigger && comprehensiveSafetyCheck.keywords) {
        this.logger.log(
          `Injecting safety response for trigger: ${comprehensiveSafetyCheck.trigger}`,
        );

        responseContent = this.aiSafetyService.injectSafetyResponse(
          comprehensiveSafetyCheck.trigger,
          responseContent,
          comprehensiveSafetyCheck.keywords,
        );
      }

      // Prepend localized medical disclaimer if needed (legacy support)
      if (safetyCheck.requiresDisclaimer) {
        this.logger.log(
          `Adding ${safetyCheck.severity} medical disclaimer for user ${userId}: ${safetyCheck.detectedKeywords.join(', ')}`,
        );

        // Note: emergency cases are handled earlier and return immediately (line 161-178)
        // and 'low' severity has requiresDisclaimer===false
        // so at this point severity can only be 'medium' or 'high'
        const disclaimerLevel: 'high' | 'medium' =
          safetyCheck.severity === 'low' ? 'medium' : safetyCheck.severity;

        const localizedDisclaimer =
          this.multiLanguageService.getMedicalDisclaimer(
            userLanguage,
            disclaimerLevel,
          );

        responseContent = `${localizedDisclaimer}\n\n---\n\n${responseContent}`;
      }

      // Add assistant message to history
      const assistantMessage: ConversationMessage = {
        role: MessageRole.ASSISTANT,
        content: responseContent,
        timestamp: new Date(),
      };
      conversation.messages.push(assistantMessage);

      // Update token count
      const estimatedTokens =
        this.contextManager.estimateTokenCount(chatDto.message) +
        this.contextManager.estimateTokenCount(responseContent);

      conversation.totalTokens += totalTokens || estimatedTokens;

      // Save conversation
      await this.conversationRepository.save(conversation);

      // Increment rate limit counter and track query for suspicious patterns
      await this.aiRateLimitService.incrementCounter(userId);
      await this.aiRateLimitService.trackQuery(
        userId,
        sanitizedMessage,
        comprehensiveSafetyCheck.trigger,
      );

      // Store embeddings for new messages (async, non-blocking)
      const userMessageIndex = conversation.messages.length - 2; // User message
      const assistantMessageIndex = conversation.messages.length - 1; // Assistant message

      this.conversationMemoryService
        .storeMessageEmbedding(
          conversation.id,
          userId,
          userMessageIndex,
          MessageRole.USER,
          sanitizedMessage,
        )
        .catch((err) => {
          this.logger.warn(
            `Failed to store user message embedding: ${err.message}`,
          );
        });

      this.conversationMemoryService
        .storeMessageEmbedding(
          conversation.id,
          userId,
          assistantMessageIndex,
          MessageRole.ASSISTANT,
          responseContent,
        )
        .catch((err) => {
          this.logger.warn(
            `Failed to store assistant message embedding: ${err.message}`,
          );
        });

      this.logger.log(
        `Chat response generated for conversation ${conversation.id} using ${this.aiProvider}`,
      );

      return {
        conversationId: conversation.id,
        message: responseContent,
        timestamp: assistantMessage.timestamp,
        metadata: {
          model:
            this.aiProvider === 'azure'
              ? this.azureChatDeployment
              : this.configService.get('OPENAI_MODEL'),
          provider: this.aiProvider,
          reasoningTokens,
          totalTokens,
        },
      };
    } catch (error) {
      this.logger.error(`Chat failed: ${error.message}`, error.stack);

      // Fallback to OpenAI if Azure fails
      if (this.aiProvider === 'azure' && this.chatModel) {
        this.logger.warn('Azure OpenAI failed, attempting OpenAI fallback...');
        this.aiProvider = 'openai';
        return this.chat(userId, chatDto);
      }

      throw new BadRequestException('Failed to generate AI response');
    }
  }

  /**
   * Generate response with Azure OpenAI (GPT-5 with reasoning tokens)
   */
  private async generateWithAzure(messages: ConversationMessage[]): Promise<{
    content: string;
    reasoningTokens?: number;
    totalTokens?: number;
  }> {
    const url = `${this.azureChatEndpoint}/openai/deployments/${this.azureChatDeployment}/chat/completions?api-version=${this.azureChatApiVersion}`;

    // Convert messages to Azure format
    const azureMessages = messages.map((msg) => ({
      role: this.convertRoleToAzure(msg.role),
      content: msg.content,
    }));

    const maxTokens = parseInt(
      this.configService.get('AZURE_OPENAI_CHAT_MAX_TOKENS', '1000'),
      10,
    );

    // GPT-5 specific request body
    const requestBody = {
      messages: azureMessages,
      // temperature: 1, // GPT-5 only supports temperature=1 (default), so we omit it
      max_completion_tokens: maxTokens, // GPT-5 uses max_completion_tokens instead of max_tokens
      stream: false,
      // GPT-5 specific parameters
      reasoning_effort: this.azureReasoningEffort, // 'minimal', 'low', 'medium', 'high'
      // Optional: response_format for structured output
      // response_format: { type: 'text' }, // or 'json_object' if needed
    };

    this.logger.debug('Azure OpenAI request:', {
      url,
      deployment: this.azureChatDeployment,
      reasoning_effort: this.azureReasoningEffort,
      messageCount: azureMessages.length,
    });

    const response = await axios.post<AzureGPT5Response>(url, requestBody, {
      headers: {
        'api-key': this.azureChatApiKey,
        'Content-Type': 'application/json',
      },
      timeout: 30000, // 30 second timeout
    });

    const choice = response.data.choices[0];

    // GPT-5 returns reasoning_tokens in usage
    this.logger.debug('Azure OpenAI response:', {
      model: response.data.model,
      finish_reason: choice.finish_reason,
      prompt_tokens: response.data.usage.prompt_tokens,
      completion_tokens: response.data.usage.completion_tokens,
      reasoning_tokens: response.data.usage.reasoning_tokens,
      total_tokens: response.data.usage.total_tokens,
    });

    return {
      content: choice.message.content,
      reasoningTokens: response.data.usage.reasoning_tokens,
      totalTokens: response.data.usage.total_tokens,
    };
  }

  /**
   * Generate response with OpenAI (fallback)
   */
  private async generateWithOpenAI(
    messages: ConversationMessage[],
  ): Promise<string> {
    // Convert to LangChain message format
    const langchainMessages = messages.map((msg) => {
      if (msg.role === MessageRole.SYSTEM) {
        return { type: 'system', content: msg.content };
      } else if (msg.role === MessageRole.USER) {
        return { type: 'human', content: msg.content };
      } else {
        return { type: 'ai', content: msg.content };
      }
    });

    const response = await this.chatModel.invoke(langchainMessages as any);
    return response.content as string;
  }

  /**
   * Convert internal message role to Azure format
   */
  private convertRoleToAzure(role: MessageRole): string {
    switch (role) {
      case MessageRole.SYSTEM:
        return 'system';
      case MessageRole.USER:
        return 'user';
      case MessageRole.ASSISTANT:
        return 'assistant';
      default:
        return 'user';
    }
  }

  /**
   * Get conversation history
   */
  async getConversation(
    userId: string,
    conversationId: string,
  ): Promise<AIConversation> {
    const conversation = await this.conversationRepository.findOne({
      where: { id: conversationId, userId },
    });

    if (!conversation) {
      throw new BadRequestException('Conversation not found');
    }

    return conversation;
  }

  /**
   * Get all conversations for a user
   */
  async getUserConversations(userId: string): Promise<AIConversation[]> {
    return this.conversationRepository.find({
      where: { userId },
      order: { updatedAt: 'DESC' },
      select: ['id', 'title', 'createdAt', 'updatedAt', 'totalTokens', 'metadata'],
    });
  }

  /**
   * Delete a conversation
   */
  async deleteConversation(
    userId: string,
    conversationId: string,
  ): Promise<void> {
    const result = await this.conversationRepository.delete({
      id: conversationId,
      userId,
    });

    if (result.affected === 0) {
      throw new BadRequestException('Conversation not found');
    }
  }

  /**
   * Update conversation group
   */
  async updateConversationGroup(
    userId: string,
    conversationId: string,
    groupName: string | null,
  ): Promise<AIConversation> {
    const conversation = await this.conversationRepository.findOne({
      where: { id: conversationId, userId },
    });

    if (!conversation) {
      throw new BadRequestException('Conversation not found');
    }

    // Update metadata with group information
    conversation.metadata = {
      ...conversation.metadata,
      groupName: groupName,
    };

    return this.conversationRepository.save(conversation);
  }

  /**
   * Get all conversation groups for a user
   */
  async getConversationGroups(userId: string): Promise<string[]> {
    const conversations = await this.conversationRepository.find({
      where: { userId },
      select: ['metadata'],
    });

    // Extract unique group names from metadata
    const groupNames = new Set<string>();
    conversations.forEach((conv) => {
      if (conv.metadata?.groupName && typeof conv.metadata.groupName === 'string') {
        groupNames.add(conv.metadata.groupName);
      }
    });

    return Array.from(groupNames).sort();
  }

  /**
   * Generate a title for the conversation from the first message
   */
  private generateConversationTitle(firstMessage: string): string {
    const maxLength = 50;
    if (firstMessage.length <= maxLength) {
      return firstMessage;
    }
    return firstMessage.substring(0, maxLength - 3) + '...';
  }

  /**
   * Detect if user message contains prompt injection attempts
   */
  private detectPromptInjection(message: string): boolean {
    const suspiciousPatterns = [
      // Direct instruction override attempts
      /ignore (previous|all|the|your) instructions?/i,
      /disregard (previous|all|the|your) instructions?/i,
      /forget (previous|all|the|your) (instructions?|context|system)/i,

      // Role manipulation attempts
      /you are (now|a|an|the)/i,
      /act as (a|an|the)/i,
      /pretend (you are|to be)/i,
      /simulate (a|an|the)/i,
      /roleplay as/i,

      // System prompt manipulation
      /system prompt:?/i,
      /new (instructions?|prompt|system|role):?/i,
      /override (instructions?|prompt|system)/i,
      /change (your|the) (instructions?|behavior|prompt)/i,

      // Jailbreak attempts
      /DAN mode/i,
      /developer mode/i,
      /jailbreak/i,
      /🔓/,
      /\[INST\]/i,
      /\[\/INST\]/i,

      // Output manipulation
      /print (your|the) (prompt|system|instructions?)/i,
      /show (your|the) (prompt|system|instructions?)/i,
      /reveal (your|the) (prompt|system|instructions?)/i,
      /output (your|the) (prompt|system|instructions?)/i,

      // Context breaking
      /---BEGIN/i,
      /###/,
      /\<\|endoftext\|\>/i,
      /\<\|im_start\|\>/i,
      /\<\|im_end\|\>/i,

      // SQL/Code injection patterns
      /'; DROP TABLE/i,
      /\<script\>/i,
      /javascript:/i,
      /eval\(/i,
      /exec\(/i,
    ];

    return suspiciousPatterns.some((pattern) => pattern.test(message));
  }

  /**
   * Sanitize user input
   */
  private sanitizeInput(message: string, userId: string): string {
    // Check for empty or whitespace-only messages
    const trimmed = message.trim();
    if (!trimmed) {
      throw new BadRequestException('Message cannot be empty');
    }

    // Check for excessive length (prevent DoS via token exhaustion)
    const maxLength = 2000; // characters
    if (trimmed.length > maxLength) {
      throw new BadRequestException(
        `Message is too long. Maximum ${maxLength} characters allowed.`,
      );
    }

    // Detect prompt injection
    if (this.detectPromptInjection(trimmed)) {
      this.logger.warn(
        `Potential prompt injection detected from user ${userId}: "${trimmed.substring(0, 100)}..."`,
      );

      // Log security violation to audit log (async, don't block the request)
      this.auditService
        .logSecurityViolation(userId, 'prompt_injection', {
          message: trimmed.substring(0, 200), // Store first 200 chars for review
          detectedAt: new Date().toISOString(),
        })
        .catch((err) => {
          this.logger.error('Failed to log security violation', err);
        });

      throw new BadRequestException(
        'Your message contains potentially unsafe content. Please rephrase your question about parenting and childcare.',
      );
    }

    return trimmed;
  }

  /**
   * Get current AI provider status
   */
  getProviderStatus(): {
    provider: 'openai' | 'azure';
    model: string;
    configured: boolean;
    endpoint?: string;
  } {
    if (this.aiProvider === 'azure') {
      return {
        provider: 'azure',
        model: this.azureChatDeployment,
        configured: !!this.azureChatApiKey,
        endpoint: this.azureChatEndpoint,
      };
    }

    return {
      provider: 'openai',
      model: this.configService.get('OPENAI_MODEL', 'gpt-4o-mini'),
      configured: !!this.chatModel,
    };
  }
}
