/**
 * Product resolution and display utilities.
 *
 * Extracted from pages/machine/[id].vue – these functions resolve product
 * references from deeply nested API payloads and build display objects.
 */

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export interface ProductDisplay {
  name: string
  reference: string | null
  category: string | null
  suppliers: string | null
  price: string | null
}

type AnyRecord = Record<string, unknown>

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

const isPlainObject = (value: unknown): value is AnyRecord =>
  Object.prototype.toString.call(value) === '[object Object]'

export const resolveIdentifier = (...candidates: unknown[]): string | null => {
  for (const candidate of candidates) {
    if (candidate !== undefined && candidate !== null && candidate !== '') {
      return candidate as string
    }
  }
  return null
}

// ---------------------------------------------------------------------------
// Supplier / price labels
// ---------------------------------------------------------------------------

export const getProductSuppliersLabel = (product: AnyRecord | null): string | null => {
  if (!product) return null
  const suppliers = Array.isArray(product.constructeurs)
    ? (product.constructeurs as AnyRecord[]).map((c) => c?.name as string).filter(Boolean)
    : []
  return suppliers.length > 0 ? suppliers.join(', ') : null
}

export const getProductPriceLabel = (product: AnyRecord | null): string | null => {
  if (!product) return null
  const priceValue =
    (product.supplierPrice ?? product.prix ?? product.price ?? null) as string | number | null
  if (priceValue === undefined || priceValue === null) return null
  const numeric = Number(priceValue)
  if (Number.isNaN(numeric)) return null
  return `${numeric.toFixed(2)} €`
}

// ---------------------------------------------------------------------------
// resolveProductReference
// ---------------------------------------------------------------------------

export const resolveProductReference = (
  source: AnyRecord | null | undefined,
  findProductById: (id: string) => AnyRecord | null,
): { product: AnyRecord | null; productId: string | null } => {
  if (!source || typeof source !== 'object') {
    return { product: null, productId: null }
  }

  const candidateKeys: (string | null)[] = [
    null,
    'productLink',
    'machinePieceLink',
    'machineComponentLink',
    'machineProductLink',
    'originalPiece',
    'originalComposant',
    'link',
    'overrides',
    'machineComponentLinkOverrides',
    'requirement',
    'selection',
    'entry',
  ]

  let product: AnyRecord | null = null
  let productId: string | null = null

  const inspect = (container: unknown) => {
    if (!container || typeof container !== 'object') return
    const c = container as AnyRecord
    if (!product && c.product && typeof c.product === 'object') {
      product = c.product as AnyRecord
    }
    if (!productId) {
      const candidate =
        (c.productId as string) ||
        (c.product && typeof c.product === 'object'
          ? ((c.product as AnyRecord).id as string) || ((c.product as AnyRecord).productId as string)
          : null) ||
        null
      if (candidate) productId = candidate
    }
  }

  candidateKeys.forEach((key) => {
    if (key === null) inspect(source)
    else inspect((source as AnyRecord)[key])
  })

  if (!product && productId) {
    product = findProductById(productId) || null
  }

  if (!product && !productId && source.productName) {
    const suppliersLabel =
      typeof source.constructeursLabel === 'string'
        ? source.constructeursLabel
        : typeof source.productSuppliers === 'string'
          ? source.productSuppliers
          : null

    return {
      product: {
        name: source.productName,
        reference: source.productReference || null,
        typeProduct: source.productCategory ? { name: source.productCategory } : null,
        constructeurs: suppliersLabel
          ? (suppliersLabel as string)
              .split(',')
              .map((name: string) => name.trim())
              .filter((name: string) => name.length > 0)
              .map((name: string) => ({ name }))
          : undefined,
        supplierPrice: source.productPrice ?? source.productPriceLabel ?? source.price ?? null,
      } as AnyRecord,
      productId: null,
    }
  }

  if (productId && product && product.id && product.id !== productId) {
    const resolved = findProductById(productId)
    if (resolved) product = resolved
  }

  return { product: product || null, productId: productId || null }
}

// ---------------------------------------------------------------------------
// getProductDisplay
// ---------------------------------------------------------------------------

