/**
 * Entity assignment normalization and display utilities.
 *
 * Extracted from pages/machines/new.vue – these pure functions resolve
 * machine / component / piece assignments from nested API payloads.
 */

type AnyRecord = Record<string, unknown>

// ---------------------------------------------------------------------------
// Primitive helpers
// ---------------------------------------------------------------------------

const isPlainObject = (value: unknown): value is AnyRecord =>
  value !== null && typeof value === 'object' && !Array.isArray(value)

const toTrimmedString = (value: unknown): string | null => {
  if (typeof value === 'string') {
    const trimmed = value.trim()
    return trimmed.length > 0 ? trimmed : null
  }
  if (typeof value === 'number' && Number.isFinite(value)) {
    return String(value)
  }
  return null
}

// ---------------------------------------------------------------------------
// Dedup
// ---------------------------------------------------------------------------

export const dedupeAssignments = (
  assignments: AnyRecord[],
): AnyRecord[] => {
  const seen = new Set<string>()
  return assignments.filter((assignment) => {
    if (!assignment) return false
    const id = assignment.id != null ? String(assignment.id) : ''
    const name = assignment.name != null ? String(assignment.name) : ''
    const key = `${id}::${name}`
    if (!id && !name) return false
    if (seen.has(key)) return false
    seen.add(key)
    return true
  })
}

// ---------------------------------------------------------------------------
// Machine assignments
// ---------------------------------------------------------------------------

export const normalizeMachineAssignment = (input: unknown): AnyRecord | null => {
  if (!input) return null
  if (typeof input === 'string') {
    const name = toTrimmedString(input)
    return name ? { id: name, name } : null
  }
  if (typeof input === 'number' && Number.isFinite(input)) {
    const value = String(input)
    return { id: value, name: value }
  }

  const container = (input as AnyRecord).machine || (input as AnyRecord).machineData || input
  if (!isPlainObject(container)) return null

  const id =
    container.id ?? (input as AnyRecord).machineId ?? (input as AnyRecord).id ?? null
  const name =
    container.name ||
    (input as AnyRecord).machineName ||
    container.label ||
    container.title ||
    (typeof id === 'string' ? id : null) ||
    (typeof id === 'number' ? String(id) : null)

  if (id == null && name == null) return null

  return {
    id: id != null ? id : null,
    name: name != null ? name : null,
  }
}

export const collectMachineAssignments = (source: unknown): AnyRecord[] => {
  if (!isPlainObject(source)) return []

  const candidates = [
    source.machines,
    source.machineLinks,
    source.machineAssignments,
    source.machinesAssignments,
    source.linkedMachines,
  ]

  const assignments: AnyRecord[] = []

  candidates.forEach((list) => {
    if (Array.isArray(list)) {
      list.forEach((item) => {
        const normalized = normalizeMachineAssignment(item)
        if (normalized) assignments.push(normalized)
      })
    }
  })

  if (!assignments.length) {
    const direct = normalizeMachineAssignment(source.machine)
    if (direct) assignments.push(direct)
  }

  if (!assignments.length) {
    const idCandidate = source.machineId ?? source.machineID ?? null
    const nameCandidate = source.machineName ?? null
    const normalized = normalizeMachineAssignment(nameCandidate || idCandidate)
    if (normalized) assignments.push(normalized)
  }

  return dedupeAssignments(assignments)
}

// ---------------------------------------------------------------------------
// Component assignments
// ---------------------------------------------------------------------------

export const normalizeComponentAssignment = (input: unknown): AnyRecord | null => {
  if (!input) return null
  if (typeof input === 'string') {
    const value = toTrimmedString(input)
    return value ? { id: value, name: value } : null
  }
  if (typeof input === 'number' && Number.isFinite(input)) {
    const value = String(input)
    return { id: value, name: value }
  }

  const container =
    (input as AnyRecord).component || (input as AnyRecord).composant || input
  if (!isPlainObject(container)) return null

  const id =
    container.id ??
    (input as AnyRecord).componentId ??
    (input as AnyRecord).composantId ??
    (input as AnyRecord).id ??
    null
  const name =
    container.name ||
    (input as AnyRecord).componentName ||
    (input as AnyRecord).composantName ||
    container.label ||
    (typeof id === 'string' ? id : null) ||
    (typeof id === 'number' ? String(id) : null)

  if (id == null && name == null) return null

  return {
    id: id != null ? id : null,
    name: name != null ? name : null,
  }
}

export const collectComponentAssignments = (source: unknown): AnyRecord[] => {
  if (!isPlainObject(source)) return []

  const candidates = [
    source.components,
    source.composants,
    source.componentLinks,
    source.linkedComponents,
  ]

  const assignments: AnyRecord[] = []

  candidates.forEach((list) => {
    if (Array.isArray(list)) {
      list.forEach((item) => {
        const normalized = normalizeComponentAssignment(item)
        if (normalized) assignments.push(normalized)
      })
    }
  })

  if (!assignments.length) {
    const direct = normalizeComponentAssignment(source.component || source.composant)
    if (direct) assignments.push(direct)
  }

  if (!assignments.length) {
    const idCandidate = source.componentId ?? source.composantId ?? null
    const normalized = normalizeComponentAssignment(idCandidate)
    if (normalized) assignments.push(normalized)
  }

  return dedupeAssignments(assignments)
}

// ---------------------------------------------------------------------------
// Convenience wrappers
// ---------------------------------------------------------------------------

export const getComponentMachineAssignments = (component: unknown): AnyRecord[] =>
  collectMachineAssignments(component || {})

export const getPieceMachineAssignments = (piece: unknown): AnyRecord[] =>
  collectMachineAssignments(piece || {})

export const getPieceComponentAssignments = (piece: unknown): AnyRecord[] =>
  collectComponentAssignments(piece || {})

// ---------------------------------------------------------------------------
// Display
// ---------------------------------------------------------------------------

export const formatAssignmentList = (assignments: AnyRecord[]): string => {
  if (!Array.isArray(assignments) || assignments.length === 0) return ''
  return assignments
    .map((assignment) => (assignment?.name || assignment?.id) as string)
    .filter(Boolean)
    .join(', ')
}
