// 身份识别与合并服务
// 实现基于数据字典标识的关键字段的匹配逻辑

import { getIdentityKeyFields } from "@/lib/data-dictionary"

export interface IdentityMatch {
  userId: string
  confidence: number
  matchedFields: string[]
  matchType: "exact" | "fuzzy" | "partial"
}

export interface UserIdentity {
  userId: string
  identityFields: Record<string, any>
}

export class IdentityService {
  private static instance: IdentityService
  private userIdentities: Map<string, UserIdentity> = new Map()

  private constructor() {
    // 初始化一些模拟数据
    this.initializeMockData()
  }

  public static getInstance(): IdentityService {
    if (!IdentityService.instance) {
      IdentityService.instance = new IdentityService()
    }
    return IdentityService.instance
  }

  private initializeMockData() {
    // 模拟已存在的用户身份数据
    const mockUsers = [
      {
        userId: "user_global_id_1",
        identityFields: {
          phone: "13800138000",
          email: "zhangsan@example.com",
          username: "zhangsan",
          fullName: "张三",
        },
      },
      {
        userId: "user_global_id_2",
        identityFields: {
          phone: "13912345678",
          email: "lisi@example.com",
          username: "lisi",
          fullName: "李四",
        },
      },
    ]

    mockUsers.forEach((user) => {
      this.userIdentities.set(user.userId, user)
    })
  }

  // 根据输入数据查找匹配的用户身份
  public async findMatchingIdentity(inputData: Record<string, any>): Promise<IdentityMatch[]> {
    const identityKeyFields = getIdentityKeyFields()
    const matches: IdentityMatch[] = []

    for (const [userId, userIdentity] of this.userIdentities) {
      const matchResult = this.calculateMatch(inputData, userIdentity.identityFields, identityKeyFields)
      if (matchResult.confidence > 0) {
        matches.push({
          userId,
          ...matchResult,
        })
      }
    }

    // 按置信度排序
    return matches.sort((a, b) => b.confidence - a.confidence)
  }

  // 计算匹配度
  private calculateMatch(
    inputData: Record<string, any>,
    existingData: Record<string, any>,
    keyFields: string[],
  ): { confidence: number; matchedFields: string[]; matchType: "exact" | "fuzzy" | "partial" } {
    const matchedFields: string[] = []
    let exactMatches = 0
    let fuzzyMatches = 0
    let totalFields = 0

    for (const field of keyFields) {
      if (inputData[field] && existingData[field]) {
        totalFields++

        if (this.isExactMatch(inputData[field], existingData[field])) {
          exactMatches++
          matchedFields.push(field)
        } else if (this.isFuzzyMatch(inputData[field], existingData[field])) {
          fuzzyMatches++
          matchedFields.push(field)
        }
      }
    }

    if (totalFields === 0) {
      return { confidence: 0, matchedFields: [], matchType: "partial" }
    }

    const confidence = (exactMatches * 1.0 + fuzzyMatches * 0.7) / totalFields

    let matchType: "exact" | "fuzzy" | "partial" = "partial"
    if (exactMatches > 0 && fuzzyMatches === 0) {
      matchType = "exact"
    } else if (exactMatches > 0 || fuzzyMatches > 0) {
      matchType = "fuzzy"
    }

    return { confidence, matchedFields, matchType }
  }

  // 精确匹配
  private isExactMatch(value1: any, value2: any): boolean {
    if (typeof value1 === "string" && typeof value2 === "string") {
      return value1.toLowerCase().trim() === value2.toLowerCase().trim()
    }
    return value1 === value2
  }

  // 模糊匹配
  private isFuzzyMatch(value1: any, value2: any): boolean {
    if (typeof value1 === "string" && typeof value2 === "string") {
      const str1 = value1.toLowerCase().trim()
      const str2 = value2.toLowerCase().trim()

      // 简单的相似度计算
      const similarity = this.calculateStringSimilarity(str1, str2)
      return similarity > 0.8
    }
    return false
  }

  // 计算字符串相似度
  private calculateStringSimilarity(str1: string, str2: string): number {
    const longer = str1.length > str2.length ? str1 : str2
    const shorter = str1.length > str2.length ? str2 : str1

    if (longer.length === 0) {
      return 1.0
    }

    const editDistance = this.levenshteinDistance(longer, shorter)
    return (longer.length - editDistance) / longer.length
  }

  // 计算编辑距离
  private levenshteinDistance(str1: string, str2: string): number {
    const matrix = []

    for (let i = 0; i <= str2.length; i++) {
      matrix[i] = [i]
    }

    for (let j = 0; j <= str1.length; j++) {
      matrix[0][j] = j
    }

    for (let i = 1; i <= str2.length; i++) {
      for (let j = 1; j <= str1.length; j++) {
        if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
          matrix[i][j] = matrix[i - 1][j - 1]
        } else {
          matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1)
        }
      }
    }

    return matrix[str2.length][str1.length]
  }

  // 创建新的用户身份
  public async createNewIdentity(inputData: Record<string, any>): Promise<string> {
    const userId = `user_global_id_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
    const identityKeyFields = getIdentityKeyFields()

    const identityFields: Record<string, any> = {}
    identityKeyFields.forEach((field) => {
      if (inputData[field]) {
        identityFields[field] = inputData[field]
      }
    })

    this.userIdentities.set(userId, {
      userId,
      identityFields,
    })

    return userId
  }

  // 更新用户身份信息
  public async updateIdentity(userId: string, updateData: Record<string, any>): Promise<void> {
    const existingIdentity = this.userIdentities.get(userId)
    if (existingIdentity) {
      const identityKeyFields = getIdentityKeyFields()
      identityKeyFields.forEach((field) => {
        if (updateData[field]) {
          existingIdentity.identityFields[field] = updateData[field]
        }
      })
      this.userIdentities.set(userId, existingIdentity)
    }
  }

  // 合并用户身份
  public async mergeIdentities(primaryUserId: string, secondaryUserId: string): Promise<void> {
    const primaryIdentity = this.userIdentities.get(primaryUserId)
    const secondaryIdentity = this.userIdentities.get(secondaryUserId)

    if (primaryIdentity && secondaryIdentity) {
      // 合并身份字段，优先保留主身份的数据
      Object.keys(secondaryIdentity.identityFields).forEach((field) => {
        if (!primaryIdentity.identityFields[field] && secondaryIdentity.identityFields[field]) {
          primaryIdentity.identityFields[field] = secondaryIdentity.identityFields[field]
        }
      })

      this.userIdentities.set(primaryUserId, primaryIdentity)
      this.userIdentities.delete(secondaryUserId)
    }
  }
}
