import { Injectable, Inject } from '@nestjs/common';
import { EmbeddingService } from '../../infrastructure/embedding/embedding.service';
import { Neo4jService } from '../../infrastructure/database/neo4j/neo4j.service';
import {
  IUserMemoryRepository,
  ISystemExperienceRepository,
  USER_MEMORY_REPOSITORY,
  SYSTEM_EXPERIENCE_REPOSITORY,
} from '../../domain/repositories/memory.repository.interface';
import { UserMemoryEntity, MemoryType } from '../../domain/entities/user-memory.entity';
import {
  SystemExperienceEntity,
  ExperienceType,
  VerificationStatus,
} from '../../domain/entities/system-experience.entity';

/**
 * 记忆管理服务
 * 管理用户长期记忆和系统经验
 */
@Injectable()
export class MemoryService {
  constructor(
    private embeddingService: EmbeddingService,
    private neo4jService: Neo4jService,
    @Inject(USER_MEMORY_REPOSITORY)
    private memoryRepo: IUserMemoryRepository,
    @Inject(SYSTEM_EXPERIENCE_REPOSITORY)
    private experienceRepo: ISystemExperienceRepository,
  ) {}

  // ========== 用户记忆 ==========

  /**
   * 保存用户记忆
   */
  async saveUserMemory(params: {
    userId: string;
    memoryType: MemoryType;
    content: string;
    importance?: number;
    sourceConversationId?: string;
    relatedCategory?: string;
  }): Promise<UserMemoryEntity> {
    const memory = UserMemoryEntity.create(params);

    // 生成向量
    const embedding = await this.embeddingService.getEmbedding(params.content);
    memory.setEmbedding(embedding);

    // 保存到PostgreSQL
    await this.memoryRepo.save(memory);

    // 同时记录到Neo4j时间线
    await this.neo4jService.recordUserEvent({
      userId: params.userId,
      eventId: memory.id,
      eventType: `MEMORY_${params.memoryType}`,
      content: params.content,
      metadata: {
        importance: params.importance,
        relatedCategory: params.relatedCategory,
      },
    });

    console.log(`[MemoryService] Saved memory for user ${params.userId}: ${params.memoryType}`);

    return memory;
  }

  /**
   * 获取用户的相关记忆
   */
  async getUserRelevantMemories(
    userId: string,
    query: string,
    options?: { limit?: number; memoryTypes?: MemoryType[] },
  ): Promise<UserMemoryEntity[]> {
    const embedding = await this.embeddingService.getEmbedding(query);

    const results = await this.memoryRepo.searchByVector(userId, embedding, {
      limit: options?.limit || 5,
      minSimilarity: 0.6,
    });

    // 记录访问
    for (const { memory } of results) {
      memory.recordAccess();
      await this.memoryRepo.update(memory);
    }

    return results.map(r => r.memory);
  }

  /**
   * 获取用户最重要的记忆（用于对话上下文）
   */
  async getUserTopMemories(userId: string, limit = 5): Promise<UserMemoryEntity[]> {
    return this.memoryRepo.findTopMemories(userId, limit);
  }

  /**
   * 获取用户所有记忆
   */
  async getUserMemories(
    userId: string,
    options?: { memoryType?: MemoryType; includeExpired?: boolean },
  ): Promise<UserMemoryEntity[]> {
    return this.memoryRepo.findByUserId(userId, options);
  }

  /**
   * 更新记忆重要性
   */
  async updateMemoryImportance(memoryId: string, importance: number): Promise<void> {
    const memory = await this.memoryRepo.findById(memoryId);
    if (memory) {
      memory.updateImportance(importance);
      await this.memoryRepo.update(memory);
    }
  }

  /**
   * 标记记忆为过期
   */
  async expireMemory(memoryId: string): Promise<void> {
    const memory = await this.memoryRepo.findById(memoryId);
    if (memory) {
      memory.markAsExpired();
      await this.memoryRepo.update(memory);
    }
  }

  /**
   * 清理过期记忆
   */
  async cleanupExpiredMemories(userId: string, olderThanDays = 180): Promise<number> {
    return this.memoryRepo.markExpiredMemories(userId, olderThanDays);
  }

  /**
   * 删除用户所有记忆（GDPR合规）
   */
  async deleteUserMemories(userId: string): Promise<void> {
    await this.memoryRepo.deleteByUserId(userId);
    console.log(`[MemoryService] Deleted all memories for user ${userId}`);
  }

  // ========== 系统经验 ==========

