import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import {
  UserPreferences,
  ResponseStyle,
  ResponseTone,
  TopicPreference,
  ResponsePattern,
} from '../../database/entities/user-preferences.entity';
import { AIFeedback, FeedbackRating } from '../../database/entities/ai-feedback.entity';

export interface PersonalizedPromptConfig {
  systemPromptAdditions: string[];
  responseStyle: ResponseStyle;
  tone: ResponseTone;
  maxLength: number;
  formatting: {
    useBulletPoints: boolean;
    includeExamples: boolean;
    useStepByStep: boolean;
  };
  topicWeights: Map<string, number>;
}

@Injectable()
export class PersonalizationService {
  private readonly logger = new Logger(PersonalizationService.name);

  constructor(
    @InjectRepository(UserPreferences)
    private userPreferencesRepository: Repository<UserPreferences>,
    @InjectRepository(AIFeedback)
    private aiFeedbackRepository: Repository<AIFeedback>,
  ) {}

  /**
   * Get or create user preferences
   */
  async getUserPreferences(userId: string): Promise<UserPreferences> {
    let preferences = await this.userPreferencesRepository.findOne({
      where: { userId },
    });

    if (!preferences) {
      preferences = this.userPreferencesRepository.create({
        userId,
        responseStyle: ResponseStyle.BALANCED,
        tone: ResponseTone.FRIENDLY,
        language: 'en',
      });
      await this.userPreferencesRepository.save(preferences);
      this.logger.log(`Created default preferences for user ${userId}`);
    }

    return preferences;
  }

  /**
   * Learn from user feedback and update preferences
   * TODO: Re-implement after adding conversation relation to AIFeedback entity
   */
  async learnFromFeedback(feedbackId: string): Promise<void> {
    const feedback = await this.aiFeedbackRepository.findOne({
      where: { id: feedbackId },
    });

    if (!feedback) {
      this.logger.warn(`Feedback ${feedbackId} not found`);
      return;
    }

    const preferences = await this.getUserPreferences(feedback.userId);

    // Update feedback counts
    if (feedback.rating === FeedbackRating.HELPFUL || feedback.rating === FeedbackRating.POSITIVE) {
      preferences.positiveFeedbackCount += 1;
    } else if (feedback.rating === FeedbackRating.NOT_HELPFUL || feedback.rating === FeedbackRating.NEGATIVE) {
      preferences.negativeFeedbackCount += 1;
    }

    preferences.totalInteractions += 1;
    preferences.lastUpdatedFromFeedback = new Date();

    await this.userPreferencesRepository.save(preferences);

    this.logger.log(
      `Updated preferences for user ${feedback.userId} based on ${feedback.rating} feedback`,
    );
  }

  /**
   * Generate personalized prompt configuration
   */
  async getPersonalizedConfig(userId: string): Promise<PersonalizedPromptConfig> {
    const preferences = await this.getUserPreferences(userId);

    const systemPromptAdditions: string[] = [];

    // Add response style guidance
    switch (preferences.responseStyle) {
      case ResponseStyle.CONCISE:
        systemPromptAdditions.push(
          'Keep responses brief and to the point. Limit to 2-3 sentences when possible.',
        );
        break;
      case ResponseStyle.DETAILED:
        systemPromptAdditions.push(
          'Provide comprehensive, detailed explanations with context and examples.',
        );
        break;
      case ResponseStyle.BALANCED:
        systemPromptAdditions.push(
          'Balance brevity with helpful detail. Provide enough context without overwhelming.',
        );
        break;
    }

    // Add tone guidance
    switch (preferences.tone) {
      case ResponseTone.FRIENDLY:
        systemPromptAdditions.push(
          'Use a warm, supportive, and encouraging tone. You are a helpful friend.',
        );
        break;
      case ResponseTone.PROFESSIONAL:
        systemPromptAdditions.push(
          'Maintain a professional, informative tone. Focus on facts and evidence.',
        );
        break;
      case ResponseTone.CASUAL:
        systemPromptAdditions.push(
          'Use a relaxed, conversational tone. Keep it light and approachable.',
        );
        break;
      case ResponseTone.EMPATHETIC:
        systemPromptAdditions.push(
          'Show deep empathy and understanding. Acknowledge the emotional aspects of parenting.',
        );
        break;
    }

    // Add formatting preferences
    if (preferences.preferBulletPoints) {
      systemPromptAdditions.push(
        'Format responses using bullet points for clarity.',
      );
    }

    if (preferences.preferStepByStep) {
      systemPromptAdditions.push(
        'Break down advice into clear, numbered steps when appropriate.',
      );
    }

    if (preferences.preferExamples) {
      systemPromptAdditions.push(
        'Include practical examples to illustrate your points.',
      );
    }

    // Add focus area guidance
    if (preferences.focusAreas.length > 0) {
      systemPromptAdditions.push(
        `The user is particularly interested in: ${preferences.focusAreas.join(', ')}.`,
      );
    }

    // Add avoided topics
    if (preferences.avoidedTopics.length > 0) {
      const avoidedList = preferences.avoidedTopics.map((t) => t.topic).join(', ');
      systemPromptAdditions.push(
        `Avoid or minimize discussion of: ${avoidedList} unless directly asked.`,
      );
    }

    // Build topic weights map
    const topicWeights = new Map<string, number>();
    preferences.preferredTopics.forEach((tp) => {
      topicWeights.set(tp.topic, tp.weight);
    });

    return {
      systemPromptAdditions,
      responseStyle: preferences.responseStyle,
      tone: preferences.tone,
      maxLength: preferences.maxResponseLength,
      formatting: {
        useBulletPoints: preferences.preferBulletPoints,
        includeExamples: preferences.preferExamples,
        useStepByStep: preferences.preferStepByStep,
      },
      topicWeights,
    };
  }

