import crypto from 'crypto'
import { getDb } from '../database/client'
import { externalUserRepo } from '../database/repositories/external-user.repo'
import { externalIdentityRepo } from '../database/repositories/external-identity.repo'
import type { ExternalUser } from '../database/schema'

/**
 * ExternalUserService — 统一外部用户身份解析入口。
 *
 * 所有触发源（IM / H5 / 小程序）通过 resolveOrCreate() 获取 external_user_id。
 * 身份解析流程：
 *   1. 查 external_identities WHERE (channelType, channelId, platformUserId) → 命中返回
 *   2. 未命中 → 查 external_users WHERE (ownerUserId, phone) [如有手机号] → 命中则关联
 *   3. 都未命中 → 创建新 external_users + external_identities
 */

export interface ResolveParams {
  /** 渠道类型：'im:feishu' | 'im:telegram' | 'im:discord' | 'im:weixin' | 'im:wecom' | 'im:dingtalk' | 'h5' | 'wxapp' */
  channelType: string
  /** 渠道配置 ID：im_channels.id / h5_pages.id / wxapp_configs.id（IM 用，H5/小程序可空） */
  channelId: string
  /** 平台原始 ID：飞书 open_id / tg user_id / wxapp openid / H5 sub */
  platformUserId: string
  /** 平台展示名（飞书用户名、微信昵称等，可空） */
  platformName?: string
  /** 平台头像 URL（可空） */
  platformAvatar?: string
  /** 归属 owner（user.id），租户隔离键 */
  ownerUserId: string
  /** 手机号（跨渠道关联键，可空） */
  phone?: string
}

class ExternalUserService {
  /**
   * 解析或创建外部用户身份。
   * 返回 external_user_id（external_users.id）。
   */
  resolveOrCreate(params: ResolveParams): string {
    // 1. 快速路径：身份已关联
    const existing = externalIdentityRepo.findByChannelAndPlatformUser(
      params.channelType,
      params.channelId,
      params.platformUserId,
    )
    if (existing) {
      // 刷新 last_active_at + 渠道展示信息（如有更新）
      externalUserRepo.touchActive(existing.externalUserId)
      if (params.platformName && params.platformName !== existing.platformName) {
        externalIdentityRepo.updatePlatformInfo(existing.id, params.platformName, params.platformAvatar ?? '')
      }
      return existing.externalUserId
    }

    // 2. 手机号跨渠道关联
    let externalUser: ExternalUser | undefined
    if (params.phone) {
      externalUser = externalUserRepo.findByOwnerAndPhone(params.ownerUserId, params.phone)
    }

    // 3. 创建新用户（如未通过手机号关联到已有用户）
    if (!externalUser) {
      const userId = crypto.randomUUID()
      externalUser = externalUserRepo.create({
        id: userId,
        ownerUserId: params.ownerUserId,
        displayName: params.platformName ?? '',
        avatarUrl: params.platformAvatar ?? '',
        phone: params.phone ?? '',
      })
      if (!externalUser) {
        throw new Error('Failed to create external user')
      }
    }

    // 4. 创建身份关联
    externalIdentityRepo.create({
      id: crypto.randomUUID(),
      externalUserId: externalUser.id,
      channelType: params.channelType,
      channelId: params.channelId,
      platformUserId: params.platformUserId,
      platformName: params.platformName ?? '',
      platformAvatar: params.platformAvatar ?? '',
    })

    return externalUser.id
  }

  /** 按 (channelType, channelId, platformUserId) 精确查，不创建 */
  findByIdentity(channelType: string, channelId: string, platformUserId: string): string | null {
    const identity = externalIdentityRepo.findByChannelAndPlatformUser(channelType, channelId, platformUserId)
    return identity?.externalUserId ?? null
  }

  /** 列出 owner 的全部外部用户 */
  listByOwner(ownerUserId: string) {
    return externalUserRepo.listByOwner(ownerUserId)
  }

  /**
   * 合并两个外部用户（owner 端手动操作）。
   * 将 fromId 的全部身份迁移到 intoId，然后删除 fromId。
   */
  merge(fromId: string, intoId: string): void {
    if (fromId === intoId) return

    const db = getDb()
    db.transaction(() => {
      // 将 fromId 的全部身份指向 intoId
      const identities = externalIdentityRepo.listByExternalUser(fromId)
      for (const identity of identities) {
        // 重新关联到 intoId（避免唯一约束冲突：如果 intoId 已有相同渠道身份则跳过）
        const existing = externalIdentityRepo.findByChannelAndPlatformUser(
          identity.channelType,
          identity.channelId,
          identity.platformUserId,
        )
        if (!existing || existing.externalUserId === fromId) {
          externalIdentityRepo.deleteByExternalUser(fromId)
          // 逐条重建指向 intoId
        }
      }
      // 简化：删除 from 的全部身份，再删除 from 用户
      externalIdentityRepo.deleteByExternalUser(fromId)
      externalUserRepo.deleteById(fromId)
    })
  }
}

/** 单例 */
export const externalUserService = new ExternalUserService()