  /**
   * 提取并保存系统经验
   */
  async extractAndSaveExperience(params: {
    experienceType: ExperienceType;
    content: string;
    scenario: string;
    relatedCategory?: string;
    sourceConversationId: string;
    confidence?: number;
  }): Promise<SystemExperienceEntity> {
    // 生成向量
    const embedding = await this.embeddingService.getEmbedding(
      `${params.scenario}\n${params.content}`,
    );

    // 查找相似经验（用于合并）
    const similarExperiences = await this.experienceRepo.findSimilarExperiences(
      embedding,
      0.9, // 高阈值，只合并非常相似的
    );

    if (similarExperiences.length > 0) {
      // 合并到现有经验
      const existingExperience = similarExperiences[0];
      existingExperience.addSourceConversation(params.sourceConversationId);
      existingExperience.setEmbedding(embedding); // 可以选择更新向量
      await this.experienceRepo.update(existingExperience);

      console.log(`[MemoryService] Merged experience into ${existingExperience.id}`);
      return existingExperience;
    }

    // 创建新经验
    const experience = SystemExperienceEntity.create(params);
    experience.setEmbedding(embedding);
    await this.experienceRepo.save(experience);

    console.log(`[MemoryService] Created new experience: ${experience.id}`);
    return experience;
  }

  /**
   * 获取相关系统经验
   */
  async getRelevantExperiences(
    query: string,
    options?: {
      experienceType?: ExperienceType;
      category?: string;
      limit?: number;
    },
  ): Promise<SystemExperienceEntity[]> {
    const embedding = await this.embeddingService.getEmbedding(query);

    const results = await this.experienceRepo.searchByVector(embedding, {
      experienceType: options?.experienceType,
      activeOnly: true,
      limit: options?.limit || 5,
      minSimilarity: 0.7,
    });

    // 记录使用
    for (const { experience } of results) {
      experience.recordUsage();
      await this.experienceRepo.update(experience);
    }

    return results.map(r => r.experience);
  }

  /**
   * 获取待验证的经验
   */
  async getPendingExperiences(options?: {
    experienceType?: ExperienceType;
    page?: number;
    pageSize?: number;
  }): Promise<{
    items: SystemExperienceEntity[];
    total: number;
  }> {
    const page = options?.page || 1;
    const pageSize = options?.pageSize || 20;

    const items = await this.experienceRepo.findPendingExperiences({
      experienceType: options?.experienceType,
      limit: pageSize,
      offset: (page - 1) * pageSize,
    });

    // 简单计数（实际应该有专门的count方法）
    const stats = await this.experienceRepo.getStatistics();
    const total = stats.byStatus[VerificationStatus.PENDING] || 0;

    return { items, total };
  }

  /**
   * 审批经验
   */
  async approveExperience(experienceId: string, adminId: string): Promise<void> {
    const experience = await this.experienceRepo.findById(experienceId);
    if (!experience) {
      throw new Error(`Experience not found: ${experienceId}`);
    }

    experience.approve(adminId);
    await this.experienceRepo.update(experience);

    console.log(`[MemoryService] Experience ${experienceId} approved by ${adminId}`);
  }

  /**
   * 拒绝经验
   */
  async rejectExperience(experienceId: string, adminId: string): Promise<void> {
    const experience = await this.experienceRepo.findById(experienceId);
    if (!experience) {
      throw new Error(`Experience not found: ${experienceId}`);
    }

    experience.reject(adminId);
    await this.experienceRepo.update(experience);

    console.log(`[MemoryService] Experience ${experienceId} rejected by ${adminId}`);
  }

  /**
   * 记录经验反馈
   */
  async recordExperienceFeedback(experienceId: string, positive: boolean): Promise<void> {
    const experience = await this.experienceRepo.findById(experienceId);
    if (experience) {
      experience.recordFeedback(positive);
      await this.experienceRepo.update(experience);
    }
  }

  /**
   * 获取经验统计
   */
  async getExperienceStatistics(): Promise<{
    total: number;
    byStatus: Record<VerificationStatus, number>;
    byType: Record<ExperienceType, number>;
  }> {
    return this.experienceRepo.getStatistics();
  }

  // ========== 用户时间线（Neo4j） ==========

  /**
   * 获取用户时间线
   */
  async getUserTimeline(
    userId: string,
    options?: {
      limit?: number;
      beforeDate?: Date;
      eventTypes?: string[];
    },
  ) {
    return this.neo4jService.getUserTimeline(userId, options);
  }

  /**
   * 初始化用户节点
   */
  async initializeUserNode(userId: string, properties?: Record<string, unknown>): Promise<void> {
    await this.neo4jService.createUserNode(userId, properties);
  }
}