  /**
   * Extract topics from user message
   */
  private extractTopics(message: string): string[] {
    const topics: string[] = [];
    const lowerMessage = message.toLowerCase();

    // Common parenting topics
    const topicKeywords = {
      sleep: ['sleep', 'nap', 'bedtime', 'wake', 'insomnia'],
      feeding: ['feed', 'bottle', 'breast', 'formula', 'nursing', 'milk'],
      development: ['development', 'milestone', 'crawl', 'walk', 'talk'],
      health: ['sick', 'fever', 'doctor', 'medicine', 'vaccine', 'health'],
      behavior: ['crying', 'tantrum', 'behavior', 'discipline'],
      diaper: ['diaper', 'poop', 'pee', 'potty'],
      safety: ['safe', 'danger', 'car seat', 'baby proof'],
    };

    Object.entries(topicKeywords).forEach(([topic, keywords]) => {
      if (keywords.some((keyword) => lowerMessage.includes(keyword))) {
        topics.push(topic);
      }
    });

    return topics;
  }

  /**
   * Update topic weights based on feedback
   */
  private updateTopicWeights(
    topicList: TopicPreference[],
    topics: string[],
    adjustment: number,
  ): void {
    topics.forEach((topic) => {
      const existing = topicList.find((t) => t.topic === topic);
      if (existing) {
        existing.weight = Math.min(1.0, existing.weight + adjustment);
      } else {
        topicList.push({ topic, weight: 0.5 + adjustment });
      }
    });
  }

  /**
   * Update response patterns based on feedback
   */
  private updateResponsePatterns(
    patterns: ResponsePattern[],
    response: string,
  ): void {
    // Extract patterns (simple keyword extraction for now)
    const words = response
      .toLowerCase()
      .match(/\b\w+\b/g) || [];

    // Track 2-3 word phrases that appear in helpful/unhelpful responses
    for (let i = 0; i < words.length - 1; i++) {
      const phrase = `${words[i]} ${words[i + 1]}`;
      if (phrase.length > 8) { // Only meaningful phrases
        const existing = patterns.find((p) => p.pattern === phrase);
        if (existing) {
          existing.count += 1;
          existing.lastSeen = new Date();
        } else if (patterns.length < 100) { // Limit to 100 patterns
          patterns.push({
            pattern: phrase,
            count: 1,
            lastSeen: new Date(),
          });
        }
      }
    }
  }

  /**
   * Adjust response style based on feedback patterns
   * TODO: Re-implement after adding conversation relation to AIFeedback entity
   */
  private adjustResponseStyle(
    preferences: UserPreferences,
    feedback: AIFeedback,
  ): void {
    // Temporarily disabled - needs conversation relation
    // Basic adjustment based on feedback counts
    if (preferences.positiveFeedbackCount > 10 && preferences.negativeFeedbackCount < 3) {
      // User seems satisfied, keep current style
      return;
    }
    if (preferences.negativeFeedbackCount > preferences.positiveFeedbackCount) {
      // Try different style
      if (preferences.responseStyle === ResponseStyle.DETAILED) {
        preferences.responseStyle = ResponseStyle.CONCISE;
      } else if (preferences.responseStyle === ResponseStyle.CONCISE) {
        preferences.responseStyle = ResponseStyle.BALANCED;
      }
    }
  }

  /**
   * Update user preferences manually
   */
  async updatePreferences(
    userId: string,
    updates: Partial<UserPreferences>,
  ): Promise<UserPreferences> {
    const preferences = await this.getUserPreferences(userId);

    Object.assign(preferences, updates);

    return await this.userPreferencesRepository.save(preferences);
  }
}
