import type {
  ApiDiscoveredProfile,
  ApiEnrichedContactData,
  ApiEnrichmentSuggestion,
} from './discovery-types'
import type { FullContact } from './types'

const LABEL_MAP: Record<string, string> = {
  work: 'Travail',
  home: 'Domicile',
  mobile: 'Mobile',
  other: 'Autre',
  linkedin: 'LinkedIn',
  twitter: 'X / Twitter',
  facebook: 'Facebook',
  instagram: 'Instagram',
  github: 'GitHub',
}

function mapLabel(label?: string): string {
  if (!label) return 'Autre'
  return LABEL_MAP[label.toLowerCase()] ?? label
}

export function discoveredProfileToFullContact(profile: ApiDiscoveredProfile): FullContact {
  const data: ApiEnrichedContactData | undefined = profile.enriched_data
  const now = Date.now()

  const emails = data?.emails?.length
    ? data.emails.map((e) => ({ value: e.value, label: mapLabel(e.label) }))
    : [{ value: profile.primary_email, label: 'Autre' }]

  const phones = (data?.phones ?? []).map((p) => ({
    value: p.value,
    label: mapLabel(p.label),
  }))

  const addresses = (data?.addresses ?? []).map((a) => ({
    street: a.street,
    city: a.city,
    region: a.region,
    postalCode: a.postal_code,
    country: a.country,
    label: mapLabel(a.label),
  }))

  const socialProfiles = (data?.social_profiles ?? []).map((p) => ({
    value: p.value,
    label: mapLabel(p.label),
  }))

  return {
    id: profile.id,
    firstName: data?.first_name ?? profile.display_name.split(' ')[0] ?? '',
    lastName: data?.last_name ?? profile.display_name.split(' ').slice(1).join(' ') ?? '',
    company: data?.company,
    department: data?.department,
    jobTitle: data?.job_title,
    website: data?.website,
    socialProfiles: socialProfiles.length > 0 ? socialProfiles : undefined,
    emails,
    phones,
    addresses: addresses.length > 0 ? addresses : undefined,
    notes: data?.notes,
    interactionCount: profile.message_count,
    isOtherContact: true,
    createdAt: now,
    updatedAt: now,
  }
}

function emailLocalPart(email: string): string {
  const at = email.lastIndexOf('@')
  if (at <= 0) return email.trim().toLowerCase()
  return email.slice(0, at).trim().toLowerCase()
}

function hasMeaningfulDisplayName(name: string | undefined, email: string): boolean {
  const trimmed = name?.trim()
  if (!trimmed || trimmed.includes('@')) return false
  const local = emailLocalPart(email)
  if (!local) return true
  return trimmed.toLowerCase() !== local
}

function enrichedDataHasValueBeyondEmail(
  data: ApiEnrichedContactData | undefined | null,
): boolean {
  if (!data) return false
  if (
    data.first_name?.trim() ||
    data.last_name?.trim() ||
    data.company?.trim() ||
    data.department?.trim() ||
    data.job_title?.trim() ||
    data.website?.trim() ||
    data.notes?.trim()
  ) {
    return true
  }
  if (data.social_profiles?.some((p) => p.value?.trim())) return true
  if (data.phones?.some((p) => p.value?.trim())) return true
  return (
    data.addresses?.some(
      (a) =>
        a.street?.trim() ||
        a.city?.trim() ||
        a.region?.trim() ||
        a.postal_code?.trim() ||
        a.country?.trim(),
    ) ?? false
  )
}

/** True when profile has more than a bare email (signature, name, enriched fields, etc.). */
export function profileHasValueBeyondEmail(profile: ApiDiscoveredProfile): boolean {
  if ((profile.signatures?.length ?? 0) > 0) return true
  if (enrichedDataHasValueBeyondEmail(profile.enriched_data)) return true
  if (hasMeaningfulDisplayName(profile.display_name, profile.primary_email)) return true
  for (const e of profile.all_emails ?? []) {
    if (hasMeaningfulDisplayName(e.display_name, e.email)) return true
  }
  return false
}

