import type {
  ApiDiscoveredProfile,
  ApiDiscoveredProfileGroup,
  ApiDiscoveryOtherPage,
} from './discovery-types'
import { profileDisplayName } from './discovery-utils'

export function profileToDiscoveryGroup(
  profile: ApiDiscoveredProfile,
): ApiDiscoveredProfileGroup {
  return {
    group_key: profile.id,
    profile_ids: [profile.id],
    display_name: profileDisplayName(profile),
    primary_email: profile.primary_email,
    message_count: profile.message_count,
    profile,
    profiles: [profile],
  }
}

function isDiscoveredProfile(value: unknown): value is ApiDiscoveredProfile {
  if (!value || typeof value !== 'object') return false
  const row = value as Record<string, unknown>
  return typeof row.id === 'string' && typeof row.primary_email === 'string' && !('profile' in row)
}

export function normalizeDiscoveryGroup(
  group: ApiDiscoveredProfileGroup,
): ApiDiscoveredProfileGroup | null {
  const profile = group.profile ?? group.profiles?.[0]
  if (!profile?.id) return null

  const profileIds =
    group.profile_ids?.length > 0 ? group.profile_ids : [profile.id]

  return {
    ...group,
    group_key: group.group_key || profileIds[0] || profile.id,
    profile_ids: profileIds,
    profile,
    profiles: group.profiles?.length ? group.profiles : [profile],
    display_name: group.display_name || profileDisplayName(profile),
    primary_email: group.primary_email || profile.primary_email,
    message_count: group.message_count ?? profile.message_count,
  }
}

export interface DiscoveryOtherPageResult {
  groups: ApiDiscoveredProfileGroup[]
  total: number
  hasMore: boolean
}

export function parseDiscoveryOtherPage(
  res: ApiDiscoveryOtherPage | {
    groups?: ApiDiscoveredProfileGroup[]
    profiles?: ApiDiscoveredProfile[]
    total?: number
    has_more?: boolean
    limit?: number
    offset?: number
  },
  options?: { offset?: number; pageSize?: number },
): DiscoveryOtherPageResult {
  const offset = options?.offset ?? 0
  const pageSize = options?.pageSize ?? 20
  const allGroups = parseDiscoveryOtherResponse(res)
  const hasServerHasMore = 'has_more' in res && res.has_more != null
  const hasServerTotal = typeof res.total === 'number'
  const serverLimit = typeof res.limit === 'number' ? res.limit : undefined

  // Réponse legacy : tous les groupes en une fois sans pagination
  const looksUnpaginated =
    !hasServerHasMore &&
    !hasServerTotal &&
    allGroups.length > pageSize &&
    (serverLimit == null || serverLimit >= allGroups.length)

  if (looksUnpaginated) {
    const groups = allGroups.slice(offset, offset + pageSize)
    return {
      groups,
      total: allGroups.length,
      hasMore: offset + pageSize < allGroups.length,
    }
  }

  const groups = allGroups
  const total = hasServerTotal ? res.total! : groups.length + offset
  const hasMore = hasServerHasMore
    ? Boolean(res.has_more)
    : hasServerTotal
      ? offset + groups.length < res.total!
      : groups.length >= pageSize

  return { groups, total, hasMore }
}

export function parseDiscoveryOtherResponse(res: {
  groups?: ApiDiscoveredProfileGroup[]
  profiles?: ApiDiscoveredProfile[]
}): ApiDiscoveredProfileGroup[] {
  if (res.groups?.length) {
    const normalized: ApiDiscoveredProfileGroup[] = []
    for (const group of res.groups) {
      const row = normalizeDiscoveryGroup(group)
      if (row) normalized.push(row)
    }
    return normalized
  }

  if (res.profiles?.length) {
    return res.profiles.map(profileToDiscoveryGroup)
  }

  return []
}

/** Stable React key — prefer person group id when several profiles are merged. */
export function discoveryGroupReactKey(group: ApiDiscoveredProfileGroup): string {
  const profileIds = (group.profile_ids ?? []).filter(Boolean)
  const profileId = group.profile?.id ?? profileIds[0]
  const groupKey = group.group_key?.trim()

  if (groupKey && profileIds.length > 1) {
    return groupKey
  }
  if (groupKey && profileId && groupKey !== profileId) {
    return groupKey
  }
  return profileId ?? groupKey ?? 'unknown'
}

/** Remove duplicate groups (infinite scroll / refetch overlap). */
export function dedupeDiscoveryGroups(
  groups: ApiDiscoveredProfileGroup[],
): ApiDiscoveredProfileGroup[] {
  const seen = new Set<string>()
  const out: ApiDiscoveredProfileGroup[] = []
  for (const group of groups) {
    const normalized = normalizeDiscoveryGroup(group)
    if (!normalized) continue
    const key = discoveryGroupReactKey(normalized)
    if (seen.has(key)) continue
    seen.add(key)
    out.push(normalized)
  }
  return out
}

/** Coerce cached query rows that may still be flat profiles. */
export function coerceDiscoveryGroups(data: unknown): ApiDiscoveredProfileGroup[] {
  if (!Array.isArray(data) || data.length === 0) return []
  if (isDiscoveredProfile(data[0])) {
    return (data as ApiDiscoveredProfile[]).map(profileToDiscoveryGroup)
  }
  const out: ApiDiscoveredProfileGroup[] = []
  for (const row of data as ApiDiscoveredProfileGroup[]) {
    const normalized = normalizeDiscoveryGroup(row)
    if (normalized) out.push(normalized)
  }
  return out
}