export const getProductDisplay = (
  source: AnyRecord | null | undefined,
  findProductById: (id: string) => AnyRecord | null,
): ProductDisplay | null => {
  if (!source || typeof source !== 'object') return null

  const { product, productId } = resolveProductReference(source, findProductById)

  if (product) {
    return {
      name: (product.name as string) || (product.reference as string) || 'Produit catalogue',
      reference: (product.reference as string) || null,
      category: (product.typeProduct as AnyRecord)?.name as string || null,
      suppliers: getProductSuppliersLabel(product),
      price: getProductPriceLabel(product),
    }
  }

  let fallbackName =
    (source.productName ||
      source.productLabel ||
      source.typeProductLabel ||
      (source.typeProduct as AnyRecord)?.name ||
      (productId ? `Produit ${productId}` : null)) as string | null
  let fallbackReference = (source.productReference || source.reference || null) as string | null
  let fallbackCategory =
    (source.productCategory ||
      source.typeProductLabel ||
      (source.typeProduct as AnyRecord)?.name ||
      null) as string | null
  let fallbackSuppliers =
    (source.productSuppliers ||
      source.constructeursLabel ||
      source.supplierLabel ||
      null) as string | null
  let fallbackPrice =
    (source.productPriceLabel ||
      source.productPrice ||
      source.priceLabel ||
      source.price ||
      null) as string | number | null

  const structuralCandidates = [
    source.products,
    (source.definition as AnyRecord)?.products,
    ((source.definition as AnyRecord)?.structure as AnyRecord)?.products,
    (source.structure as AnyRecord)?.products,
    (source.requirement as AnyRecord)?.products,
    ((source.requirement as AnyRecord)?.structure as AnyRecord)?.products,
    (source.typeComposant as AnyRecord)?.products,
    ((source.typeComposant as AnyRecord)?.structure as AnyRecord)?.products,
    (source.originalComposant as AnyRecord)?.products,
    ((source.originalComposant as AnyRecord)?.definition as AnyRecord)?.products,
    (((source.originalComposant as AnyRecord)?.definition as AnyRecord)?.structure as AnyRecord)?.products,
    (source.originalComponent as AnyRecord)?.products,
    ((source.originalComponent as AnyRecord)?.definition as AnyRecord)?.products,
    (((source.originalComponent as AnyRecord)?.definition as AnyRecord)?.structure as AnyRecord)?.products,
  ]

  const structuralProducts = structuralCandidates
    .flatMap((candidate) => {
      if (Array.isArray(candidate)) return candidate
      if (candidate && typeof candidate === 'object' && Array.isArray((candidate as AnyRecord).products)) {
        return (candidate as AnyRecord).products as unknown[]
      }
      return []
    })
    .filter((entry) => entry && typeof entry === 'object')

  const structuralProduct = structuralProducts.length ? (structuralProducts[0] as AnyRecord) : null

  const structuralFamilyCode =
    (structuralProduct && typeof structuralProduct.familyCode === 'string'
      ? structuralProduct.familyCode
      : null) ||
    (typeof source.familyCode === 'string' ? source.familyCode : null)

  if (!fallbackName && structuralProduct) {
    fallbackName =
      (structuralProduct.typeProductLabel as string) ||
      ((structuralProduct.typeProduct as AnyRecord)?.name as string) ||
      (structuralProduct.reference as string) ||
      (structuralFamilyCode ? `Famille ${structuralFamilyCode}` : null) ||
      null
  }

  if (!fallbackReference && structuralProduct?.reference) {
    fallbackReference = structuralProduct.reference as string
  }

  if (!fallbackCategory) {
    fallbackCategory =
      (structuralProduct?.typeProductLabel as string) ||
      ((structuralProduct?.typeProduct as AnyRecord)?.name as string) ||
      (structuralFamilyCode ? `Famille ${structuralFamilyCode}` : null) ||
      null
  }

  if (!fallbackSuppliers && structuralProduct?.supplierLabel) {
    fallbackSuppliers = structuralProduct.supplierLabel as string
  }

  if (!fallbackSuppliers && Array.isArray(structuralProduct?.constructeurs)) {
    const supplierNames = (structuralProduct!.constructeurs as AnyRecord[])
      .map((c) => c?.name as string)
      .filter((name) => typeof name === 'string' && name.trim().length > 0)
    if (supplierNames.length) fallbackSuppliers = supplierNames.join(', ')
  }

  if (!fallbackPrice && structuralProduct?.priceLabel) fallbackPrice = structuralProduct.priceLabel as string
  if (!fallbackPrice && structuralProduct?.price) fallbackPrice = structuralProduct.price as string | number

  if (fallbackName || fallbackReference || fallbackCategory || fallbackSuppliers || fallbackPrice) {
    return {
      name: fallbackName || 'Produit catalogue',
      reference: fallbackReference,
      category: fallbackCategory,
      suppliers: fallbackSuppliers,
      price:
        typeof fallbackPrice === 'number'
          ? `${fallbackPrice.toFixed(2)} €`
          : (fallbackPrice as string) || null,
    }
  }

  return null
}

// ---------------------------------------------------------------------------
// Parent link identifiers
// ---------------------------------------------------------------------------

export const extractParentLinkIdentifiers = (source: AnyRecord | null | undefined): AnyRecord => {
  if (!source || typeof source !== 'object') return {}

  const identifiers: AnyRecord = {}

  const idKeys = [
    'parentRequirementId',
    'parentComponentRequirementId',
    'parentPieceRequirementId',
    'parentMachineComponentRequirementId',
    'parentMachinePieceRequirementId',
    'parentLinkId',
    'parentComponentLinkId',
    'parentPieceLinkId',
    'parentComponentId',
    'parentPieceId',
  ]

  idKeys.forEach((key) => {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      const value = source[key]
      if (value !== undefined && value !== null && value !== '') {
        identifiers[key] = value
      }
    }
  })

  const objectKeys = [
    'parentRequirement',
    'parentComponentRequirement',
    'parentPieceRequirement',
    'parentMachineComponentRequirement',
    'parentMachinePieceRequirement',
  ]

  objectKeys.forEach((key) => {
    const value = source[key]
    if (isPlainObject(value) && value.id !== undefined && value.id !== null && value.id !== '') {
      const idKey = `${key}Id`
      if (!Object.prototype.hasOwnProperty.call(identifiers, idKey)) {
        identifiers[idKey] = value.id
      }
    }
  })

  return identifiers
}