export function isSuggestableDiscoveryGroup(group: {
  profile?: ApiDiscoveredProfile
  profiles?: ApiDiscoveredProfile[]
}): boolean {
  const profiles = group.profiles?.length
    ? group.profiles
    : group.profile
      ? [group.profile]
      : []
  if (profiles.some((p) => profileHasNoReplyEmail(p))) return false
  return profiles.some((p) => profileHasValueBeyondEmail(p))
}

export function profileDisplayName(profile: ApiDiscoveredProfile): string {
  const data = profile.enriched_data
  if (data?.first_name || data?.last_name) {
    return `${data.first_name ?? ''} ${data.last_name ?? ''}`.trim()
  }
  return profile.display_name || profile.primary_email
}

function normalizePhone(s: string): string {
  return s.replace(/\D/g, '')
}

function phonesMatch(a: string, b: string): boolean {
  const na = normalizePhone(a)
  const nb = normalizePhone(b)
  if (!na || !nb) return false
  if (na.length >= 9 && nb.length >= 9) {
    return na.slice(-9) === nb.slice(-9)
  }
  return na === nb
}

function stringsEqualInsensitive(a: string, b: string): boolean {
  return a.trim().toLowerCase() === b.trim().toLowerCase()
}

export function isNoReplyEmail(email: string): boolean {
  const lower = email.trim().toLowerCase()
  return (
    lower.includes('noreply') ||
    lower.includes('no-reply') ||
    lower.includes('no_reply')
  )
}

function profileHasNoReplyEmail(profile: ApiDiscoveredProfile): boolean {
  if (isNoReplyEmail(profile.primary_email)) return true
  for (const e of profile.all_emails ?? []) {
    if (isNoReplyEmail(e.email)) return true
  }
  for (const e of profile.enriched_data?.emails ?? []) {
    if (isNoReplyEmail(e.value)) return true
  }
  return false
}

/** Suggestions shown in « Ajouter des coordonnées » (enrichissement de contacts existants). */
export function filterVisibleEnrichmentSuggestions(
  rawSuggestions: ApiEnrichmentSuggestion[],
  contacts: FullContact[],
): ApiEnrichmentSuggestion[] {
  return rawSuggestions.filter((s) => {
    if (s.suggestion_type !== 'enrich_contact' || !s.target_contact_uid) {
      return true
    }
    const contact = contacts.find((c) => c.id === s.target_contact_uid)
    if (!contact) return true
    return !isEnrichmentSuggestionRedundant(contact, s)
  })
}

/** True when the suggestion value is already present on the contact. */
export function isEnrichmentSuggestionRedundant(
  contact: FullContact,
  suggestion: Pick<ApiEnrichmentSuggestion, 'field_path' | 'suggested_value'>,
): boolean {
  const val = suggestion.suggested_value.trim()
  if (!val) return true

  switch (suggestion.field_path) {
    case 'full_name': {
      const full = `${contact.firstName} ${contact.lastName}`.trim()
      return stringsEqualInsensitive(val, full)
    }
    case 'company':
      return contact.company ? stringsEqualInsensitive(val, contact.company) : false
    case 'job_title':
      return contact.jobTitle ? stringsEqualInsensitive(val, contact.jobTitle) : false
    case 'phones':
      return contact.phones.some((p) => phonesMatch(p.value, val))
    case 'emails':
      return contact.emails.some((e) => stringsEqualInsensitive(e.value, val))
    case 'social_profiles':
      return (contact.socialProfiles ?? []).some((p) => stringsEqualInsensitive(p.value, val))
    default:
      return false
  }
}

export const FIELD_LABELS: Record<string, string> = {
  first_name: 'Prénom',
  last_name: 'Nom',
  company: 'Entreprise',
  department: 'Service',
  job_title: 'Poste',
  emails: 'E-mail',
  phones: 'Téléphone',
  addresses: 'Adresse',
  website: 'Site web',
  social_profiles: 'Réseaux sociaux',
  notes: 'Notes',
  full_name: 'Nom complet',
}
